-- Make two websocket fragmentation tests tolerant of extra, real -- partial socket writes. These tests use a real loopback websocket -- connection and mock ws_send to simulate one partial write, but -- still call through to the real socket send for the rest; on -- FreeBSD the real loopback socket may legitimately perform its own -- additional partial write, producing more attempts than the tests' -- hardcoded exact counts expect, causing intermittent failures -- unrelated to actual correctness (data integrity is always -- verified). Loosen the exact-count assertions to invariant/ -- lower-bound checks that still catch the real regression being -- guarded against (resending the whole original chunk instead of -- just the remainder after a partial send). --- tests/unittest/test_async_websockets.py.orig 2026-09-30 07:17:08 UTC +++ tests/unittest/test_async_websockets.py @@ -1681,17 +1681,27 @@ class TestAsyncWebSocketFragmentationFix: data, _ = await ws_connection.recv() assert data == payload - # Verify the exact chunking sequence generated by the hot loop: + # Verify the chunking sequence generated by the hot loop: # 1. Loop tries 65536, mock only accepts 10000 # 2. Loop MUST try exactly 55536 next (the remainder of the 65536 frame) - # 3. Loop tries 34464 (the final fragment) - assert len(attempt_logs) == 3 + # 3. Zero or more further frames, each resuming at exactly the + # remainder of the previous one (never resending the whole + # original chunk) -- real loopback sockets may perform their + # own extra partial writes beyond the simulated one. + assert len(attempt_logs) >= 3 assert attempt_logs[0] == (65536, 10000) assert attempt_logs[1] == ( 55536, 55536, ) # <-- The old code failed here by trying 65536 - assert attempt_logs[2] == (34464, 34464) + for prev, cur in zip(attempt_logs, attempt_logs[1:]): + prev_chunk_len, prev_n_sent = prev + cur_chunk_len, _ = cur + if prev_n_sent < prev_chunk_len: + # Previous attempt was a partial write: the next + # attempt must resume with exactly the remainder, + # never the whole original chunk. + assert cur_chunk_len == prev_chunk_len - prev_n_sent async def test_send_eagain_retry_preserves_state( self, ws_connection: AsyncWebSocket @@ -1722,7 +1732,9 @@ class TestAsyncWebSocketFragmentationFix: assert data == payload # 1 EAGAIN attempt + 1st fragment (65536) + 2nd fragment (34464) - assert call_count == 3 + # (real loopback sockets may perform additional legitimate + # partial writes beyond this minimum) + assert call_count >= 3 async def test_manual_fragmentation_with_cont_flag( self, ws_connection: AsyncWebSocket