From 092a57a8cbe1410347c27288845a312b991113eb Mon Sep 17 00:00:00 2001 From: jaylfc Date: Tue, 18 Aug 2026 02:56:44 +0000 Subject: [PATCH] Fix _stream_rejection: accumulate into one buffer instead of discarding bytes by luck of chunk sizes --- .../tsk-ocjut3-stream-rejection-buffer.md | 3 ++ tests/test_a2a.py | 32 +++++++------------ 2 files changed, 14 insertions(+), 21 deletions(-) create mode 100644 changelog.d/tsk-ocjut3-stream-rejection-buffer.md diff --git a/changelog.d/tsk-ocjut3-stream-rejection-buffer.md b/changelog.d/tsk-ocjut3-stream-rejection-buffer.md new file mode 100644 index 00000000..dd2533c0 --- /dev/null +++ b/changelog.d/tsk-ocjut3-stream-rejection-buffer.md @@ -0,0 +1,3 @@ +### Fixed + +- `_stream_rejection` in `tests/test_a2a.py` now accumulates all received data into a single buffer until the `\r\n\r\n` separator is found, instead of discarding already-read bytes across separate 128-byte chunk reads. This eliminates the latent fragility where the function worked only by luck of buffer sizes. \ No newline at end of file diff --git a/tests/test_a2a.py b/tests/test_a2a.py index c50c9c6b..58f4cba6 100644 --- a/tests/test_a2a.py +++ b/tests/test_a2a.py @@ -368,41 +368,31 @@ def _stream_rejection(live_server: str, path: str, timeout: float = 3.0) -> tupl f"GET {path} HTTP/1.1\r\nHost: {host}:{port}\r\nConnection: close\r\n\r\n".encode() ) sock.settimeout(timeout) - line = b"" - while b"\r\n" not in line: + data = b"" + while b"\r\n\r\n" not in data: try: - chunk = sock.recv(128) + chunk = sock.recv(4096) except (socket.timeout, TimeoutError) as exc: - raise AssertionError(f"timed out reading stream status line: {exc}") from exc + raise AssertionError(f"timed out reading stream response: {exc}") from exc if not chunk: break - line += chunk - status_line = line.decode("utf-8", "replace").splitlines()[0] + data += chunk + + header_text, _, body_text = data.partition(b"\r\n\r\n") + + status_line = header_text.decode("utf-8", "replace").splitlines()[0] status = int(status_line.split()[1]) if status == 200: return status, None - headers_raw = b"" - while b"\r\n\r\n" not in headers_raw: - try: - chunk = sock.recv(128) - except (socket.timeout, TimeoutError) as exc: - raise AssertionError(f"timed out reading response headers: {exc}") from exc - if not chunk: - break - headers_raw += chunk - - header_text = headers_raw.decode("utf-8", "replace") - body_start = header_text.find("\r\n\r\n") + 4 - body_bytes = header_text[body_start:].encode("utf-8") - content_length = None - for h in header_text.splitlines()[1:]: + for h in header_text.decode("utf-8", "replace").splitlines()[1:]: if h.lower().startswith("content-length:"): content_length = int(h.split(":", 1)[1].strip()) break + body_bytes = body_text if content_length is not None: remaining = content_length - len(body_bytes) while remaining > 0: