Example #1
0
def test_coroutine_cancelled_waitingforbody(container, transport):
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol = aioweb.protocol.HttpProtocol(container=container,
                                                loop=unittest.mock.Mock())
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # Invoke the worker loop. The loop should then wait on the queue
    #
    coro.send(None)
    #
    # Simulate data to make sure that the protocol creates a parser
    #
    request = b'''GET / HTTP/1.1
Host: example.com
Content-Length: 3

X'''.replace(b'\n', b'\r\n')
    protocol.data_received(request)
    #
    # Now we should have written something into the queue. If we now
    # resume the coroutine, it should proceed into our handler and wait
    # for the body
    #
    future = coro.send(None)
    #
    # Throw a CancelledError
    #
    raised = False
    try:
        coro.throw(asyncio.exceptions.CancelledError())
    except asyncio.exceptions.CancelledError:
        raised = True
    assert raised
Example #2
0
def test_handler_returntypemismatch(container, transport):
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol = aioweb.protocol.HttpProtocol(container=container,
                                                loop=unittest.mock.Mock())
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # Ask the handler to return None
    #
    container._no_response = True
    #
    # Simulate data
    #
    request = b'''GET / HTTP/1.1
Host: example.com
Content-Length: 3

XYZ'''.replace(b'\n', b'\r\n')
    protocol.data_received(request)
    #
    # We now have added a request object to the queue. Invoke the
    # worker loop which should proceed right into our handler
    #
    coro.send(None)
    assert container._request is not None
Example #3
0
def test_transport_fails(container, transport):
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol = aioweb.protocol.HttpProtocol(container=container,
                                                loop=unittest.mock.Mock())
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # Ask the transport to raise an error
    #
    transport.fail_next()
    #
    # Simulate data to make sure that the protocol creates a parser
    #
    request = b'''GET / HTTP/1.1
Host: example.com
Content-Length: 3

XYZ'''.replace(b'\n', b'\r\n')
    protocol.data_received(request)
    #
    # We now have added a request object to the queue. Invoke the
    # worker loop which should proceed right into our handler but
    # ignore the error
    #
    coro.send(None)
    assert container._request is not None
Example #4
0
def test_transport_is_closing(transport):
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol = aioweb.protocol.HttpProtocol(container=None,
                                                loop=unittest.mock.Mock())
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # Close transport
    #
    transport.close()
    #
    # Simulate data to make sure that the protocol creates a parser
    #
    request = b'''GET / HTTP/1.1
Host: example.com
Content-Length: 3

XYZ'''.replace(b'\n', b'\r\n')
    protocol.data_received(request)
    #
    # We now have added a request object to the queue. Invoke the
    # worker loop. This should return as the transport is already closed
    #
    raised = False
    try:
        coro.send(None)
    except StopIteration:
        raised = True
    assert raised
Example #5
0
def test_full_request_lifecycle_handler_baseexception(transport, container):

    protocol = aioweb.protocol.HttpProtocol(container=container)
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # When we now start our coroutine, it should suspend and wait
    #
    coro.send(None)
    #
    # Feed some data
    #
    request = b'''GET / HTTP/1.1
Host: example.com
Content-Length: 3

XYZ'''
    protocol.data_received(request.replace(b'\n', b'\r\n'))
    #
    # When we now call send on the coroutine to simulate that the event
    # loop reschedules it, it should invoke our handler function. We instruct
    # the dummy handler to raise an exception
    #
    container.set_exception(BaseException())
    coro.send(None)
    #
    # Make sure that the handler has been called
    #
    assert container._request is not None
    #
    # Verify some attributes of the request object
    #
    request = container._request
    assert isinstance(request, aioweb.request.Request)
    headers = request.headers()
    assert headers is not None
    assert isinstance(headers, dict)
    assert "Host" in headers
    assert headers["Host"] == b"example.com"
    assert request.http_version() == "1.1"
    #
    # Verify that we have written back something into the transport
    #
    assert len(transport._data) > 0
    #
    # Now let us try to parse the response data
    #
    parser_helper = ParserHelper()
    parser = httptools.HttpResponseParser(parser_helper)
    parser.feed_data(transport._data)
    #
    # If we get to this point, this is a valid HTTP response
    #
    assert parser.get_status_code() == 500
    #
    # Finally check that the transport is not closed
    #
    assert not transport._is_closing
