import pytest
from unittest import mock
from aiohttp import helpers
import datetime


def test_parse_mimetype_1():
    assert helpers.parse_mimetype('') == ('', '', '', {})


def test_parse_mimetype_2():
    assert helpers.parse_mimetype('*') == ('*', '*', '', {})


def test_parse_mimetype_3():
    assert (helpers.parse_mimetype('application/json') ==
            ('application', 'json', '', {}))


def test_parse_mimetype_4():
    assert (
        helpers.parse_mimetype('application/json;  charset=utf-8') ==
        ('application', 'json', '', {'charset': 'utf-8'}))


def test_parse_mimetype_5():
    assert (
        helpers.parse_mimetype('''application/json; charset=utf-8;''') ==
        ('application', 'json', '', {'charset': 'utf-8'}))


def test_parse_mimetype_6():
    assert(
        helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT="UTF-8"') ==
        ('application', 'json', '', {'charset': 'UTF-8'}))


def test_parse_mimetype_7():
    assert (
        helpers.parse_mimetype('application/rss+xml') ==
        ('application', 'rss', 'xml', {}))


def test_parse_mimetype_8():
    assert (
        helpers.parse_mimetype('text/plain;base64') ==
        ('text', 'plain', '', {'base64': ''}))


def test_basic_auth1():
    # missing password here
    with pytest.raises(ValueError):
        helpers.BasicAuth(None)


def test_basic_auth2():
    with pytest.raises(ValueError):
        helpers.BasicAuth('nkim', None)


def test_basic_auth3():
    auth = helpers.BasicAuth('nkim')
    assert auth.login == 'nkim'
    assert auth.password == ''


def test_basic_auth4():
    auth = helpers.BasicAuth('nkim', 'pwd')
    assert auth.login == 'nkim'
    assert auth.password == 'pwd'
    assert auth.encode() == 'Basic bmtpbTpwd2Q='


def test_invalid_formdata_params():
    with pytest.raises(TypeError):
        helpers.FormData('asdasf')


def test_invalid_formdata_params2():
    with pytest.raises(TypeError):
        helpers.FormData('as')  # 2-char str is not allowed


def test_invalid_formdata_content_type():
    form = helpers.FormData()
    invalid_vals = [0, 0.1, {}, [], b'foo']
    for invalid_val in invalid_vals:
        with pytest.raises(TypeError):
            form.add_field('foo', 'bar', content_type=invalid_val)


def test_invalid_formdata_filename():
    form = helpers.FormData()
    invalid_vals = [0, 0.1, {}, [], b'foo']
    for invalid_val in invalid_vals:
        with pytest.raises(TypeError):
            form.add_field('foo', 'bar', filename=invalid_val)


def test_invalid_formdata_content_transfer_encoding():
    form = helpers.FormData()
    invalid_vals = [0, 0.1, {}, [], b'foo']
    for invalid_val in invalid_vals:
        with pytest.raises(TypeError):
            form.add_field('foo',
                           'bar',
                           content_transfer_encoding=invalid_val)


def test_access_logger_format():
    log_format = '%T {%{SPAM}e} "%{ETag}o" %X {X} %%P'
    mock_logger = mock.Mock()
    access_logger = helpers.AccessLogger(mock_logger, log_format)
    expected = '%s {%s} "%s" %%X {X} %%%s'
    assert expected == access_logger._log_format


@mock.patch("aiohttp.helpers.datetime")
@mock.patch("os.getpid")
def test_access_logger_atoms(mock_getpid, mock_datetime):
    utcnow = datetime.datetime(1843, 1, 1, 0, 0)
    mock_datetime.datetime.utcnow.return_value = utcnow
    mock_getpid.return_value = 42
    log_format = '%a %t %P %l %u %r %s %b %O %T %Tf %D'
    mock_logger = mock.Mock()
    access_logger = helpers.AccessLogger(mock_logger, log_format)
    message = mock.Mock(headers={}, method="GET", path="/path", version=(1, 1))
    environ = {}
    response = mock.Mock(headers={}, output_length=123,
                         body_length=42, status=200)
    transport = mock.Mock()
    transport.get_extra_info.return_value = ("127.0.0.2", 1234)
    access_logger.log(message, environ, response, transport, 3.1415926)
    assert not mock_logger.exception.called
    expected = ('127.0.0.2 [01/Jan/1843:00:00:00 +0000] <42> - - '
                'GET /path HTTP/1.1 200 42 123 3 3.141593 3141593')
    mock_logger.info.assert_called_with(expected)


def test_access_logger_dicts():
    log_format = '%{User-Agent}i %{Content-Length}o %{SPAM}e %{None}i'
    mock_logger = mock.Mock()
    access_logger = helpers.AccessLogger(mock_logger, log_format)
    message = mock.Mock(headers={"USER-AGENT": "Mock/1.0"}, version=(1, 1))
    environ = {"SPAM": "EGGS"}
    response = mock.Mock(headers={"CONTENT-LENGTH": 123})
    transport = mock.Mock()
    transport.get_extra_info.return_value = ("127.0.0.2", 1234)
    access_logger.log(message, environ, response, transport, 0.0)
    assert not mock_logger.error.called
    expected = 'Mock/1.0 123 EGGS -'
    mock_logger.info.assert_called_with(expected)


