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, 'aiospamc.responses.Response', 'Response', ([], {}), False, 'from aiospamc.responses import Response\n'), (64, 'pytest.raises', 'pytest.raises', (['UsageException'], {}), False, 'import pytest\n'), (73, 'pytest.raises', 'pytest.raises', (['DataErrorException'], {}), False, 'import pytest\n'), (82, 'pytest.raises', 'pytest.raises', (['NoInputException'], {}), False, 'import pytest\n'), (91, 'pytest.raises', 'pytest.raises', (['NoUserException'], {}), False, 'import pytest\n'), (100, 'pytest.raises', 'pytest.raises', (['NoHostException'], {}), False, 'import pytest\n'), (109, 'pytest.raises', 'pytest.raises', (['UnavailableException'], {}), False, 'import pytest\n'), (118, 'pytest.raises', 'pytest.raises', (['InternalSoftwareException'], {}), False, 'import pytest\n'), (127, 'pytest.raises', 'pytest.raises', (['OSErrorException'], {}), False, 'import pytest\n'), (136, 'pytest.raises', 'pytest.raises', (['OSFileException'], {}), False, 'import pytest\n'), (145, 'pytest.raises', 'pytest.raises', (['CantCreateException'], {}), False, 'import pytest\n'), (154, 'pytest.raises', 'pytest.raises', (['IOErrorException'], {}), False, 'import pytest\n'), (163, 'pytest.raises', 'pytest.raises', (['TemporaryFailureException'], {}), False, 'import pytest\n'), (172, 'pytest.raises', 'pytest.raises', (['ProtocolException'], {}), False, 'import pytest\n'), (181, 'pytest.raises', 'pytest.raises', (['NoPermissionException'], {}), False, 'import pytest\n'), (188, 'pytest.raises', 'pytest.raises', (['ConfigException'], {}), False, 'import pytest\n'), (197, 'pytest.raises', 'pytest.raises', (['ServerTimeoutException'], {}), False, 'import pytest\n'), (206, 'pytest.raises', 'pytest.raises', (['ResponseException'], {}), False, 'import pytest\n')]