Skip to content

Commit d3118f5

Browse files
tcoratgerclaude
andauthored
test: add 100% coverage for QUIC connection + fix RFC 9000 Section 10 bug (leanEthereum#529)
* refactor: simplify testing framework with proper OOP design Move building logic from fixture classes to spec types where it belongs. Each spec type now owns the methods that operate on its own fields: - BlockSpec: resolve_proposer_index, resolve_parent_root, build_attestations, build_signed_block, build_signed_block_with_store - AggregatedAttestationSpec: build_attestation_data, build_invalid_proof - GossipAttestationSpec: build_attestation_data, build_signed - GossipAggregatedAttestationSpec: build_attestation_data, build_signed Fixture files are now pure orchestration (~357 lines for fork_choice, ~144 for verify_signatures). Also: - Fix double fixture registration bug in BaseFixture - Fix assert tuple bug in genesis.py - Move expect_exception field + serializer to BaseConsensusFixture - Rewrite StoreChecks.validate_against_store with explicit checks - Remove dispatch tables and unused arguments - Convert all non-self methods to @staticmethod - Modernize typing imports (dict, list, type, set) - Delete dead code (_children, supports_fork, transitions_to) - Add XmssKeyManager.sign_and_aggregate for common pattern - Create test_types/utils.py for shared resolve_checkpoint - Update doc-writer agent rules for better documentation quality - Show full hex in error messages instead of truncated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add 100% coverage for QUIC connection module + fix RFC 9000 bug Closes leanEthereum#516. Adds 38 new tests (76 total) achieving 100% isolated coverage for quic/connection.py (274 statements, 74 branches, 0 missing). Fixes a spec violation: ConnectionTerminated was signaling FIN (clean end-of-stream) on all open streams. Per RFC 9000 Section 10, connection termination implicitly resets all streams — data may have been lost. Changed to _receive_reset() so pending reads raise an error instead of returning empty bytes that falsely imply successful delivery. Also clarifies the doc-writer agent rule that line-by-line documentation applies identically to test code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fb50720 commit d3118f5

3 files changed

Lines changed: 658 additions & 10 deletions

File tree

.claude/agents/doc-writer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ That belongs in the inline comments.
5050

5151
### 4. Line-by-line documentation inside every function body
5252

53-
This is **the most important rule**. Every logical step gets a comment block BEFORE it.
53+
This is **the most important rule**. Every logical step gets a comment block BEFORE it. This applies everywhere: spec code, utility code, **and test code**. Tests are functions — the same rules apply without exception.
5454

5555
Each comment block:
5656
- Starts with a short summary line

src/lean_spec/subspecs/networking/transport/quic/connection.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,15 @@ def _handle_event(self, event: QuicEvent) -> None:
342342

343343
elif isinstance(event, ConnectionTerminated):
344344
self._closed = True
345-
# Signal all waiting streams.
345+
346+
# Per RFC 9000 Section 10, connection termination implicitly
347+
# resets all open streams — data may have been lost.
348+
#
349+
# Using _receive_reset (not _receive_end) ensures that pending
350+
# reads raise an error instead of returning empty bytes, which
351+
# would falsely imply a clean end-of-stream.
346352
for stream in self._streams.values():
347-
stream._receive_end()
353+
stream._receive_reset(event.error_code)
348354

349355

350356
class LibP2PQuicProtocol(QuicConnectionProtocol):

0 commit comments

Comments
 (0)