def test_logger_no_message_and_environ():
    mock_logger = mock.Mock()
    mock_transport = mock.Mock()
    mock_transport.get_extra_info.return_value = ("127.0.0.3", 0)
    access_logger = helpers.AccessLogger(mock_logger, "%r %{FOOBAR}e")
    access_logger.log(None, None, None, mock_transport, 0.0)
    mock_logger.info.assert_called_with("- -")


def test_reify():
    class A:
        @helpers.reify
        def prop(self):
            return 1

    a = A()
    assert 1 == a.prop


def test_reify_class():
    class A:
        @helpers.reify
        def prop(self):
            """Docstring."""
            return 1

    assert isinstance(A.prop, helpers.reify)
    assert 'Docstring.' == A.prop.__doc__


def test_reify_assignment():
    class A:
        @helpers.reify
        def prop(self):
            return 1

    a = A()

    with pytest.raises(AttributeError):
        a.prop = 123


def test_requote_uri_with_unquoted_percents():
    # Ensure we handle unquoted percent signs in redirects.
    bad_uri = 'http://example.com/fiz?buz=%ppicture'
    quoted = 'http://example.com/fiz?buz=%25ppicture'
    assert quoted == helpers.requote_uri(bad_uri)


def test_requote_uri_properly_requotes():
    # Ensure requoting doesn't break expectations.
    quoted = 'http://example.com/fiz?buz=%25ppicture'
    assert quoted == helpers.requote_uri(quoted)

