Skip to content

test: add coverage for network service event routing and publishing (64%) #514

@tcoratger

Description

@tcoratger

Summary

src/lean_spec/subspecs/networking/service/service.py has 64% test coverage — no test file exists. This module is the bridge between the network layer and the sync service, routing gossip events (blocks, attestations, peer status) and publishing locally-produced messages to peers.

Coverage stats:

File Statements Covered Coverage
networking/service/service.py 80 28 uncovered 64%

Uncovered lines: 109, 113–118, 160, 169–185, 201, 213–218, 233–238, 249–254

What needs testing

NetworkService — Event routing

run() (async main loop)

  • Normal event loop: Feed events through a mock EventSource, verify each is dispatched
  • Stop flag: Call stop() mid-loop, verify the loop exits cleanly
  • Source exhaustion: EventSource raises StopAsyncIteration, verify graceful termination
  • Running state: is_running transitions correctly during run/stop lifecycle

_handle_event() — Pattern matching dispatch

  • GossipBlockEvent: Verify sync_service.on_gossip_block() is called with correct args
  • GossipAttestationEvent: Verify sync_service.on_gossip_attestation() is called
  • GossipAggregatedAttestationEvent: Verify sync_service.on_gossip_aggregated_attestation() is called
  • PeerStatusEvent: Verify sync_service.on_peer_status() is called
  • PeerConnectedEvent: Verify peer is added to peer_manager and count logged
  • PeerDisconnectedEvent: Verify peer is removed from peer_manager

publish_block()

  • Happy path: Verify block is SSZ-encoded, snappy-compressed, and published to correct gossip topic
  • Topic format: Verify GossipTopic.block(fork_digest) produces correct topic ID

publish_attestation()

  • Happy path: Verify attestation published to correct subnet topic
  • Subnet routing: Different SubnetId values produce different topic IDs

publish_aggregated_attestation()

  • Happy path: Verify aggregated attestation published to committee aggregation topic

stop() / is_running

  • Lifecycle: Verify running flag transitions
  • Thread safety: stop() can be called before run() without error

Why this matters

  • Event routing correctness: If events are misrouted, blocks might be dropped or attestations lost
  • Publishing reliability: Incorrectly encoded or compressed messages will be rejected by peers
  • Topic correctness: Publishing to wrong gossip topics means messages never reach subscribers

How to test

Running tests with coverage

uv run pytest tests/lean_spec/subspecs/networking/service/test_service.py -v \
  --cov=src/lean_spec/subspecs/networking/service/service --cov-report=term-missing

Target: ≥90% line coverage.

Verifying with the coverage gate

uvx tox -e coverage-gate

Test file location

tests/lean_spec/subspecs/networking/service/test_service.py

Testing tips

  • Use a mock EventSource that yields predefined events (async iterator)
  • Mock SyncService to verify dispatch calls without needing real forkchoice logic
  • Mock snappy.compress and encode_bytes() to test publish methods without real SSZ
  • Use pytest-asyncio for async tests

Using Claude Code subagents

1. code-tester agent — Generate the tests

Generate unit tests for src/lean_spec/subspecs/networking/service/service.py. Cover the event routing dispatch for all 6 event types, the run() loop lifecycle (stop, source exhaustion), and all three publish methods (block, attestation, aggregated attestation). Use mock EventSource and SyncService.

2. doc-writer agent — Document the test module

Add documentation to the network service test file explaining the testing strategy for event dispatch and publish encoding.

Workflow

  1. Create mock EventSource and SyncService
  2. Test each event type dispatch independently
  3. Test publish methods with mocked encoding
  4. Test run() lifecycle (start, stop, source exhaustion)
  5. Run uvx tox -e all-checks to pass all quality checks

Metadata

Metadata

Assignees

Labels

good first issueGood for newcomerstestsScope: Changes to the spec tests

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions