From c21477272c1e20a9acad81e2e2f944239cbe6610 Mon Sep 17 00:00:00 2001 From: Dusan Haustein Date: Fri, 7 Mar 2025 08:17:21 +0100 Subject: [PATCH 1/2] fix: typo --- server.py | 4 ++-- tests/integration/test_client_server.py | 4 ++-- tests/unit/test_server.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server.py b/server.py index d09cc95..29f84de 100644 --- a/server.py +++ b/server.py @@ -8,7 +8,7 @@ DEFAULT_RESPONSE = b"Request received!" -def contruct_response(response_payload: bytes = DEFAULT_RESPONSE) -> bytes: +def construct_response(response_payload: bytes = DEFAULT_RESPONSE) -> bytes: response_line = b"HTTP/1.1 200 OK\r\n" headers = b"".join( [b"Server: CrappyServer/0.0.1\r\n", b"Content-Type: text/plain\r\n"] @@ -61,7 +61,7 @@ def main() -> None: ) args = parser.parse_args() - start_server(response=contruct_response(args.response_payload.encode("utf-8"))) + start_server(response=construct_response(args.response_payload.encode("utf-8"))) if __name__ == "__main__": diff --git a/tests/integration/test_client_server.py b/tests/integration/test_client_server.py index 6f2163b..4912a20 100644 --- a/tests/integration/test_client_server.py +++ b/tests/integration/test_client_server.py @@ -6,7 +6,7 @@ import pytest from client import send_request -from server import contruct_response, start_server +from server import construct_response, start_server # fun with types ServerFactoryCallable = Callable[[bytes], tuple[threading.Thread, int]] @@ -53,7 +53,7 @@ def create_server( port = random.randint(8081, 9080) def run_server() -> None: - start_server(contruct_response(response_payload), port=port) + start_server(construct_response(response_payload), port=port) thread = threading.Thread(target=run_server, daemon=True) threads.append((thread, port)) diff --git a/tests/unit/test_server.py b/tests/unit/test_server.py index 6bc8fc2..51cd6f4 100644 --- a/tests/unit/test_server.py +++ b/tests/unit/test_server.py @@ -2,7 +2,7 @@ import pytest # noqa: F401 -from server import contruct_response, start_server +from server import construct_response, start_server def test_server_connection() -> None: @@ -13,7 +13,7 @@ def test_server_connection() -> None: host = "127.0.0.1" port = 8888 client_request = b"HTTP/1.1 200 OK\r\nUser-Agent: CrappyClient/0.0.1\r\nContent-Type: text/plain\r\n\r\ntest payload from client" - server_response = contruct_response(b"My test response") + server_response = construct_response(b"My test response") mock_conn = Mock() mock_socket = Mock() From 794e16109e0377b360496da350776edd203609fd Mon Sep 17 00:00:00 2001 From: Dusan Haustein Date: Fri, 7 Mar 2025 09:34:42 +0100 Subject: [PATCH 2/2] fix: a buncha fixes --- client.py | 11 +++++++--- tests/acceptance/test_e2e.py | 28 ++++++++++++++++++++++++- tests/integration/test_client_server.py | 10 +++++---- tests/unit/test_client.py | 2 +- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/client.py b/client.py index 459f6ec..1356284 100644 --- a/client.py +++ b/client.py @@ -12,13 +12,18 @@ def send_request( with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) - response_line = b"HTTP/1.1 200 OK\r\n" + request_line = b"GET / HTTP/1.1\r\n" headers = b"".join( - [b"User-Agent: CrappyClient/0.0.1\r\n", b"Content-Type: text/plain\r\n"] + [ + f"Host: {host}:{port}\r\n".encode("utf-8"), + b"User-Agent: CrappyClient/0.0.1\r\n", + b"Content-Type: text/plain\r\n", + f"Content-Length: {len(request_payload)}\r\n".encode("utf-8"), + ] ) blank_line = b"\r\n" - request = b"".join([response_line, headers, blank_line, request_payload]) + request = b"".join([request_line, headers, blank_line, request_payload]) s.sendall(request) data = s.recv(1024) diff --git a/tests/acceptance/test_e2e.py b/tests/acceptance/test_e2e.py index 231600b..3e746ec 100644 --- a/tests/acceptance/test_e2e.py +++ b/tests/acceptance/test_e2e.py @@ -12,6 +12,29 @@ def get_container_logs(container_id: str) -> str: # type: ignore pass +def wait_for_server_ready( + server_name: str, max_attempts: int = 20, delay: float = 0.5 +) -> None: + """Quick and dirty wait for server to be ready by attempting to connect to it""" + for attempt in range(max_attempts): + try: + client = podman.PodmanClient() + container = client.containers.get(server_name) + exit_code, _ = container.exec_run("ss -tulpn | grep LISTEN") + + if exit_code == 0: + return + except Exception: + pass + + print(f"Waiting for server to be ready... (attempt {attempt+1}/{max_attempts})") + time.sleep(delay) + + raise TimeoutError( + f"Server did not become ready after {max_attempts * delay} seconds" + ) + + # environment setup as fixtures @@ -36,8 +59,11 @@ def server_container(podman_network: str) -> Generator[str, None, None]: name="test-server", detach=True, ) - time.sleep(10) # wait for server to start + + wait_for_server_ready("test-server", max_attempts=10) + yield "test-server" + container.stop() container.remove() diff --git a/tests/integration/test_client_server.py b/tests/integration/test_client_server.py index 4912a20..73098d2 100644 --- a/tests/integration/test_client_server.py +++ b/tests/integration/test_client_server.py @@ -1,7 +1,7 @@ import random import threading import time -from typing import Callable, Generator +from typing import Callable, Generator, TypeAlias import pytest @@ -9,7 +9,9 @@ from server import construct_response, start_server # fun with types -ServerFactoryCallable = Callable[[bytes], tuple[threading.Thread, int]] +ServerThread: TypeAlias = threading.Thread +ServerPort: TypeAlias = int +ServerFactoryCallable = Callable[[bytes], tuple[ServerThread, ServerPort]] ServerFactoryFixture = Generator[ServerFactoryCallable, None, None] @@ -58,7 +60,7 @@ def run_server() -> None: thread = threading.Thread(target=run_server, daemon=True) threads.append((thread, port)) thread.start() - time.sleep(0.1) + time.sleep(0.1) # should be replaced with a proper polling/readiness check return thread, port @@ -106,7 +108,7 @@ def test_extra_long_request_payload_rejected( """Test that a request larger than the default buffer size of 1024 the server will reject this with 'Connection reset by peer'""" thread, port = server_factory(b"Request received!") - very_long_payload = b"bla" * 1000000000 + very_long_payload = b"bla" * 100000000 with pytest.raises(ConnectionResetError): request, response = send_request(very_long_payload, port=port) diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 81b0077..ad2740f 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -11,7 +11,7 @@ def test_send_request() -> None: We pretend-check the client is 'HTTP complicant' by checking it includes the expected headers """ payload = b"test payload" - request = b"HTTP/1.1 200 OK\r\nUser-Agent: CrappyClient/0.0.1\r\nContent-Type: text/plain\r\n\r\ntest payload" + request = b"GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nUser-Agent: CrappyClient/0.0.1\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\ntest payload" response = b"HTTP/1.1 200 OK\r\nServer: CrappyServer/0.0.1\r\nContent-Type: text/plain\r\n\r\nRequest received!" # mock the server response