Example #6
0
def test_on_headers_complete():
    with unittest.mock.patch(
            "aioweb.protocol.httptools.HttpRequestParser") as mock:
        with unittest.mock.patch("aioweb.protocol.asyncio.Queue") as Queue:
            protocol = aioweb.protocol.HttpProtocol(container=None,
                                                    loop=unittest.mock.Mock())
            #
            # Simulate data to make sure that the protocol creates a parser
            #
            protocol.data_received(b"X")
            protocol.on_header(b"Host", b"127.0.0.1")
            protocol.on_headers_complete()
            queue = Queue.return_value
    #
    # Verify the state
    #
    assert protocol.get_state() == aioweb.protocol.ConnectionState.BODY
    #
    # Check that we have added something to the queue
    #
    queue.put_nowait.assert_called()
Example #7
0
def test_full_request_lifecycle_http11(transport, container):

    protocol = aioweb.protocol.HttpProtocol(container=container)
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # When we now start our coroutine, it should suspend and wait
    #
    coro.send(None)
    #
    # Feed some data and complete the headers
    #
    request = b'''GET / HTTP/1.1
Host: example.com
Content-Length: 3

X'''
    protocol.data_received(request.replace(b'\n', b'\r\n'))
    assert protocol.get_state() == aioweb.protocol.ConnectionState.BODY
    #
    # When we now call send on the coroutine to simulate that the event
    # loop reschedules it, it should invoke our handler function
    #
    coro.send(None)
    #
    # Make sure that the handler has been called
    #
    assert container._request is not None
    #
    # Verify some attributes of the request object
    #
    request = container._request
    assert isinstance(request, aioweb.request.Request)
    headers = request.headers()
    assert headers is not None
    assert isinstance(headers, dict)
    assert "Host" in headers
    assert headers["Host"] == b"example.com"
    assert request.http_version() == "1.1"
    #
    # Get the future to wait for completion of the body
    #
    future = request.body().send(None)
    #
    # In our case, the body should not be complete yet
    #
    assert not future.done()
    #
    # complete it
    #
    request = b'YZ'
    protocol.data_received(request)
    assert protocol.get_state() == aioweb.protocol.ConnectionState.PENDING
    #
    # At this point, our future should be complete
    #
    body = future.result()
    assert body == b"XYZ"
    #
    # Verify that we have written back something into the transport
    #
    assert len(transport._data) > 0
    #
    # Now let us try to parse the response data
    #
    parser_helper = ParserHelper()
    parser = httptools.HttpResponseParser(parser_helper)
    parser.feed_data(transport._data)
    #
    # If we get to this point, this is a valid HTTP response
    #
    assert parser.get_status_code() == 200
    assert parser_helper._body == b"abc"
    #
    # Finally check that the transport is not closed
    #
    assert not transport._is_closing
Example #8
0
def test_pipelining(transport, container):

    protocol = aioweb.protocol.HttpProtocol(container=container)
    with unittest.mock.patch("asyncio.create_task") as mock:
        protocol.connection_made(transport)
        coro = mock.call_args.args[0]
    #
    # Feed a first complete record
    #
    request = b'''GET / HTTP/1.1
Host: example1.com
Content-Length: 3

XYZ'''
    protocol.data_received(request.replace(b'\n', b'\r\n'))
    assert protocol.get_state() == aioweb.protocol.ConnectionState.PENDING
    #
    # Now feed a second record
    #
    request = b'''GET / HTTP/1.1
Host: example2.com
Content-Length: 3

123'''
    protocol.data_received(request.replace(b'\n', b'\r\n'))
    assert protocol.get_state() == aioweb.protocol.ConnectionState.PENDING
    #
    # Now simulate the event loop and run the coroutine for the first time
    #
    coro.send(None)
    #
    # This should again block on the queue, but only after the two records
    # have been received. Thus we should have invoked our handler twice
    #
    assert container._request_count == 2
    #
    # Get the first request
    #
    request = container._requests[0]
    assert isinstance(request, aioweb.request.Request)
    #
    # this should be the first request
    #
    assert request.headers()['Host'] == b"example1.com"
    #
    # check content of first response
    #
    assert container._replies[0] == b"XYZ"
    #
    # Now check the second request
    #
    request = container._requests[1]
    assert isinstance(request, aioweb.request.Request)
    assert request.headers()['Host'] == b"example2.com"
    assert container._replies[1] == b"123"
    #
    # Now we check that two responses have been written into
    # the transport. We get them from the transport and send them
    # through our parser
    #
    parser_helper = ParserHelper()
    parser = httptools.HttpResponseParser(parser_helper)
    parser.feed_data(transport._messages[0])
    assert parser.get_status_code() == 200
    assert bytes(parser_helper._body) == b"XYZ"

    parser_helper = ParserHelper()
    parser = httptools.HttpResponseParser(parser_helper)
    parser.feed_data(transport._messages[1])
    assert parser.get_status_code() == 200
    assert bytes(parser_helper._body) == b"123"