import pytest

from aiospamc.client import Client
from aiospamc.exceptions import (
    BadResponse,
    UsageException,
    DataErrorException,
    NoInputException,
    NoUserException,
    NoHostException,
    UnavailableException,
    InternalSoftwareException,
    OSErrorException,
    OSFileException,
    CantCreateException,
    IOErrorException,
    TemporaryFailureException,
    ProtocolException,
    NoPermissionException,
    ConfigException,
    ServerTimeoutException,
    ResponseException,
)
from aiospamc.responses import Response


async def test_request_sent_to_connection(mock_client_dependency, mocker, hostname):
    mock_req = mocker.MagicMock()
    await mock_client_dependency.request(mock_req, host=hostname)

    assert (
        bytes(mock_req)
        == mock_client_dependency.connection_factory().request.await_args[0][0]
    )


async def test_request_response_sent_to_parser(
    mock_client_dependency, mocker, hostname
):
    mock_req = mocker.MagicMock()
    connection = mock_client_dependency.connection_factory()
    parser = mock_client_dependency.parser_factory()
    mocker.spy(parser, "parse")
    await mock_client_dependency.request(mock_req, host=hostname)

    response = connection.request.return_value
    assert response == parser.parse.call_args[0][0]


async def test_request_returns_response(mock_client_dependency, mocker, hostname):
    mock_req = mocker.MagicMock()
    connection = mock_client_dependency.connection_factory()
    parser = mock_client_dependency.parser_factory()
    parse_spy = mocker.spy(parser, "parse")
    result = await mock_client_dependency.request(mock_req, host=hostname)
    expected = Response(**parse_spy.spy_return)

    assert expected == result


