3.6 KiB
| id | status | status_updated | status_note | component | severity | timestamp | last_seen | occurrences | files | tags | related | fix_commits | legacy | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bug-1683 | fixed | 2026-10-03 | xceadmin | unknown | 2026-08-25T00:05:00Z | 2026-10-03T07:27:36Z | 3 |
|
|
|
|
true |
bug-1683: xceadmin pytest failure: test_send_frame_writes_exact_known_good_byte_sequence…
Description
xceadmin pytest failure: test_send_frame_writes_exact_known_good_byte_sequence (src/xceadmin/tests/test_wire.py:200). Test sends a 4-byte payload b'xce!' via wire.send_frame() over a real TLS socket to a raw capture handler that reads exactly 12 bytes (8-byte length header + 4-byte payload) directly off the wire, bypassing this module's own recv_frame() decoder. Expected the captured bytes to be struct.pack('=Q', 4) + b'xce!' (header correctly encodes length=4, followed by the literal payload bytes). Actual captured bytes: the 8-byte header is correct (b'\x04\x00\x00\x00\x00\x00\x00\x00', i.e. length=4 little-endian native uint64_t), but the trailing 4 bytes are all zero (b'\x00\x00\x00\x00') instead of b'xce!' -- the real payload bytes never reached the wire. 1 failed, 266 passed, 3 skipped -- isolated to this one test.
UPDATE (2026-10-03): Correction: the trailing bytes were never zeroed -- pytest's truncated diff showed the 8-byte header alone. See Root cause (test-harness TLS RST race).
Environment
Not recorded (migrated from buglog.json).
Reproduction
Not recorded (migrated from buglog.json).
Root cause
Corrected 2026-10-03, superseding the earlier "not reproducible / build-dir race (bug-1604)" analysis (kept in git history). Test-harness race in src/xceadmin/tests/test_wire.py test_send_frame_writes_exact_known_good_byte_sequence: the client called send_frame() and then sock.close() immediately. Under TLS 1.3 the server sends NewSessionTicket records after the handshake that the client never reads; closing a TCP socket with unread inbound data makes Linux send RST instead of FIN. Each sendall() is its own TLS record, so when the RST lands between the server's read of the 8-byte header record and the 4-byte payload record, the unread payload is discarded and recv() raises ConnectionResetError/BrokenPipeError, which _TlsEchoServer._run swallowed with a bare pass -- leaving captured = header only. The "4 zero bytes" in the original description was a misreading of pytest's truncated diff of the 8-byte header. wire.send_frame() is correct; production paths read the reply before closing and are not exposed.
Fix
test_wire.py only: the client waits on a capture_done Event (set in the handler's finally) before sock.close(); _TlsEchoServer records the handler's OSError in handler_error (asserted None) instead of discarding it; the test is parametrized with settle_s [0.0, 0.05] (immediate / tickets-pending), the 0.05 case being a deterministic regression for the RST path. Fix commit 362098b1.
Verification
- Test:
test_send_frame_writes_exact_known_good_byte_sequence[tickets-pending]insrc/xceadmin/tests/test_wire.py— RED before the fix (assert b'\x04\x00...\x00' == b'\x04\x00...xce!'; reviewer's scratch copy without the wait: 5/5 ConnectionResetError 104), GREEN after; 200 looped runs 0 failures; scratch harness 8/2000 natural failures before vs 0/2000 after. - Suites:
bash src/tools/xce-build.sh xceadmin --incremental373 passed, 2026-10-03. - Live: n/a
References
- Related: bug-1604