[((3124, 3162), 'unittest.mock.patch', 'mock.patch', (['"""aiohttp.helpers.datetime"""'], {}), "('aiohttp.helpers.datetime')\n", (3134, 3162), False, 'from unittest import mock\n'), ((3164, 3187), 'unittest.mock.patch', 'mock.patch', (['"""os.getpid"""'], {}), "('os.getpid')\n", (3174, 3187), False, 'from unittest import mock\n'), ((1472, 1497), 'aiohttp.helpers.BasicAuth', 'helpers.BasicAuth', (['"""nkim"""'], {}), "('nkim')\n", (1489, 1497), False, 'from aiohttp import helpers\n'), ((1598, 1630), 'aiohttp.helpers.BasicAuth', 'helpers.BasicAuth', (['"""nkim"""', '"""pwd"""'], {}), "('nkim', 'pwd')\n", (1615, 1630), False, 'from aiohttp import helpers\n'), ((2043, 2061), 'aiohttp.helpers.FormData', 'helpers.FormData', ([], {}), '()\n', (2059, 2061), False, 'from aiohttp import helpers\n'), ((2300, 2318), 'aiohttp.helpers.FormData', 'helpers.FormData', ([], {}), '()\n', (2316, 2318), False, 'from aiohttp import helpers\n'), ((2570, 2588), 'aiohttp.helpers.FormData', 'helpers.FormData', ([], {}), '()\n', (2586, 2588), False, 'from aiohttp import helpers\n'), ((2951, 2962), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (2960, 2962), False, 'from unittest import mock\n'), ((2983, 3028), 'aiohttp.helpers.AccessLogger', 'helpers.AccessLogger', (['mock_logger', 'log_format'], {}), '(mock_logger, log_format)\n', (3003, 3028), False, 'from aiohttp import helpers\n'), ((3259, 3294), 'datetime.datetime', 'datetime.datetime', (['(1843)', '(1)', '(1)', '(0)', '(0)'], {}), '(1843, 1, 1, 0, 0)\n', (3276, 3294), False, 'import datetime\n'), ((3459, 3470), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (3468, 3470), False, 'from unittest import mock\n'), ((3491, 3536), 'aiohttp.helpers.AccessLogger', 'helpers.AccessLogger', (['mock_logger', 'log_format'], {}), '(mock_logger, log_format)\n', (3511, 3536), False, 'from aiohttp import helpers\n'), ((3551, 3616), 'unittest.mock.Mock', 'mock.Mock', ([], {'headers': '{}', 'method': '"""GET"""', 'path': '"""/path"""', 'version': '(1, 1)'}), "(headers={}, method='GET', path='/path', version=(1, 1))\n", (3560, 3616), False, 'from unittest import mock\n'), ((3649, 3717), 'unittest.mock.Mock', 'mock.Mock', ([], {'headers': '{}', 'output_length': '(123)', 'body_length': '(42)', 'status': '(200)'}), '(headers={}, output_length=123, body_length=42, status=200)\n', (3658, 3717), False, 'from unittest import mock\n'), ((3759, 3770), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (3768, 3770), False, 'from unittest import mock\n'), ((4259, 4270), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (4268, 4270), False, 'from unittest import mock\n'), ((4291, 4336), 'aiohttp.helpers.AccessLogger', 'helpers.AccessLogger', (['mock_logger', 'log_format'], {}), '(mock_logger, log_format)\n', (4311, 4336), False, 'from aiohttp import helpers\n'), ((4351, 4412), 'unittest.mock.Mock', 'mock.Mock', ([], {'headers': "{'USER-AGENT': 'Mock/1.0'}", 'version': '(1, 1)'}), "(headers={'USER-AGENT': 'Mock/1.0'}, version=(1, 1))\n", (4360, 4412), False, 'from unittest import mock\n'), ((4459, 4501), 'unittest.mock.Mock', 'mock.Mock', ([], {'headers': "{'CONTENT-LENGTH': 123}"}), "(headers={'CONTENT-LENGTH': 123})\n", (4468, 4501), False, 'from unittest import mock\n'), ((4518, 4529), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (4527, 4529), False, 'from unittest import mock\n'), ((4849, 4860), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (4858, 4860), False, 'from unittest import mock\n'), ((4882, 4893), 'unittest.mock.Mock', 'mock.Mock', ([], {}), '()\n', (4891, 4893), False, 'from unittest import mock\n'), ((4980, 5030), 'aiohttp.helpers.AccessLogger', 'helpers.AccessLogger', (['mock_logger', '"""%r %{FOOBAR}e"""'], {}), "(mock_logger, '%r %{FOOBAR}e')\n", (5000, 5030), False, 'from aiohttp import helpers\n'), ((126, 152), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['""""""'], {}), "('')\n", (148, 152), False, 'from aiohttp import helpers\n'), ((215, 242), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""*"""'], {}), "('*')\n", (237, 242), False, 'from aiohttp import helpers\n'), ((308, 350), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""application/json"""'], {}), "('application/json')\n", (330, 350), False, 'from aiohttp import helpers\n'), ((451, 509), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""application/json;  charset=utf-8"""'], {}), "('application/json;  charset=utf-8')\n", (473, 509), False, 'from aiohttp import helpers\n'), ((624, 682), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""application/json; charset=utf-8;"""'], {}), "('application/json; charset=utf-8;')\n", (646, 682), False, 'from aiohttp import helpers\n'), ((800, 858), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""ApPlIcAtIoN/JSON;ChaRseT="UTF-8\\""""'], {}), '(\'ApPlIcAtIoN/JSON;ChaRseT="UTF-8"\')\n', (822, 858), False, 'from aiohttp import helpers\n'), ((973, 1018), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""application/rss+xml"""'], {}), "('application/rss+xml')\n", (995, 1018), False, 'from aiohttp import helpers\n'), ((1117, 1160), 'aiohttp.helpers.parse_mimetype', 'helpers.parse_mimetype', (['"""text/plain;base64"""'], {}), "('text/plain;base64')\n", (1139, 1160), False, 'from aiohttp import helpers\n'), ((1274, 1299), 'pytest.raises', 'pytest.raises', (['ValueError'], {}), '(ValueError)\n', (1287, 1299), False, 'import pytest\n'), ((1309, 1332), 'aiohttp.helpers.BasicAuth', 'helpers.BasicAuth', (['None'], {}), '(None)\n', (1326, 1332), False, 'from aiohttp import helpers\n'), ((1368, 1393), 'pytest.raises', 'pytest.raises', (['ValueError'], {}), '(ValueError)\n', (1381, 1393), False, 'import pytest\n'), ((1403, 1434), 'aiohttp.helpers.BasicAuth', 'helpers.BasicAuth', (['"""nkim"""', 'None'], {}), "('nkim', None)\n", (1420, 1434), False, 'from aiohttp import helpers\n'), ((1793, 1817), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (1806, 1817), False, 'import pytest\n'), ((1827, 1853), 'aiohttp.helpers.FormData', 'helpers.FormData', (['"""asdasf"""'], {}), "('asdasf')\n", (1843, 1853), False, 'from aiohttp import helpers\n'), ((1902, 1926), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (1915, 1926), False, 'import pytest\n'), ((1936, 1958), 'aiohttp.helpers.FormData', 'helpers.FormData', (['"""as"""'], {}), "('as')\n", (1952, 1958), False, 'from aiohttp import helpers\n'), ((5635, 5664), 'pytest.raises', 'pytest.raises', (['AttributeError'], {}), '(AttributeError)\n', (5648, 5664), False, 'import pytest\n'), ((5924, 5952), 'aiohttp.helpers.requote_uri', 'helpers.requote_uri', (['bad_uri'], {}), '(bad_uri)\n', (5943, 5952), False, 'from aiohttp import helpers\n'), ((6123, 6150), 'aiohttp.helpers.requote_uri', 'helpers.requote_uri', (['quoted'], {}), '(quoted)\n', (6142, 6150), False, 'from aiohttp import helpers\n'), ((2156, 2180), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (2169, 2180), False, 'import pytest\n'), ((2413, 2437), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (2426, 2437), False, 'import pytest\n'), ((2683, 2707), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (2696, 2707), False, 'import pytest\n')]