async def test_request_raises_usage(mock_client_response, mocker, ex_usage, hostname):
    mock_client = mock_client_response(ex_usage)

    with pytest.raises(UsageException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_data_err(
    mock_client_response, mocker, ex_data_err, hostname
):
    mock_client = mock_client_response(ex_data_err)

    with pytest.raises(DataErrorException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_no_input(
    mock_client_response, mocker, ex_no_input, hostname
):
    mock_client = mock_client_response(ex_no_input)

    with pytest.raises(NoInputException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_no_user(
    mock_client_response, mocker, ex_no_user, hostname
):
    mock_client = mock_client_response(ex_no_user)

    with pytest.raises(NoUserException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_no_host(
    mock_client_response, mocker, ex_no_host, hostname
):
    mock_client = mock_client_response(ex_no_host)

    with pytest.raises(NoHostException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_unavailable(
    mock_client_response, mocker, ex_unavailable, hostname
):
    mock_client = mock_client_response(ex_unavailable)

    with pytest.raises(UnavailableException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_software(
    mock_client_response, mocker, ex_software, hostname
):
    mock_client = mock_client_response(ex_software)

    with pytest.raises(InternalSoftwareException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_os_error(
    mock_client_response, mocker, ex_os_err, hostname
):
    mock_client = mock_client_response(ex_os_err)

    with pytest.raises(OSErrorException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_os_file(
    mock_client_response, mocker, ex_os_file, hostname
):
    mock_client = mock_client_response(ex_os_file)

    with pytest.raises(OSFileException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_cant_create(
    mock_client_response, mocker, ex_cant_create, hostname
):
    mock_client = mock_client_response(ex_cant_create)

    with pytest.raises(CantCreateException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_io_error(
    mock_client_response, mocker, ex_io_err, hostname
):
    mock_client = mock_client_response(ex_io_err)

    with pytest.raises(IOErrorException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_temporary_failure(
    mock_client_response, mocker, ex_temp_fail, hostname
):
    mock_client = mock_client_response(ex_temp_fail)

    with pytest.raises(TemporaryFailureException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_protocol(
    mock_client_response, mocker, ex_protocol, hostname
):
    mock_client = mock_client_response(ex_protocol)

    with pytest.raises(ProtocolException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_no_permission(
    mock_client_response, mocker, ex_no_perm, hostname
):
    mock_client = mock_client_response(ex_no_perm)

    with pytest.raises(NoPermissionException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_config(mock_client_response, mocker, ex_config, hostname):
    mock_client = mock_client_response(ex_config)

    with pytest.raises(ConfigException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_timeout(
    mock_client_response, mocker, ex_timeout, hostname
):
    mock_client = mock_client_response(ex_timeout)

    with pytest.raises(ServerTimeoutException):
        await mock_client.request(mocker.MagicMock(), host=hostname)


async def test_request_raises_undefined(
    mock_client_response, mocker, ex_undefined, hostname
):
    mock_client = mock_client_response(ex_undefined)

    with pytest.raises(ResponseException):
        await mock_client.request(mocker.MagicMock(), host=hostname)

[((56, 15, 56, 47), 'aiospamc.responses.Response', 'Response', ({}, {}), '(**parse_spy.spy_return)', False, 'from aiospamc.responses import Response\n'), ((64, 9, 64, 38), 'pytest.raises', 'pytest.raises', ({(64, 23, 64, 37): 'UsageException'}, {}), '(UsageException)', False, 'import pytest\n'), ((73, 9, 73, 42), 'pytest.raises', 'pytest.raises', ({(73, 23, 73, 41): 'DataErrorException'}, {}), '(DataErrorException)', False, 'import pytest\n'), ((82, 9, 82, 40), 'pytest.raises', 'pytest.raises', ({(82, 23, 82, 39): 'NoInputException'}, {}), '(NoInputException)', False, 'import pytest\n'), ((91, 9, 91, 39), 'pytest.raises', 'pytest.raises', ({(91, 23, 91, 38): 'NoUserException'}, {}), '(NoUserException)', False, 'import pytest\n'), ((100, 9, 100, 39), 'pytest.raises', 'pytest.raises', ({(100, 23, 100, 38): 'NoHostException'}, {}), '(NoHostException)', False, 'import pytest\n'), ((109, 9, 109, 44), 'pytest.raises', 'pytest.raises', ({(109, 23, 109, 43): 'UnavailableException'}, {}), '(UnavailableException)', False, 'import pytest\n'), ((118, 9, 118, 49), 'pytest.raises', 'pytest.raises', ({(118, 23, 118, 48): 'InternalSoftwareException'}, {}), '(InternalSoftwareException)', False, 'import pytest\n'), ((127, 9, 127, 40), 'pytest.raises', 'pytest.raises', ({(127, 23, 127, 39): 'OSErrorException'}, {}), '(OSErrorException)', False, 'import pytest\n'), ((136, 9, 136, 39), 'pytest.raises', 'pytest.raises', ({(136, 23, 136, 38): 'OSFileException'}, {}), '(OSFileException)', False, 'import pytest\n'), ((145, 9, 145, 43), 'pytest.raises', 'pytest.raises', ({(145, 23, 145, 42): 'CantCreateException'}, {}), '(CantCreateException)', False, 'import pytest\n'), ((154, 9, 154, 40), 'pytest.raises', 'pytest.raises', ({(154, 23, 154, 39): 'IOErrorException'}, {}), '(IOErrorException)', False, 'import pytest\n'), ((163, 9, 163, 49), 'pytest.raises', 'pytest.raises', ({(163, 23, 163, 48): 'TemporaryFailureException'}, {}), '(TemporaryFailureException)', False, 'import pytest\n'), ((172, 9, 172, 41), 'pytest.raises', 'pytest.raises', ({(172, 23, 172, 40): 'ProtocolException'}, {}), '(ProtocolException)', False, 'import pytest\n'), ((181, 9, 181, 45), 'pytest.raises', 'pytest.raises', ({(181, 23, 181, 44): 'NoPermissionException'}, {}), '(NoPermissionException)', False, 'import pytest\n'), ((188, 9, 188, 39), 'pytest.raises', 'pytest.raises', ({(188, 23, 188, 38): 'ConfigException'}, {}), '(ConfigException)', False, 'import pytest\n'), ((197, 9, 197, 46), 'pytest.raises', 'pytest.raises', ({(197, 23, 197, 45): 'ServerTimeoutException'}, {}), '(ServerTimeoutException)', False, 'import pytest\n'), ((206, 9, 206, 41), 'pytest.raises', 'pytest.raises', ({(206, 23, 206, 40): 'ResponseException'}, {}), '(ResponseException)', False, 'import pytest\n')]