class TestHandshake(testcases.ASGIWebSocketTestCase): """ Tests for the WebSocket handshake """ def test_minimal(self): message = WebSocketConnection().connect() self.assert_valid_websocket_connect_message(message) @given( path=http_strategies.http_path(), params=http_strategies.query_params(), headers=http_strategies.headers(), ) def test_connection(self, path, params, headers): message = WebSocketConnection().connect(path, params, headers) self.assert_valid_websocket_connect_message(message, path, params, headers)
class TestHTTPRequestSpec(testcases.ASGIHTTPTestCase): """ Tests which try to pour the HTTP request section of the ASGI spec into code. The heavy lifting is done by the assert_valid_http_request_message function, the tests mostly serve to wire up hypothesis so that it exercise it's power to find edge cases. """ def test_minimal_request(self): """ Smallest viable example. Mostly verifies that our request building works. """ request_method, request_path = 'GET', '/' message = message_for_request(request_method, request_path) self.assert_valid_http_request_message(message, request_method, request_path) @given(request_path=http_strategies.http_path(), request_params=http_strategies.query_params()) def test_get_request(self, request_path, request_params): """ Tests a typical HTTP GET request, with a path and query parameters """ request_method = 'GET' message = message_for_request(request_method, request_path, request_params) self.assert_valid_http_request_message(message, request_method, request_path, request_params=request_params) @given(request_path=http_strategies.http_path(), request_body=http_strategies.http_body()) def test_post_request(self, request_path, request_body): """ Tests a typical POST request, submitting some data in a body. """ request_method = 'POST' headers = [content_length_header(request_body)] message = message_for_request(request_method, request_path, headers=headers, body=request_body) self.assert_valid_http_request_message(message, request_method, request_path, request_headers=headers, request_body=request_body) @given(request_headers=http_strategies.headers()) def test_headers(self, request_headers): """ Tests that HTTP header fields are handled as specified """ request_method, request_path = 'OPTIONS', '/te st-à/' message = message_for_request(request_method, request_path, headers=request_headers) self.assert_valid_http_request_message(message, request_method, request_path, request_headers=request_headers) @given(request_headers=http_strategies.headers()) def test_duplicate_headers(self, request_headers): """ Tests that duplicate header values are preserved """ assume(len(request_headers) >= 2) # Set all header field names to the same value header_name = request_headers[0][0] duplicated_headers = [(header_name, header[1]) for header in request_headers] request_method, request_path = 'OPTIONS', '/te st-à/' message = message_for_request(request_method, request_path, headers=duplicated_headers) self.assert_valid_http_request_message( message, request_method, request_path, request_headers=duplicated_headers) @given( request_method=http_strategies.http_method(), request_path=http_strategies.http_path(), request_params=http_strategies.query_params(), request_headers=http_strategies.headers(), request_body=http_strategies.http_body(), ) # This test is slow enough that on Travis, hypothesis sometimes complains. def test_kitchen_sink(self, request_method, request_path, request_params, request_headers, request_body): """ Throw everything at channels that we dare. The idea is that if a combination of method/path/headers/body would break the spec, hypothesis will eventually find it. """ request_headers.append(content_length_header(request_body)) message = message_for_request(request_method, request_path, request_params, request_headers, request_body) self.assert_valid_http_request_message(message, request_method, request_path, request_params, request_headers, request_body) def test_headers_are_lowercased_and_stripped(self): request_method, request_path = 'GET', '/' headers = [('MYCUSTOMHEADER', ' foobar ')] message = message_for_request(request_method, request_path, headers=headers) self.assert_valid_http_request_message(message, request_method, request_path, request_headers=headers) # Note that Daphne returns a list of tuples here, which is fine, because the spec # asks to treat them interchangeably. assert message['headers'] == [(b'mycustomheader', b'foobar')] @given(daphne_path=http_strategies.http_path()) def test_root_path_header(self, daphne_path): """ Tests root_path handling. """ request_method, request_path = 'GET', '/' # Daphne-Root-Path must be URL encoded when submitting as HTTP header field headers = [('Daphne-Root-Path', parse.quote(daphne_path.encode('utf8')))] message = message_for_request(request_method, request_path, headers=headers) # Daphne-Root-Path is not included in the returned 'headers' section. So we expect # empty headers. expected_headers = [] self.assert_valid_http_request_message( message, request_method, request_path, request_headers=expected_headers) # And what we're looking for, root_path being set. assert message['root_path'] == daphne_path