diff --git a/tests/asyncio/test_client.py b/tests/asyncio/test_client.py index 293e41a2..2c162cc0 100644 --- a/tests/asyncio/test_client.py +++ b/tests/asyncio/test_client.py @@ -448,10 +448,11 @@ def remove_accept_header(self, request, response): with self.assertRaises(InvalidHandshake) as raised: async with connect(get_uri(server) + "/no-op", close_timeout=MS): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "missing Sec-WebSocket-Accept header", - ) + + self.assertEqual( + str(raised.exception), + "missing Sec-WebSocket-Accept header", + ) async def test_timeout_during_handshake(self): """Client times out before receiving handshake response from server.""" @@ -461,10 +462,11 @@ async def test_timeout_during_handshake(self): with self.assertRaises(TimeoutError) as raised: async with connect(f"ws://{host}:{port}", open_timeout=MS): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "timed out during opening handshake", - ) + + self.assertEqual( + str(raised.exception), + "timed out during opening handshake", + ) async def test_connection_closed_during_handshake(self): """Client reads EOF before receiving handshake response from server.""" @@ -476,15 +478,16 @@ def close_connection(self, request): with self.assertRaises(InvalidMessage) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "did not receive a valid HTTP response", - ) - self.assertIsInstance(raised.exception.__cause__, EOFError) - self.assertEqual( - str(raised.exception.__cause__), - "connection closed while reading HTTP status line", - ) + + self.assertEqual( + str(raised.exception), + "did not receive a valid HTTP response", + ) + self.assertIsInstance(raised.exception.__cause__, EOFError) + self.assertEqual( + str(raised.exception.__cause__), + "connection closed while reading HTTP status line", + ) async def test_http_response(self): """Client reads HTTP response.""" @@ -562,16 +565,16 @@ async def junk(reader, writer): with self.assertRaises(InvalidMessage) as raised: async with connect(f"ws://{host}:{port}"): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "did not receive a valid HTTP response", - ) - self.assertIsInstance(raised.exception.__cause__, ValueError) - self.assertEqual( - str(raised.exception.__cause__), - "unsupported protocol; expected HTTP/1.1: " - "220 smtp.invalid ESMTP Postfix", - ) + + self.assertEqual( + str(raised.exception), + "did not receive a valid HTTP response", + ) + self.assertIsInstance(raised.exception.__cause__, ValueError) + self.assertEqual( + str(raised.exception.__cause__), + "unsupported protocol; expected HTTP/1.1: 220 smtp.invalid ESMTP Postfix", + ) class SecureClientTests(unittest.IsolatedAsyncioTestCase): @@ -619,10 +622,11 @@ async def test_reject_invalid_server_certificate(self): # The test certificate is self-signed. async with connect(get_uri(server)): self.fail("did not raise") - self.assertIn( - "self signed certificate", - str(raised.exception).replace("-", " "), - ) + + self.assertIn( + "self signed certificate", + str(raised.exception).replace("-", " "), + ) async def test_reject_invalid_server_hostname(self): """Client rejects certificate where server hostname doesn't match.""" @@ -633,10 +637,11 @@ async def test_reject_invalid_server_hostname(self): get_uri(server), ssl=CLIENT_CONTEXT, server_hostname="invalid" ): self.fail("did not raise") - self.assertIn( - "Hostname mismatch", - str(raised.exception), - ) + + self.assertIn( + "Hostname mismatch", + str(raised.exception), + ) async def test_cross_origin_redirect(self): """Client follows redirect to a secure URI on a different origin.""" @@ -717,6 +722,7 @@ async def test_authenticated_socks_proxy_error(self): self.fail("did not raise") finally: self.proxy_options.update(proxyauth=None) + self.assertEqual( str(raised.exception), "failed to connect to SOCKS proxy", @@ -745,6 +751,7 @@ async def test_socks_proxy_connection_timeout(self): with self.assertRaises(TimeoutError) as raised: async with connect("ws://example.com/", open_timeout=MS): self.fail("did not raise") + self.assertEqual( str(raised.exception), "timed out during opening handshake", @@ -817,6 +824,7 @@ async def test_authenticated_http_proxy_error(self): self.fail("did not raise") finally: self.proxy_options.update(proxyauth=None) + self.assertEqual( str(raised.exception), "proxy rejected connection: HTTP 407", @@ -851,6 +859,7 @@ async def test_http_proxy_protocol_error(self): self.fail("did not raise") finally: self.proxy_options.update(break_http_connect=False) + self.assertEqual( str(raised.exception), "did not receive a valid HTTP response from proxy", @@ -867,6 +876,7 @@ async def test_http_proxy_connection_error(self): self.fail("did not raise") finally: self.proxy_options.update(close_http_connect=False) + self.assertEqual( str(raised.exception), "did not receive a valid HTTP response from proxy", @@ -891,6 +901,7 @@ async def test_http_proxy_connection_timeout(self): with self.assertRaises(TimeoutError) as raised: async with connect("ws://example.com/", open_timeout=MS): self.fail("did not raise") + self.assertEqual( str(raised.exception), "timed out during opening handshake", @@ -948,6 +959,7 @@ async def test_https_proxy_invalid_proxy_certificate(self): # The proxy certificate isn't trusted. async with connect("wss://example.com/"): self.fail("did not raise") + self.assertIn( "unable to get local issuer certificate", str(raised.exception), @@ -961,6 +973,7 @@ async def test_https_proxy_invalid_server_certificate(self): # The test certificate is self-signed. async with connect(get_uri(server), proxy_ssl=self.proxy_context): self.fail("did not raise") + self.assertIn( "self signed certificate", str(raised.exception).replace("-", " "), @@ -1066,6 +1079,7 @@ async def test_ssl_without_secure_uri(self): """Client rejects ssl when URI isn't secure.""" with self.assertRaises(ValueError) as raised: await connect("ws://localhost/", ssl=CLIENT_CONTEXT) + self.assertEqual( str(raised.exception), "ssl argument is incompatible with a ws:// URI", @@ -1075,6 +1089,7 @@ async def test_secure_uri_without_ssl(self): """Client rejects ssl=None when URI is secure.""" with self.assertRaises(ValueError) as raised: await connect("wss://localhost/", ssl=None) + self.assertEqual( str(raised.exception), "ssl=None is incompatible with a wss:// URI", @@ -1088,6 +1103,7 @@ async def test_proxy_ssl_without_https_proxy(self): proxy="http://localhost:8080", proxy_ssl=True, ) + self.assertEqual( str(raised.exception), "proxy_ssl argument is incompatible with an http:// proxy", @@ -1101,6 +1117,7 @@ async def test_https_proxy_without_proxy_ssl(self): proxy="https://localhost:8080", proxy_ssl=None, ) + self.assertEqual( str(raised.exception), "proxy_ssl=None is incompatible with an https:// proxy", @@ -1111,6 +1128,7 @@ async def test_unsupported_proxy(self): with self.assertRaises(InvalidProxy) as raised: async with connect("ws://example.com/", proxy="other://localhost:51080"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "other://localhost:51080 isn't a valid proxy: scheme other isn't supported", @@ -1120,6 +1138,7 @@ async def test_unix_without_path_or_sock(self): """Unix client requires path when sock isn't provided.""" with self.assertRaises(ValueError) as raised: await unix_connect() + self.assertEqual( str(raised.exception), "no path and sock were specified", @@ -1131,6 +1150,7 @@ async def test_unix_with_path_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: await unix_connect(path="/", sock=sock) + self.assertEqual( str(raised.exception), "path and sock can not be specified at the same time", @@ -1140,6 +1160,7 @@ async def test_invalid_subprotocol(self): """Client rejects single value of subprotocols.""" with self.assertRaises(TypeError) as raised: await connect("ws://localhost/", subprotocols="chat") + self.assertEqual( str(raised.exception), "subprotocols must be a list, not a str", @@ -1149,6 +1170,7 @@ async def test_unsupported_compression(self): """Client rejects incorrect value of compression.""" with self.assertRaises(ValueError) as raised: await connect("ws://localhost/", compression=False) + self.assertEqual( str(raised.exception), "unsupported compression: False", @@ -1162,6 +1184,7 @@ async def test_reentrancy(self): with self.assertRaises(RuntimeError) as raised: async with connecter: self.fail("did not raise") + self.assertEqual( str(raised.exception), "connect() isn't reentrant", diff --git a/tests/asyncio/test_connection.py b/tests/asyncio/test_connection.py index 25750c1f..9de64b62 100644 --- a/tests/asyncio/test_connection.py +++ b/tests/asyncio/test_connection.py @@ -228,6 +228,7 @@ async def test_recv_during_recv(self): await self.connection.recv() finally: recv_task.cancel() + self.assertEqual( str(raised.exception), "cannot call recv while another coroutine " @@ -245,6 +246,7 @@ async def test_recv_during_recv_streaming(self): await self.connection.recv() finally: recv_streaming_task.cancel() + self.assertEqual( str(raised.exception), "cannot call recv while another coroutine " @@ -367,6 +369,7 @@ async def test_recv_streaming_during_recv(self): self.fail("did not raise") finally: recv_task.cancel() + self.assertEqual( str(raised.exception), "cannot call recv_streaming while another coroutine " @@ -385,6 +388,7 @@ async def test_recv_streaming_during_recv_streaming(self): self.fail("did not raise") finally: recv_streaming_task.cancel() + self.assertEqual( str(raised.exception), "cannot call recv_streaming while another coroutine " @@ -1006,6 +1010,7 @@ async def test_ping_duplicate_payload(self): with self.assertRaises(ConcurrencyError) as raised: await self.connection.ping("idem") + self.assertEqual( str(raised.exception), "already waiting for a pong with the same data", diff --git a/tests/asyncio/test_router.py b/tests/asyncio/test_router.py index 5c0ea05f..7070dc77 100644 --- a/tests/asyncio/test_router.py +++ b/tests/asyncio/test_router.py @@ -105,6 +105,7 @@ async def test_not_found(self): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server) + "/n"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 404", @@ -146,6 +147,7 @@ def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server) + "/"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 403", @@ -163,6 +165,7 @@ async def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server) + "/"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 403", diff --git a/tests/asyncio/test_server.py b/tests/asyncio/test_server.py index 05574a3f..f8a4aed9 100644 --- a/tests/asyncio/test_server.py +++ b/tests/asyncio/test_server.py @@ -48,10 +48,11 @@ async def test_connection_handler_returns(self): async with connect(get_uri(server) + "/no-op") as client: with self.assertRaises(ConnectionClosedOK) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1000 (OK); then sent 1000 (OK)", - ) + + self.assertEqual( + str(raised.exception), + "received 1000 (OK); then sent 1000 (OK)", + ) async def test_connection_handler_raises_exception(self): """Connection handler raises an exception.""" @@ -59,10 +60,11 @@ async def test_connection_handler_raises_exception(self): async with connect(get_uri(server) + "/crash") as client: with self.assertRaises(ConnectionClosedError) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1011 (internal error); then sent 1011 (internal error)", - ) + + self.assertEqual( + str(raised.exception), + "received 1011 (internal error); then sent 1011 (internal error)", + ) async def test_existing_socket(self): """Server receives connection using a pre-existing socket.""" @@ -99,10 +101,11 @@ def select_subprotocol(ws, subprotocols): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 400", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 400", + ) async def test_select_subprotocol_raises_exception(self): """Server returns an error if select_subprotocol raises an exception.""" @@ -114,10 +117,11 @@ def select_subprotocol(ws, subprotocols): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) async def test_compression_is_enabled(self): """Server enables compression by default.""" @@ -173,10 +177,11 @@ async def handler(ws): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 403", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 403", + ) async def test_async_process_request_returns_response(self): """Server aborts handshake if async process_request returns a response.""" @@ -194,10 +199,11 @@ async def handler(ws): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 403", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 403", + ) async def test_process_request_raises_exception(self): """Server returns an error if process_request raises an exception.""" @@ -210,10 +216,11 @@ def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_request failed", "BOOM") async def test_async_process_request_raises_exception(self): @@ -227,10 +234,11 @@ async def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_request failed", "BOOM") async def test_process_response_returns_none(self): @@ -312,10 +320,11 @@ def process_response(ws, request, response): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_response failed", "BOOM") async def test_async_process_response_raises_exception(self): @@ -329,10 +338,11 @@ async def process_response(ws, request, response): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_response failed", "BOOM") async def test_override_server_header(self): @@ -416,10 +426,11 @@ def remove_key_header(self, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 400", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 400", + ) async def test_timeout_before_handshake_request(self): """Server times out before receiving handshake request from client.""" @@ -508,10 +519,11 @@ async def process_request(ws, _request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 503", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 503", + ) async def test_close_closes_open_connections(self): """Server closes open connections with close code 1001.""" @@ -520,10 +532,11 @@ async def test_close_closes_open_connections(self): server.close() with self.assertRaises(ConnectionClosedOK) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1001 (going away); then sent 1001 (going away)", - ) + + self.assertEqual( + str(raised.exception), + "received 1001 (going away); then sent 1001 (going away)", + ) async def test_close_closes_open_connections_with_code_and_reason(self): """Server closes open connections with custom code and reason.""" @@ -532,11 +545,12 @@ async def test_close_closes_open_connections_with_code_and_reason(self): server.close(code=1012, reason="restarting") with self.assertRaises(ConnectionClosedError) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1012 (service restart) restarting; " - "then sent 1012 (service restart) restarting", - ) + + self.assertEqual( + str(raised.exception), + "received 1012 (service restart) restarting; " + "then sent 1012 (service restart) restarting", + ) async def test_close_keeps_connections_open(self): """Server waits for the client to close open connections.""" @@ -642,10 +656,6 @@ async def test_canceling_serve_forever_closes_open_connections(self): serve_forever_task.cancel() with self.assertRaises(ConnectionClosedOK) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1001 (going away); then sent 1001 (going away)", - ) with self.assertRaises(asyncio.CancelledError): await serve_forever_task @@ -654,6 +664,11 @@ async def test_canceling_serve_forever_closes_open_connections(self): server.close() await server.wait_closed() + self.assertEqual( + str(raised.exception), + "received 1001 (going away); then sent 1001 (going away)", + ) + async def test_close_exits_serve_forever(self): """Closing the server exits serve_forever().""" server = await serve(*args) @@ -772,6 +787,7 @@ async def test_host_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: await serve(handler, host="localhost", sock=sock) + self.assertEqual( str(raised.exception), "host/port and sock can not be specified at the same time", @@ -783,6 +799,7 @@ async def test_port_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: await serve(handler, port=0, sock=sock) + self.assertEqual( str(raised.exception), "host/port and sock can not be specified at the same time", @@ -792,6 +809,7 @@ async def test_unix_without_path_or_sock(self): """Unix server requires path when sock isn't provided.""" with self.assertRaises(ValueError) as raised: await unix_serve(handler) + self.assertEqual( str(raised.exception), "path was not specified, and no sock specified", @@ -803,6 +821,7 @@ async def test_unix_with_path_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: await unix_serve(handler, path="/", sock=sock) + self.assertEqual( str(raised.exception), "path and sock can not be specified at the same time", @@ -812,6 +831,7 @@ async def test_invalid_subprotocol(self): """Server rejects single value of subprotocols.""" with self.assertRaises(TypeError) as raised: await serve(*args, subprotocols="chat") + self.assertEqual( str(raised.exception), "subprotocols must be a list, not a str", @@ -821,6 +841,7 @@ async def test_unsupported_compression(self): """Server rejects incorrect value of compression.""" with self.assertRaises(ValueError) as raised: await serve(*args, compression=False) + self.assertEqual( str(raised.exception), "unsupported compression: False", @@ -874,10 +895,11 @@ async def test_missing_authorization(self): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_unsupported_authorization(self): """basic_auth rejects client with unsupported credentials.""" @@ -891,10 +913,11 @@ async def test_unsupported_authorization(self): additional_headers={"Authorization": "Negotiate ..."}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_authorization_with_unknown_username(self): """basic_auth rejects client with unknown username.""" @@ -908,10 +931,11 @@ async def test_authorization_with_unknown_username(self): additional_headers={"Authorization": "Basic YnllOnlvdWxvdmVtZQ=="}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_authorization_with_incorrect_password(self): """basic_auth rejects client with incorrect password.""" @@ -925,10 +949,11 @@ async def test_authorization_with_incorrect_password(self): additional_headers={"Authorization": "Basic aGVsbG86aWxvdmV5b3U="}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_list_of_credentials(self): """basic_auth accepts a list of hard coded credentials.""" @@ -985,6 +1010,7 @@ async def test_without_credentials_or_check_credentials(self): """basic_auth requires either credentials or check_credentials.""" with self.assertRaises(ValueError) as raised: basic_auth() + self.assertEqual( str(raised.exception), "provide either credentials or check_credentials", @@ -997,6 +1023,7 @@ async def test_with_credentials_and_check_credentials(self): credentials=("hello", "iloveyou"), check_credentials=lambda: False, # pragma: no cover ) + self.assertEqual( str(raised.exception), "provide either credentials or check_credentials", @@ -1006,6 +1033,7 @@ async def test_bad_credentials(self): """basic_auth receives an unsupported credentials argument.""" with self.assertRaises(TypeError) as raised: basic_auth(credentials=42) + self.assertEqual( str(raised.exception), "invalid credentials argument: 42", @@ -1015,6 +1043,7 @@ async def test_bad_list_of_credentials(self): """basic_auth receives an unsupported credentials argument.""" with self.assertRaises(TypeError) as raised: basic_auth(credentials=[42]) + self.assertEqual( str(raised.exception), "invalid credentials argument: [42]", diff --git a/tests/sync/test_client.py b/tests/sync/test_client.py index fdf198be..79a7fda6 100644 --- a/tests/sync/test_client.py +++ b/tests/sync/test_client.py @@ -456,10 +456,11 @@ def remove_accept_header(self, request, response): with self.assertRaises(InvalidHandshake) as raised: with connect(get_uri(server) + "/no-op", close_timeout=MS): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "missing Sec-WebSocket-Accept header", - ) + + self.assertEqual( + str(raised.exception), + "missing Sec-WebSocket-Accept header", + ) def test_timeout_during_handshake(self): """Client times out before receiving handshake response from server.""" @@ -469,10 +470,11 @@ def test_timeout_during_handshake(self): with self.assertRaises(TimeoutError) as raised: with connect(f"ws://{host}:{port}", open_timeout=MS): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "timed out while waiting for handshake response", - ) + + self.assertEqual( + str(raised.exception), + "timed out while waiting for handshake response", + ) def test_connection_closed_during_handshake(self): """Client reads EOF before receiving handshake response from server.""" @@ -485,15 +487,16 @@ def close_connection(self, request): with self.assertRaises(InvalidMessage) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "did not receive a valid HTTP response", - ) - self.assertIsInstance(raised.exception.__cause__, EOFError) - self.assertEqual( - str(raised.exception.__cause__), - "connection closed while reading HTTP status line", - ) + + self.assertEqual( + str(raised.exception), + "did not receive a valid HTTP response", + ) + self.assertIsInstance(raised.exception.__cause__, EOFError) + self.assertEqual( + str(raised.exception.__cause__), + "connection closed while reading HTTP status line", + ) def test_http_response(self): """Client reads HTTP response.""" @@ -584,20 +587,20 @@ def handle(self): with self.assertRaises(InvalidMessage) as raised: with connect(f"ws://{host}:{port}"): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "did not receive a valid HTTP response", - ) - self.assertIsInstance(raised.exception.__cause__, ValueError) - self.assertEqual( - str(raised.exception.__cause__), - "unsupported protocol; expected HTTP/1.1: " - "220 smtp.invalid ESMTP Postfix", - ) finally: server.shutdown() thread.join() + self.assertEqual( + str(raised.exception), + "did not receive a valid HTTP response", + ) + self.assertIsInstance(raised.exception.__cause__, ValueError) + self.assertEqual( + str(raised.exception.__cause__), + "unsupported protocol; expected HTTP/1.1: 220 smtp.invalid ESMTP Postfix", + ) + class SecureClientTests(unittest.TestCase): def test_context_manager(self): @@ -641,10 +644,11 @@ def test_reject_invalid_server_certificate(self): # The test certificate is self-signed. with connect(get_uri(server)): self.fail("did not raise") - self.assertIn( - "self signed certificate", - str(raised.exception).replace("-", " "), - ) + + self.assertIn( + "self signed certificate", + str(raised.exception).replace("-", " "), + ) def test_reject_invalid_server_hostname(self): """Client rejects certificate where server hostname doesn't match.""" @@ -655,10 +659,11 @@ def test_reject_invalid_server_hostname(self): get_uri(server), ssl=CLIENT_CONTEXT, server_hostname="invalid" ): self.fail("did not raise") - self.assertIn( - "Hostname mismatch", - str(raised.exception), - ) + + self.assertIn( + "Hostname mismatch", + str(raised.exception), + ) def test_cross_origin_redirect(self): """Client follows redirect to a secure URI on a different origin.""" @@ -746,6 +751,7 @@ def test_authenticated_socks_proxy_error(self): self.fail("did not raise") finally: self.proxy_options.update(proxyauth=None) + self.assertEqual( str(raised.exception), "failed to connect to SOCKS proxy", @@ -845,6 +851,7 @@ def test_authenticated_http_proxy_error(self): self.fail("did not raise") finally: self.proxy_options.update(proxyauth=None) + self.assertEqual( str(raised.exception), "proxy rejected connection: HTTP 407", @@ -879,6 +886,7 @@ def test_http_proxy_protocol_error(self): self.fail("did not raise") finally: self.proxy_options.update(break_http_connect=False) + self.assertEqual( str(raised.exception), "did not receive a valid HTTP response from proxy", @@ -895,6 +903,7 @@ def test_http_proxy_connection_error(self): self.fail("did not raise") finally: self.proxy_options.update(close_http_connect=False) + self.assertEqual( str(raised.exception), "did not receive a valid HTTP response from proxy", @@ -919,6 +928,7 @@ def test_http_proxy_connection_timeout(self): with self.assertRaises(TimeoutError) as raised: with connect("ws://example.com/", open_timeout=MS): self.fail("did not raise") + self.assertEqual( str(raised.exception), "timed out while connecting to HTTP proxy", @@ -969,6 +979,7 @@ def test_https_proxy_invalid_proxy_certificate(self): # The proxy certificate isn't trusted. with connect("wss://example.com/"): self.fail("did not raise") + self.assertIn( "unable to get local issuer certificate", str(raised.exception), @@ -983,6 +994,7 @@ def test_https_proxy_invalid_server_certificate(self): # The test certificate is self-signed. with connect(get_uri(server), proxy_ssl=self.proxy_context): self.fail("did not raise") + self.assertIn( "self signed certificate", str(raised.exception).replace("-", " "), @@ -1083,6 +1095,7 @@ def test_ssl_without_secure_uri(self): """Client rejects ssl when URI isn't secure.""" with self.assertRaises(ValueError) as raised: connect("ws://localhost/", ssl=CLIENT_CONTEXT) + self.assertEqual( str(raised.exception), "ssl argument is incompatible with a ws:// URI", @@ -1097,6 +1110,7 @@ def test_proxy_ssl_without_https_proxy(self): proxy_ssl=CLIENT_CONTEXT, ): self.fail("did not raise") + self.assertEqual( str(raised.exception), "proxy_ssl argument is incompatible with an http:// proxy", @@ -1107,6 +1121,7 @@ def test_unsupported_proxy(self): with self.assertRaises(InvalidProxy) as raised: with connect("ws://example.com/", proxy="other://localhost:58080"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "other://localhost:58080 isn't a valid proxy: scheme other isn't supported", @@ -1116,6 +1131,7 @@ def test_unix_without_path_or_sock(self): """Unix client requires path when sock isn't provided.""" with self.assertRaises(ValueError) as raised: unix_connect() + self.assertEqual( str(raised.exception), "missing path argument", @@ -1127,6 +1143,7 @@ def test_unix_with_path_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: unix_connect(path="/", sock=sock) + self.assertEqual( str(raised.exception), "path is incompatible with sock", @@ -1136,6 +1153,7 @@ def test_invalid_subprotocol(self): """Client rejects single value of subprotocols.""" with self.assertRaises(TypeError) as raised: connect("ws://localhost/", subprotocols="chat") + self.assertEqual( str(raised.exception), "subprotocols must be a list, not a str", @@ -1145,6 +1163,7 @@ def test_unsupported_compression(self): """Client rejects incorrect value of compression.""" with self.assertRaises(ValueError) as raised: connect("ws://localhost/", compression=False) + self.assertEqual( str(raised.exception), "unsupported compression: False", @@ -1158,6 +1177,7 @@ def test_reentrancy(self): with self.assertRaises(RuntimeError) as raised: with connecter: self.fail("did not raise") + self.assertEqual( str(raised.exception), "connect() isn't reentrant", diff --git a/tests/sync/test_connection.py b/tests/sync/test_connection.py index ab63dc1d..775d9285 100644 --- a/tests/sync/test_connection.py +++ b/tests/sync/test_connection.py @@ -221,6 +221,7 @@ def test_recv_during_recv(self): self.connection.recv() finally: self.remote_connection.send("") + self.assertEqual( str(raised.exception), "cannot call recv while another thread " @@ -235,6 +236,7 @@ def test_recv_during_recv_streaming(self): self.connection.recv() finally: self.remote_connection.send("") + self.assertEqual( str(raised.exception), "cannot call recv while another thread " @@ -323,6 +325,7 @@ def test_recv_streaming_during_recv(self): self.fail("did not raise") finally: self.remote_connection.send("") + self.assertEqual( str(raised.exception), "cannot call recv_streaming while another thread " @@ -338,6 +341,7 @@ def test_recv_streaming_during_recv_streaming(self): self.fail("did not raise") finally: self.remote_connection.send("") + self.assertEqual( str(raised.exception), "cannot call recv_streaming while another thread " @@ -438,6 +442,7 @@ def fragments(): with self.subTest(message=message): with self.assertRaises(ConcurrencyError) as raised: self.connection.send(message) + self.assertEqual( str(raised.exception), "cannot call send while another thread " @@ -744,6 +749,7 @@ def test_ping_duplicate_payload(self): with self.assertRaises(ConcurrencyError) as raised: self.connection.ping("idem") + self.assertEqual( str(raised.exception), "already waiting for a pong with the same data", diff --git a/tests/sync/test_router.py b/tests/sync/test_router.py index 4d2b2ad9..cdd8e138 100644 --- a/tests/sync/test_router.py +++ b/tests/sync/test_router.py @@ -104,6 +104,7 @@ def test_not_found(self): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server) + "/n"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 404", @@ -129,6 +130,7 @@ def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server) + "/"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 403", diff --git a/tests/sync/test_server.py b/tests/sync/test_server.py index 5488ec6c..3809d82c 100644 --- a/tests/sync/test_server.py +++ b/tests/sync/test_server.py @@ -51,10 +51,11 @@ def test_connection_handler_returns(self): with connect(get_uri(server) + "/no-op") as client: with self.assertRaises(ConnectionClosedOK) as raised: client.recv() - self.assertEqual( - str(raised.exception), - "received 1000 (OK); then sent 1000 (OK)", - ) + + self.assertEqual( + str(raised.exception), + "received 1000 (OK); then sent 1000 (OK)", + ) def test_connection_handler_raises_exception(self): """Connection handler raises an exception.""" @@ -62,10 +63,11 @@ def test_connection_handler_raises_exception(self): with connect(get_uri(server) + "/crash") as client: with self.assertRaises(ConnectionClosedError) as raised: client.recv() - self.assertEqual( - str(raised.exception), - "received 1011 (internal error); then sent 1011 (internal error)", - ) + + self.assertEqual( + str(raised.exception), + "received 1011 (internal error); then sent 1011 (internal error)", + ) def test_existing_socket(self): """Server receives connection using a pre-existing socket.""" @@ -102,10 +104,11 @@ def select_subprotocol(ws, subprotocols): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 400", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 400", + ) def test_select_subprotocol_raises_exception(self): """Server returns an error if select_subprotocol raises an exception.""" @@ -117,10 +120,11 @@ def select_subprotocol(ws, subprotocols): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) def test_compression_is_enabled(self): """Server enables compression by default.""" @@ -163,10 +167,11 @@ def handler(ws): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 403", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 403", + ) def test_process_request_raises_exception(self): """Server returns an error if process_request raises an exception.""" @@ -179,10 +184,11 @@ def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_request failed", "BOOM") def test_process_response_returns_none(self): @@ -230,10 +236,11 @@ def process_response(ws, request, response): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_response failed", "BOOM") def test_override_server_header(self): @@ -319,10 +326,11 @@ def remove_key_header(self, request): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 400", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 400", + ) def test_timeout_before_handshake_request(self): """Server times out before receiving handshake request from client.""" @@ -415,12 +423,13 @@ def shutdown_server(server): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 503", - ) shutdown_thread.join(MS) + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 503", + ) + def test_shutdown_closes_open_connections(self): """Server closes open connections with code 1001.""" with run_server() as server: @@ -428,10 +437,11 @@ def test_shutdown_closes_open_connections(self): server.shutdown() with self.assertRaises(ConnectionClosedOK) as raised: client.recv() - self.assertEqual( - str(raised.exception), - "received 1001 (going away); then sent 1001 (going away)", - ) + + self.assertEqual( + str(raised.exception), + "received 1001 (going away); then sent 1001 (going away)", + ) def test_shutdown_closes_open_connections_with_code_and_reason(self): """Server closes open connections with a custom code and reason.""" @@ -440,11 +450,12 @@ def test_shutdown_closes_open_connections_with_code_and_reason(self): server.shutdown(code=1012, reason="restarting") with self.assertRaises(ConnectionClosedError) as raised: client.recv() - self.assertEqual( - str(raised.exception), - "received 1012 (service restart) restarting; " - "then sent 1012 (service restart) restarting", - ) + + self.assertEqual( + str(raised.exception), + "received 1012 (service restart) restarting; " + "then sent 1012 (service restart) restarting", + ) def test_shutdown_keeps_connections_open(self): """Server waits for the client to close open connections.""" @@ -557,6 +568,7 @@ def test_host_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: serve(handler, host="localhost", sock=sock) + self.assertEqual( str(raised.exception), "host is incompatible with sock", @@ -568,6 +580,7 @@ def test_port_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: serve(handler, port=0, sock=sock) + self.assertEqual( str(raised.exception), "port is incompatible with sock", @@ -577,6 +590,7 @@ def test_unix_without_path_or_sock(self): """Unix server requires path when sock isn't provided.""" with self.assertRaises(ValueError) as raised: unix_serve(handler) + self.assertEqual( str(raised.exception), "missing path argument", @@ -588,6 +602,7 @@ def test_unix_with_path_and_sock(self): self.addCleanup(sock.close) with self.assertRaises(ValueError) as raised: unix_serve(handler, path="/", sock=sock) + self.assertEqual( str(raised.exception), "path is incompatible with sock", @@ -597,6 +612,7 @@ def test_invalid_subprotocol(self): """Server rejects single value of subprotocols.""" with self.assertRaises(TypeError) as raised: serve(handler, subprotocols="chat") + self.assertEqual( str(raised.exception), "subprotocols must be a list, not a str", @@ -606,6 +622,7 @@ def test_unsupported_compression(self): """Server rejects incorrect value of compression.""" with self.assertRaises(ValueError) as raised: serve(handler, compression=False) + self.assertEqual( str(raised.exception), "unsupported compression: False", @@ -655,10 +672,11 @@ def test_missing_authorization(self): with self.assertRaises(InvalidStatus) as raised: with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) def test_unsupported_authorization(self): """basic_auth rejects client with unsupported credentials.""" @@ -671,10 +689,11 @@ def test_unsupported_authorization(self): additional_headers={"Authorization": "Negotiate ..."}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) def test_authorization_with_unknown_username(self): """basic_auth rejects client with unknown username.""" @@ -687,10 +706,11 @@ def test_authorization_with_unknown_username(self): additional_headers={"Authorization": "Basic YnllOnlvdWxvdmVtZQ=="}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) def test_authorization_with_incorrect_password(self): """basic_auth rejects client with incorrect password.""" @@ -703,10 +723,11 @@ def test_authorization_with_incorrect_password(self): additional_headers={"Authorization": "Basic aGVsbG86aWxvdmV5b3U="}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) def test_list_of_credentials(self): """basic_auth accepts a list of hard coded credentials.""" @@ -744,6 +765,7 @@ def test_without_credentials_or_check_credentials(self): """basic_auth requires either credentials or check_credentials.""" with self.assertRaises(ValueError) as raised: basic_auth() + self.assertEqual( str(raised.exception), "provide either credentials or check_credentials", @@ -756,6 +778,7 @@ def test_with_credentials_and_check_credentials(self): credentials=("hello", "iloveyou"), check_credentials=lambda: False, # pragma: no cover ) + self.assertEqual( str(raised.exception), "provide either credentials or check_credentials", @@ -765,6 +788,7 @@ def test_bad_credentials(self): """basic_auth receives an unsupported credentials argument.""" with self.assertRaises(TypeError) as raised: basic_auth(credentials=42) + self.assertEqual( str(raised.exception), "invalid credentials argument: 42", @@ -774,6 +798,7 @@ def test_bad_list_of_credentials(self): """basic_auth receives an unsupported credentials argument.""" with self.assertRaises(TypeError) as raised: basic_auth(credentials=[42]) + self.assertEqual( str(raised.exception), "invalid credentials argument: [42]", diff --git a/tests/test_http11.py b/tests/test_http11.py index a93c8a28..f3eb8d5c 100644 --- a/tests/test_http11.py +++ b/tests/test_http11.py @@ -35,6 +35,7 @@ def test_parse(self): b"\r\n" ) request = self.assertGeneratorReturns(self.parse()) + self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/chat") self.assertEqual(request.protocol, "HTTP/1.1") @@ -43,12 +44,14 @@ def test_parse(self): def test_parse_non_get_method(self): self.reader.feed_data(b"OPTIONS * HTTP/1.1\r\n\r\n") request = self.assertGeneratorReturns(self.parse()) + self.assertEqual(request.method, "OPTIONS") self.assertEqual(request.path, "*") def test_parse_http_1_0(self): self.reader.feed_data(b"GET /chat HTTP/1.0\r\n\r\n") request = self.assertGeneratorReturns(self.parse()) + self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/chat") self.assertEqual(request.protocol, "HTTP/1.0") @@ -67,6 +70,7 @@ def test_parse_empty(self): self.reader.feed_eof() with self.assertRaises(EOFError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "connection closed while reading HTTP request line", @@ -78,6 +82,7 @@ def test_parse_request_line_too_long(self): self.reader.feed_data(b"GET /" + b"a" * 8186 + b" HTTP/1.1\r\n\r\n") with self.assertRaises(RequestLineTooLong) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "read 8202 bytes, expected no more than 8192 bytes", @@ -87,6 +92,7 @@ def test_parse_invalid_request_line(self): self.reader.feed_data(b"GET /\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid HTTP request line: GET /", @@ -96,6 +102,7 @@ def test_parse_unsupported_protocol(self): self.reader.feed_data(b"GET /chat HTTP/2.0\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "unsupported protocol; expected HTTP/1.1 or HTTP/1.0: GET /chat HTTP/2.0", @@ -105,6 +112,7 @@ def test_parse_invalid_header(self): self.reader.feed_data(b"GET /chat HTTP/1.1\r\nOops\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid HTTP header line: Oops", @@ -114,6 +122,7 @@ def test_parse_body(self): self.reader.feed_data(b"GET / HTTP/1.1\r\nContent-Length: 3\r\n\r\nYo\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "unsupported request body", @@ -122,12 +131,14 @@ def test_parse_body(self): def test_parse_body_content_length_zero(self): self.reader.feed_data(b"GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n") request = self.assertGeneratorReturns(self.parse()) + self.assertEqual(request.headers["Content-Length"], "0") def test_parse_body_with_transfer_encoding(self): self.reader.feed_data(b"GET / HTTP/1.1\r\nTransfer-Encoding: compress\r\n\r\n") with self.assertRaises(NotImplementedError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "transfer codings aren't supported", @@ -149,6 +160,7 @@ def test_serialize(self): ] ), ) + self.assertEqual( request.serialize(), b"GET /chat HTTP/1.1\r\n" @@ -187,6 +199,7 @@ def test_parse(self): b"\r\n" ) response = self.assertGeneratorReturns(self.parse()) + self.assertEqual(response.status_code, 101) self.assertEqual(response.reason_phrase, "Switching Protocols") self.assertEqual(response.headers["Upgrade"], "websocket") @@ -196,6 +209,7 @@ def test_parse_empty(self): self.reader.feed_eof() with self.assertRaises(EOFError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "connection closed while reading HTTP status line", @@ -207,6 +221,7 @@ def test_parse_status_line_too_long(self): self.reader.feed_data(b"HTTP/1.1 " + b"a" * 8191 + b"\r\n\r\n") with self.assertRaises(StatusLineTooLong) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "read 8202 bytes, expected no more than 8192 bytes", @@ -216,6 +231,7 @@ def test_parse_invalid_status_line(self): self.reader.feed_data(b"Hello!\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid HTTP status line: Hello!", @@ -225,6 +241,7 @@ def test_parse_unsupported_protocol(self): self.reader.feed_data(b"HTTP/1.0 400 Bad Request\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "unsupported protocol; expected HTTP/1.1: HTTP/1.0 400 Bad Request", @@ -234,6 +251,7 @@ def test_parse_non_integer_status(self): self.reader.feed_data(b"HTTP/1.1 OMG WTF\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid status code; expected integer; got OMG", @@ -243,19 +261,23 @@ def test_parse_non_three_digit_status(self): self.reader.feed_data(b"HTTP/1.1 007 My name is Bond\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( - str(raised.exception), "invalid status code; expected 100–599; got 007" + str(raised.exception), + "invalid status code; expected 100–599; got 007", ) def test_parse_iso_8859_1_reason(self): self.reader.feed_data(b"HTTP/1.1 200 \xd8K\r\nContent-Length: 0\r\n\r\n") response = self.assertGeneratorReturns(self.parse()) + self.assertEqual(response.reason_phrase, "ØK") def test_parse_invalid_reason(self): self.reader.feed_data(b"HTTP/1.1 200 \x7f\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid HTTP reason phrase: \x7f", @@ -265,6 +287,7 @@ def test_parse_invalid_header(self): self.reader.feed_data(b"HTTP/1.1 500 Internal Server Error\r\nOops\r\n") with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid HTTP header line: Oops", @@ -276,12 +299,14 @@ def test_parse_body(self): self.assertGeneratorRunning(gen) self.reader.feed_eof() response = self.assertGeneratorReturns(gen) + self.assertEqual(response.body, b"Hello world!\n") def test_parse_body_too_large(self): self.reader.feed_data(b"HTTP/1.1 200 OK\r\n\r\n" + b"a" * 1048577) with self.assertRaises(SecurityError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "read 1048577 bytes, expected no more than 1048576 bytes", @@ -292,12 +317,14 @@ def test_parse_body_with_content_length(self): b"HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello world!\n" ) response = self.assertGeneratorReturns(self.parse()) + self.assertEqual(response.body, b"Hello world!\n") def test_parse_body_with_content_length_and_body_too_large(self): self.reader.feed_data(b"HTTP/1.1 200 OK\r\nContent-Length: 1048577\r\n\r\n") with self.assertRaises(SecurityError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "body too large: 1048577 bytes", @@ -309,6 +336,7 @@ def test_parse_body_with_content_length_and_body_way_too_large(self): ) with self.assertRaises(SecurityError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid content length: 1234567890123456789", @@ -318,6 +346,7 @@ def test_parse_body_with_negative_content_length(self): self.reader.feed_data(b"HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\n") with self.assertRaises(SecurityError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid content length: -1", @@ -329,6 +358,7 @@ def test_parse_body_with_chunked_transfer_encoding(self): b"6\r\nHello \r\n7\r\nworld!\n\r\n0\r\n\r\n" ) response = self.assertGeneratorReturns(self.parse()) + self.assertEqual(response.body, b"Hello world!\n") def test_parse_body_with_chunked_transfer_encoding_and_chunk_without_crlf(self): @@ -338,6 +368,7 @@ def test_parse_body_with_chunked_transfer_encoding_and_chunk_without_crlf(self): ) with self.assertRaises(ValueError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "chunk without CRLF", @@ -350,6 +381,7 @@ def test_parse_body_with_chunked_transfer_encoding_and_chunk_too_large(self): ) with self.assertRaises(SecurityError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "chunk too large: 1 bytes after 1048576 bytes", @@ -362,6 +394,7 @@ def test_parse_body_with_chunked_transfer_encoding_and_chunk_way_too_large(self) ) with self.assertRaises(SecurityError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "invalid chunk size: 1234567890ABCDEF", @@ -371,6 +404,7 @@ def test_parse_body_with_unsupported_transfer_encoding(self): self.reader.feed_data(b"HTTP/1.1 200 OK\r\nTransfer-Encoding: compress\r\n\r\n") with self.assertRaises(NotImplementedError) as raised: next(self.parse()) + self.assertEqual( str(raised.exception), "transfer coding compress isn't supported", @@ -379,21 +413,25 @@ def test_parse_body_with_unsupported_transfer_encoding(self): def test_parse_body_no_content(self): self.reader.feed_data(b"HTTP/1.1 204 No Content\r\n\r\n") response = self.assertGeneratorReturns(self.parse()) + self.assertEqual(response.body, b"") def test_parse_body_not_modified(self): self.reader.feed_data(b"HTTP/1.1 304 Not Modified\r\n\r\n") response = self.assertGeneratorReturns(self.parse()) + self.assertEqual(response.body, b"") def test_parse_proxy_response_does_not_read_body(self): self.reader.feed_data(b"HTTP/1.1 200 Connection Established\r\n\r\n") response = self.assertGeneratorReturns(self.parse(proxy=True)) + self.assertEqual(response.body, b"") def test_parse_proxy_http10(self): self.reader.feed_data(b"HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n") response = self.assertGeneratorReturns(self.parse(proxy=True)) + self.assertEqual(response.status_code, 200) self.assertEqual(response.reason_phrase, "OK") self.assertEqual(response.body, b"") @@ -402,6 +440,7 @@ def test_parse_proxy_unsupported_protocol(self): self.reader.feed_data(b"HTTP/1.2 400 Bad Request\r\n\r\n") with self.assertRaises(ValueError) as raised: next(self.parse(proxy=True)) + self.assertEqual( str(raised.exception), "unsupported protocol; expected HTTP/1.1 or HTTP/1.0: " @@ -422,6 +461,7 @@ def test_serialize(self): ] ), ) + self.assertEqual( response.serialize(), b"HTTP/1.1 101 Switching Protocols\r\n" @@ -439,6 +479,7 @@ def test_serialize_with_body(self): Headers([("Content-Length", "13"), ("Content-Type", "text/plain")]), b"Hello world!\n", ) + self.assertEqual( response.serialize(), b"HTTP/1.1 200 OK\r\n" @@ -450,6 +491,7 @@ def test_serialize_with_body(self): def test_serialize_iso_8859_1_reason(self): response = Response(200, "ØK", Headers([("Content-Length", "0")])) + self.assertEqual( response.serialize(), b"HTTP/1.1 200 \xd8K\r\nContent-Length: 0\r\n\r\n", @@ -470,6 +512,7 @@ def parse_headers(self): def test_parse_iso_8859_1(self): self.reader.feed_data(b"X-Drink: caf\xe9\r\n\r\n") headers = self.parse_headers() + self.assertEqual(headers["X-Drink"], "café") def test_parse_invalid_name(self): @@ -486,7 +529,11 @@ def test_parse_too_many_headers(self): self.reader.feed_data(b"foo: bar\r\n" * 129 + b"\r\n") with self.assertRaises(TooManyHeaders) as raised: self.parse_headers() - self.assertEqual(str(raised.exception), "expected no more than 128 headers") + + self.assertEqual( + str(raised.exception), + "expected no more than 128 headers", + ) def test_parse_too_long_line(self): # Header line contains 5 + 8195 = 8200 bytes before the line ending, @@ -494,8 +541,10 @@ def test_parse_too_long_line(self): self.reader.feed_data(b"foo: " + b"a" * 8195 + b"\r\n\r\n") with self.assertRaises(HeaderLineTooLong) as raised: self.parse_headers() + self.assertEqual( - str(raised.exception), "read 8202 bytes, expected no more than 8192 bytes" + str(raised.exception), + "read 8202 bytes, expected no more than 8192 bytes", ) def test_parse_invalid_line_ending(self): diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 45b1bb57..3d44ae27 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1840,8 +1840,8 @@ def test_client_hits_internal_error_reading_frame(self): # This isn't supposed to happen, so we're simulating it. with patch("struct.unpack", side_effect=RuntimeError("BOOM")): client.receive_data(b"\x81\x00") - self.assertIsInstance(client.parser_exc, RuntimeError) - self.assertEqual(str(client.parser_exc), "BOOM") + self.assertIsInstance(client.parser_exc, RuntimeError) + self.assertEqual(str(client.parser_exc), "BOOM") self.assertConnectionFailing(client, CloseCode.INTERNAL_ERROR, "") def test_server_hits_internal_error_reading_frame(self): @@ -1849,8 +1849,8 @@ def test_server_hits_internal_error_reading_frame(self): # This isn't supposed to happen, so we're simulating it. with patch("struct.unpack", side_effect=RuntimeError("BOOM")): server.receive_data(b"\x81\x80\x00\x00\x00\x00") - self.assertIsInstance(server.parser_exc, RuntimeError) - self.assertEqual(str(server.parser_exc), "BOOM") + self.assertIsInstance(server.parser_exc, RuntimeError) + self.assertEqual(str(server.parser_exc), "BOOM") self.assertConnectionFailing(server, CloseCode.INTERNAL_ERROR, "") diff --git a/tests/test_streams.py b/tests/test_streams.py index 357eb4cb..e448ac70 100644 --- a/tests/test_streams.py +++ b/tests/test_streams.py @@ -40,6 +40,7 @@ def test_read_line_not_enough_data(self): gen = self.reader.read_line(32) with self.assertRaises(EOFError) as raised: next(gen) + self.assertEqual( str(raised.exception), "stream ends after 3 bytes, before end of line", @@ -51,6 +52,7 @@ def test_read_line_too_long(self): gen = self.reader.read_line(2) with self.assertRaises(RuntimeError) as raised: next(gen) + self.assertEqual( str(raised.exception), "read 5 bytes, expected no more than 2 bytes", @@ -62,6 +64,7 @@ def test_read_line_too_long_custom_exc_type(self): gen = self.reader.read_line(2, too_long_exc_type=ValueError) with self.assertRaises(ValueError) as raised: next(gen) + self.assertEqual( str(raised.exception), "read 5 bytes, expected no more than 2 bytes", @@ -73,6 +76,7 @@ def test_read_line_too_long_need_more_data(self): gen = self.reader.read_line(2) with self.assertRaises(RuntimeError) as raised: next(gen) + self.assertEqual( str(raised.exception), "read 3 bytes, expected no more than 2 bytes", @@ -83,6 +87,7 @@ def test_read_line_too_long_custom_exc_type_need_more_data(self): gen = self.reader.read_line(2, too_long_exc_type=ValueError) with self.assertRaises(ValueError) as raised: next(gen) + self.assertEqual( str(raised.exception), "read 3 bytes, expected no more than 2 bytes", @@ -121,6 +126,7 @@ def test_read_exact_not_enough_data(self): gen = self.reader.read_exact(4) with self.assertRaises(EOFError) as raised: next(gen) + self.assertEqual( str(raised.exception), "stream ends after 3 bytes, expected 4 bytes", @@ -149,6 +155,7 @@ def test_read_to_eof_too_long(self): self.reader.feed_data(b"spam") with self.assertRaises(RuntimeError) as raised: next(gen) + self.assertEqual( str(raised.exception), "read 4 bytes, expected no more than 2 bytes", @@ -160,6 +167,7 @@ def test_read_to_eof_too_long_custom_exc_type(self): self.reader.feed_data(b"spam") with self.assertRaises(ValueError) as raised: next(gen) + self.assertEqual( str(raised.exception), "read 4 bytes, expected no more than 2 bytes", @@ -204,6 +212,7 @@ def test_feed_data_after_feed_eof(self): self.reader.feed_eof() with self.assertRaises(EOFError) as raised: self.reader.feed_data(b"spam") + self.assertEqual( str(raised.exception), "stream ended", @@ -213,6 +222,7 @@ def test_feed_eof_after_feed_eof(self): self.reader.feed_eof() with self.assertRaises(EOFError) as raised: self.reader.feed_eof() + self.assertEqual( str(raised.exception), "stream ended", diff --git a/tests/trio/test_client.py b/tests/trio/test_client.py index a4d3d486..0838d101 100644 --- a/tests/trio/test_client.py +++ b/tests/trio/test_client.py @@ -440,10 +440,11 @@ def remove_accept_header(self, request, response): with self.assertRaises(InvalidHandshake) as raised: async with connect(get_uri(server) + "/no-op", close_timeout=MS): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "missing Sec-WebSocket-Accept header", - ) + + self.assertEqual( + str(raised.exception), + "missing Sec-WebSocket-Accept header", + ) async def test_timeout_during_handshake(self): """Client times out before receiving handshake response from server.""" @@ -453,10 +454,11 @@ async def test_timeout_during_handshake(self): with self.assertRaises(TimeoutError) as raised: async with connect(f"ws://{host}:{port}", open_timeout=2 * MS): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "timed out during opening handshake", - ) + + self.assertEqual( + str(raised.exception), + "timed out during opening handshake", + ) async def test_connection_closed_during_handshake(self): """Client reads EOF before receiving handshake response from server.""" @@ -468,15 +470,16 @@ async def close_connection(self, request): with self.assertRaises(InvalidMessage) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "did not receive a valid HTTP response", - ) - self.assertIsInstance(raised.exception.__cause__, EOFError) - self.assertEqual( - str(raised.exception.__cause__), - "connection closed while reading HTTP status line", - ) + + self.assertEqual( + str(raised.exception), + "did not receive a valid HTTP response", + ) + self.assertIsInstance(raised.exception.__cause__, EOFError) + self.assertEqual( + str(raised.exception.__cause__), + "connection closed while reading HTTP status line", + ) async def test_http_response(self): """Client reads HTTP response.""" @@ -566,19 +569,19 @@ async def junk(stream): with self.assertRaises(InvalidMessage) as raised: async with connect(f"ws://{host}:{port}"): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "did not receive a valid HTTP response", - ) - self.assertIsInstance(raised.exception.__cause__, ValueError) - self.assertEqual( - str(raised.exception.__cause__), - "unsupported protocol; expected HTTP/1.1: " - "220 smtp.invalid ESMTP Postfix", - ) finally: nursery.cancel_scope.cancel() + self.assertEqual( + str(raised.exception), + "did not receive a valid HTTP response", + ) + self.assertIsInstance(raised.exception.__cause__, ValueError) + self.assertEqual( + str(raised.exception.__cause__), + "unsupported protocol; expected HTTP/1.1: 220 smtp.invalid ESMTP Postfix", + ) + class SecureClientTests(IsolatedTrioTestCase): async def test_context_manager(self): @@ -620,14 +623,15 @@ async def test_reject_invalid_server_certificate(self): # The test certificate is self-signed. async with connect(get_uri(server, secure=True)): self.fail("did not raise") - self.assertIsInstance( - raised.exception.__cause__, - ssl.SSLCertVerificationError, - ) - self.assertIn( - "self signed certificate", - str(raised.exception.__cause__).replace("-", " "), - ) + + self.assertIsInstance( + raised.exception.__cause__, + ssl.SSLCertVerificationError, + ) + self.assertIn( + "self signed certificate", + str(raised.exception.__cause__).replace("-", " "), + ) async def test_reject_invalid_server_hostname(self): """Client rejects certificate where server hostname doesn't match.""" @@ -640,14 +644,15 @@ async def test_reject_invalid_server_hostname(self): server_hostname="invalid", ): self.fail("did not raise") - self.assertIsInstance( - raised.exception.__cause__, - ssl.SSLCertVerificationError, - ) - self.assertIn( - "Hostname mismatch", - str(raised.exception.__cause__), - ) + + self.assertIsInstance( + raised.exception.__cause__, + ssl.SSLCertVerificationError, + ) + self.assertIn( + "Hostname mismatch", + str(raised.exception.__cause__), + ) async def test_cross_origin_redirect(self): """Client follows redirect to a secure URI on a different origin.""" @@ -730,6 +735,7 @@ async def test_authenticated_socks_proxy_error(self): self.fail("did not raise") finally: self.proxy_options.update(proxyauth=None) + self.assertEqual( str(raised.exception), "failed to connect to SOCKS proxy", @@ -758,6 +764,7 @@ async def test_socks_proxy_connection_timeout(self): with self.assertRaises(TimeoutError) as raised: async with connect("ws://example.com/", open_timeout=2 * MS): self.fail("did not raise") + self.assertEqual( str(raised.exception), "timed out during opening handshake", @@ -832,6 +839,7 @@ async def test_authenticated_http_proxy_error(self): self.fail("did not raise") finally: self.proxy_options.update(proxyauth=None) + self.assertEqual( str(raised.exception), "proxy rejected connection: HTTP 407", @@ -848,6 +856,7 @@ async def test_http_proxy_protocol_error(self): self.fail("did not raise") finally: self.proxy_options.update(break_http_connect=False) + self.assertEqual( str(raised.exception), "did not receive a valid HTTP response from proxy", @@ -864,6 +873,7 @@ async def test_http_proxy_connection_error(self): self.fail("did not raise") finally: self.proxy_options.update(close_http_connect=False) + self.assertEqual( str(raised.exception), "did not receive a valid HTTP response from proxy", @@ -888,6 +898,7 @@ async def test_http_proxy_connection_timeout(self): with self.assertRaises(TimeoutError) as raised: async with connect("ws://example.com/", open_timeout=2 * MS): self.fail("did not raise") + self.assertEqual( str(raised.exception), "timed out during opening handshake", @@ -1051,6 +1062,7 @@ async def test_ssl_without_secure_uri(self): with self.assertRaises(ValueError) as raised: async with connect("ws://localhost/", ssl=CLIENT_CONTEXT): self.fail("did not raise") + self.assertEqual( str(raised.exception), "ssl argument is incompatible with a ws:// URI", @@ -1065,6 +1077,7 @@ async def test_proxy_ssl_without_https_proxy(self): proxy_ssl=True, ): self.fail("did not raise") + self.assertEqual( str(raised.exception), "proxy_ssl argument is incompatible with an http:// proxy", @@ -1075,6 +1088,7 @@ async def test_unsupported_proxy(self): with self.assertRaises(InvalidProxy) as raised: async with connect("ws://example.com/", proxy="other://localhost:51080"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "other://localhost:51080 isn't a valid proxy: scheme other isn't supported", @@ -1085,6 +1099,7 @@ async def test_unix_without_path_or_stream(self): with self.assertRaises(ValueError) as raised: async with unix_connect(): self.fail("did not raise") + self.assertEqual( str(raised.exception), "missing path argument", @@ -1096,6 +1111,7 @@ async def test_unix_with_path_and_stream(self): with self.assertRaises(ValueError) as raised: async with unix_connect(path="/", stream=stream): self.fail("did not raise") + self.assertEqual( str(raised.exception), "path is incompatible with stream", @@ -1106,6 +1122,7 @@ async def test_invalid_subprotocol(self): with self.assertRaises(TypeError) as raised: async with connect("ws://localhost/", subprotocols="chat"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "subprotocols must be a list, not a str", @@ -1116,6 +1133,7 @@ async def test_unsupported_compression(self): with self.assertRaises(ValueError) as raised: async with connect("ws://localhost/", compression=False): self.fail("did not raise") + self.assertEqual( str(raised.exception), "unsupported compression: False", @@ -1129,6 +1147,7 @@ async def test_reentrancy(self): with self.assertRaises(RuntimeError) as raised: async with connecter: self.fail("did not raise") + self.assertEqual( str(raised.exception), "connect() isn't reentrant", diff --git a/tests/trio/test_connection.py b/tests/trio/test_connection.py index f3137a9d..d665c735 100644 --- a/tests/trio/test_connection.py +++ b/tests/trio/test_connection.py @@ -225,6 +225,7 @@ async def test_recv_during_recv(self): await self.connection.recv() finally: nursery.cancel_scope.cancel() + self.assertEqual( str(raised.exception), "cannot call recv while another coroutine " @@ -241,6 +242,7 @@ async def test_recv_during_recv_streaming(self): await self.connection.recv() finally: nursery.cancel_scope.cancel() + self.assertEqual( str(raised.exception), "cannot call recv while another coroutine " @@ -364,6 +366,7 @@ async def test_recv_streaming_during_recv(self): self.fail("did not raise") finally: nursery.cancel_scope.cancel() + self.assertEqual( str(raised.exception), "cannot call recv_streaming while another coroutine " @@ -381,6 +384,7 @@ async def test_recv_streaming_during_recv_streaming(self): self.fail("did not raise") finally: nursery.cancel_scope.cancel() + self.assertEqual( str(raised.exception), "cannot call recv_streaming while another coroutine " @@ -928,6 +932,7 @@ async def test_ping_duplicate_payload(self): with self.assertRaises(ConcurrencyError) as raised: await self.connection.ping("idem") + self.assertEqual( str(raised.exception), "already waiting for a pong with the same data", diff --git a/tests/trio/test_router.py b/tests/trio/test_router.py index e303a3bd..9cf68e7b 100644 --- a/tests/trio/test_router.py +++ b/tests/trio/test_router.py @@ -104,6 +104,7 @@ async def test_not_found(self): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server) + "/n"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 404", @@ -139,6 +140,7 @@ def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server) + "/"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 403", @@ -154,6 +156,7 @@ async def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server) + "/"): self.fail("did not raise") + self.assertEqual( str(raised.exception), "server rejected WebSocket connection: HTTP 403", diff --git a/tests/trio/test_server.py b/tests/trio/test_server.py index ffd7337c..7c7f3d9f 100644 --- a/tests/trio/test_server.py +++ b/tests/trio/test_server.py @@ -46,10 +46,11 @@ async def test_connection_handler_returns(self): async with connect(get_uri(server) + "/no-op") as client: with self.assertRaises(ConnectionClosedOK) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1000 (OK); then sent 1000 (OK)", - ) + + self.assertEqual( + str(raised.exception), + "received 1000 (OK); then sent 1000 (OK)", + ) async def test_connection_handler_raises_exception(self): """Connection handler raises an exception.""" @@ -57,10 +58,11 @@ async def test_connection_handler_raises_exception(self): async with connect(get_uri(server) + "/crash") as client: with self.assertRaises(ConnectionClosedError) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1011 (internal error); then sent 1011 (internal error)", - ) + + self.assertEqual( + str(raised.exception), + "received 1011 (internal error); then sent 1011 (internal error)", + ) async def test_existing_listeners(self): """Server receives connection using pre-existing listeners.""" @@ -101,10 +103,11 @@ def select_subprotocol(ws, subprotocols): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 400", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 400", + ) async def test_select_subprotocol_raises_exception(self): """Server returns an error if select_subprotocol raises an exception.""" @@ -116,10 +119,11 @@ def select_subprotocol(ws, subprotocols): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) async def test_compression_is_enabled(self): """Server enables compression by default.""" @@ -173,10 +177,11 @@ async def handler(ws): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 403", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 403", + ) async def test_async_process_request_returns_response(self): """Server aborts handshake if async process_request returns a response.""" @@ -192,10 +197,11 @@ async def handler(ws): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 403", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 403", + ) async def test_process_request_raises_exception(self): """Server returns an error if process_request raises an exception.""" @@ -208,10 +214,11 @@ def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_request failed", "BOOM") async def test_async_process_request_raises_exception(self): @@ -225,10 +232,11 @@ async def process_request(ws, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_request failed", "BOOM") async def test_process_response_returns_none(self): @@ -310,10 +318,11 @@ def process_response(ws, request, response): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_response failed", "BOOM") async def test_async_process_response_raises_exception(self): @@ -327,10 +336,11 @@ async def process_response(ws, request, response): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 500", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 500", + ) self.assertExceptionLogged(logs, "process_response failed", "BOOM") async def test_override_serve_header(self): @@ -412,10 +422,11 @@ def remove_key_header(self, request): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 400", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 400", + ) async def test_timeout_before_handshake_request(self): """Server times out before receiving handshake request from client.""" @@ -513,10 +524,10 @@ async def close_server(server): async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 503", - ) + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 503", + ) async def test_aclose_closes_open_connections(self): """Server closes open connections with close code 1001.""" @@ -525,10 +536,11 @@ async def test_aclose_closes_open_connections(self): await server.aclose() with self.assertRaises(ConnectionClosedOK) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1001 (going away); then sent 1001 (going away)", - ) + + self.assertEqual( + str(raised.exception), + "received 1001 (going away); then sent 1001 (going away)", + ) async def test_aclose_closes_open_connections_with_code_and_reason(self): """Server closes open connections with custom code and reason.""" @@ -537,11 +549,12 @@ async def test_aclose_closes_open_connections_with_code_and_reason(self): await server.aclose(code=1012, reason="restarting") with self.assertRaises(ConnectionClosedError) as raised: await client.recv() - self.assertEqual( - str(raised.exception), - "received 1012 (service restart) restarting; " - "then sent 1012 (service restart) restarting", - ) + + self.assertEqual( + str(raised.exception), + "received 1012 (service restart) restarting; " + "then sent 1012 (service restart) restarting", + ) async def test_aclose_keeps_connections_open(self): """Server waits for client to close open connections.""" @@ -636,6 +649,7 @@ async def test_missing_port(self): """Server requires port.""" with self.assertRaises(ValueError) as raised: await serve(handler, None) + self.assertEqual( str(raised.exception), "port is required when listeners is not provided", @@ -647,46 +661,50 @@ async def test_port_and_listeners(self): try: with self.assertRaises(ValueError) as raised: await serve(handler, port=0, listeners=listeners) - self.assertEqual( - str(raised.exception), - "port is incompatible with listeners", - ) finally: for listener in listeners: await listener.aclose() + self.assertEqual( + str(raised.exception), + "port is incompatible with listeners", + ) + async def test_host_and_listeners(self): """Server rejects host when listeners is provided.""" listeners = await trio.open_tcp_listeners(0) try: with self.assertRaises(ValueError) as raised: await serve(handler, host="localhost", listeners=listeners) - self.assertEqual( - str(raised.exception), - "host is incompatible with listeners", - ) finally: for listener in listeners: await listener.aclose() + self.assertEqual( + str(raised.exception), + "host is incompatible with listeners", + ) + async def test_backlog_and_listeners(self): """Server rejects backlog when listeners is provided.""" listeners = await trio.open_tcp_listeners(0) try: with self.assertRaises(ValueError) as raised: await serve(handler, backlog=65535, listeners=listeners) - self.assertEqual( - str(raised.exception), - "backlog is incompatible with listeners", - ) finally: for listener in listeners: await listener.aclose() + self.assertEqual( + str(raised.exception), + "backlog is incompatible with listeners", + ) + async def test_invalid_subprotocol(self): """Server rejects single value of subprotocols.""" with self.assertRaises(TypeError) as raised: await serve(handler, subprotocols="chat") + self.assertEqual( str(raised.exception), "subprotocols must be a list, not a str", @@ -696,6 +714,7 @@ async def test_unsupported_compression(self): """Server rejects incorrect value of compression.""" with self.assertRaises(ValueError) as raised: await serve(handler, compression=False) + self.assertEqual( str(raised.exception), "unsupported compression: False", @@ -722,10 +741,11 @@ async def test_missing_authorization(self): with self.assertRaises(InvalidStatus) as raised: async with connect(get_uri(server)): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_unsupported_authorization(self): """basic_auth rejects client with unsupported credentials.""" @@ -738,10 +758,11 @@ async def test_unsupported_authorization(self): additional_headers={"Authorization": "Negotiate ..."}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_authorization_with_unknown_username(self): """basic_auth rejects client with unknown username.""" @@ -754,10 +775,11 @@ async def test_authorization_with_unknown_username(self): additional_headers={"Authorization": "Basic YnllOnlvdWxvdmVtZQ=="}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_authorization_with_incorrect_password(self): """basic_auth rejects client with incorrect password.""" @@ -770,10 +792,11 @@ async def test_authorization_with_incorrect_password(self): additional_headers={"Authorization": "Basic aGVsbG86aWxvdmV5b3U="}, ): self.fail("did not raise") - self.assertEqual( - str(raised.exception), - "server rejected WebSocket connection: HTTP 401", - ) + + self.assertEqual( + str(raised.exception), + "server rejected WebSocket connection: HTTP 401", + ) async def test_list_of_credentials(self): """basic_auth accepts a list of hard coded credentials.""" @@ -827,6 +850,7 @@ async def test_without_credentials_or_check_credentials(self): """basic_auth requires either credentials or check_credentials.""" with self.assertRaises(ValueError) as raised: basic_auth() + self.assertEqual( str(raised.exception), "provide either credentials or check_credentials", @@ -839,6 +863,7 @@ async def test_with_credentials_and_check_credentials(self): credentials=("hello", "iloveyou"), check_credentials=lambda: False, # pragma: no cover ) + self.assertEqual( str(raised.exception), "provide either credentials or check_credentials", @@ -848,6 +873,7 @@ async def test_bad_credentials(self): """basic_auth receives an unsupported credentials argument.""" with self.assertRaises(TypeError) as raised: basic_auth(credentials=42) + self.assertEqual( str(raised.exception), "invalid credentials argument: 42", @@ -857,6 +883,7 @@ async def test_bad_list_of_credentials(self): """basic_auth receives an unsupported credentials argument.""" with self.assertRaises(TypeError) as raised: basic_auth(credentials=[42]) + self.assertEqual( str(raised.exception), "invalid credentials argument: [42]",