import pytest

from .._headers import *

def test_normalize_and_validate():
    assert normalize_and_validate([("foo", "bar")]) == [(b"foo", b"bar")]
    assert normalize_and_validate([(b"foo", b"bar")]) == [(b"foo", b"bar")]

    # no leading/trailing whitespace in names
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([(b"foo ", "bar")])
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([(b" foo", "bar")])

    # no weird characters in names
    with pytest.raises(LocalProtocolError) as excinfo:
        normalize_and_validate([(b"foo bar", b"baz")])
    assert "foo bar" in str(excinfo.value)
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([(b"foo\x00bar", b"baz")])

    # no return or NUL characters in values
    with pytest.raises(LocalProtocolError) as excinfo:
        normalize_and_validate([("foo", "bar\rbaz")])
    assert "bar\\rbaz" in str(excinfo.value)
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([("foo", "bar\nbaz")])
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([("foo", "bar\x00baz")])
    # no leading/trailing whitespace
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([("foo", "  barbaz  ")])

    # content-length
    assert (normalize_and_validate([("Content-Length", "1")])
            == [(b"content-length", b"1")])
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([("Content-Length", "asdf")])
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([("Content-Length", "1x")])
    with pytest.raises(LocalProtocolError):
        normalize_and_validate([
            ("Content-Length", "1"),
            ("Content-Length", "2"),
        ])

    # transfer-encoding
    assert (normalize_and_validate([("Transfer-Encoding", "chunked")])
            == [(b"transfer-encoding", b"chunked")])
    assert (normalize_and_validate([("Transfer-Encoding", "cHuNkEd")])
            == [(b"transfer-encoding", b"chunked")])
    with pytest.raises(LocalProtocolError) as excinfo:
        normalize_and_validate([("Transfer-Encoding", "gzip")])
    assert excinfo.value.error_status_hint == 501  # Not Implemented
    with pytest.raises(LocalProtocolError) as excinfo:
        normalize_and_validate([
            ("Transfer-Encoding", "chunked"),
            ("Transfer-Encoding", "gzip"),
        ])
    assert excinfo.value.error_status_hint == 501  # Not Implemented

def test_get_set_comma_header():
    headers = normalize_and_validate([
        ("Connection", "close"),
        ("whatever", "something"),
        ("connectiON", "fOo,, , BAR"),
    ])

    assert get_comma_header(headers, b"connection") == [
        b"close", b"foo", b"bar"]

    set_comma_header(headers, b"newthing", ["a", "b"])

    with pytest.raises(LocalProtocolError):
        set_comma_header(headers, b"newthing", ["  a", "b"])

    assert headers == [
        (b"connection", b"close"),
        (b"whatever", b"something"),
        (b"connection", b"fOo,, , BAR"),
        (b"newthing", b"a"),
        (b"newthing", b"b"),
    ]

    set_comma_header(headers, b"whatever", ["different thing"])

    assert headers == [
        (b"connection", b"close"),
        (b"connection", b"fOo,, , BAR"),
        (b"newthing", b"a"),
        (b"newthing", b"b"),
        (b"whatever", b"different thing"),
    ]

def test_has_100_continue():
    from .._events import Request

    assert has_expect_100_continue(Request(
        method="GET",
        target="/",
        headers=[("Host", "example.com"), ("Expect", "100-continue")]))
    assert not has_expect_100_continue(Request(
        method="GET",
        target="/",
        headers=[("Host", "example.com")]))
    # Case insensitive
    assert has_expect_100_continue(Request(
        method="GET",
        target="/",
        headers=[("Host", "example.com"), ("Expect", "100-Continue")]))
    # Doesn't work in HTTP/1.0
    assert not has_expect_100_continue(Request(
        method="GET",
        target="/",
        headers=[("Host", "example.com"), ("Expect", "100-continue")],
        http_version="1.0"))
