Skip to content

Test/p2p handler coverage#822

Open
liam wants to merge 7 commits intobsv-blockchain:mainfrom
liam:test/p2p-handler-coverage
Open

Test/p2p handler coverage#822
liam wants to merge 7 commits intobsv-blockchain:mainfrom
liam:test/p2p-handler-coverage

Conversation

@liam
Copy link
Copy Markdown
Collaborator

@liam liam commented May 6, 2026

No description provided.

liam added 7 commits May 5, 2026 14:08
handleNodeStatusTopic was at 39.1% — only happy paths and the size
guard ran. Six focused unit tests cover the validation branches:

- bad JSON: no notification, no peer state mutation
- peer ID spoofing: sender peer != claimed peer, ban score +20, no notif
- invalid BaseURL: SSRF rejection (loopback), ban score +20, no notif
- invalid BestBlockHash: notification fires before parse, peer height
  not updated
- notification channel full: unbuffered chan exercises default branch
- storage-update side effect: Storage="full" reaches the registry

Lifts handleNodeStatusTopic 39.1% -> 89.1% and updateStorage
0% -> 100%. Package total 73.9% -> 74.9%.
shouldSkipDuringSync was at 17.6% — only the no-sync-peer return ran.
Six tests for each exit path:

- no sync peer: syncCoordinator nil -> false
- not syncing: FSM RUNNING -> false
- announcement below sync peer height -> true
- announcement from non-sync peer -> true
- originator string fails to decode -> true (error short-circuit)
- happy path: syncing, height ok, sender == sync peer -> false

Lifts shouldSkipDuringSync 17.6% -> 100%. Package total 74.9% -> 75.1%.
Both functions were unexercised: handleBanEvent at 36.4% (only the
non-add early return ran via integration), disconnectBannedPeerByID
at 0%.

Six tests across the dispatch chain:

- handleBanEvent: non-add action, empty PeerID, invalid PeerID decode,
  valid PeerID dispatching to disconnectBannedPeerByID
- disconnectBannedPeerByID: peer found in connected list (registry
  removal), peer not in connected list (no mutation)

MockServerP2PClient.GetPeers gains an optional peers field for tests
that need to drive specific connected-peer lists. Existing callers
fall through to the previous empty-PeerInfo default.

Lifts handleBanEvent 36.4% -> 100%, disconnectBannedPeerByID 0% -> 100%.
Package total 75.1% -> 75.7%.
Apply gofmt to mock.go (struct field alignment) and reorder imports in
server_handler_test.go (alphabetical: go-bt before go-p2p-message-bus).
Adds the missing blank line before the merged-in cleanup tests block.
Sixteen Client.go methods sat at 0% coverage — none of the catchup
recording, reputation update, validity reporting, peer-info, or
byte-accounting wrappers had unit tests. The wrappers are uniform:
build proto, call gRPC, propagate gRPC errors, return service error
on Ok/Success false, otherwise return nil.

Tests cover the three exit paths per method using the existing
MockPeerServiceClient pattern:

- ok / grpc_error / not_ok for: RecordCatchupAttempt, RecordCatchupSuccess,
  RecordCatchupFailure, RecordCatchupMalicious, UpdateCatchupError,
  UpdateCatchupReputation, RecordBytesDownloaded
- ok_specific_peer / ok_all_peers / grpc_error / not_ok for ResetReputation
- ok / grpc_error / not_success for ReportValidSubtree, ReportValidBlock
- ok / grpc_error for GetPeersForCatchup, GetPeerRegistry, IsPeerMalicious,
  IsPeerUnhealthy
- found / not_found / grpc_error for GetPeer

MockPeerServiceClient gains a RecordBytesDownloadedFunc field — the
existing method always returned Ok=true, blocking error/!ok testing.
The fallback preserves the prior behaviour.

Coverage: each of the 16 wrappers 0% -> 100%, package total 75.7% -> 80.1%.
NewClient / NewClientWithAddress remain at 0% (real gRPC dial, out of
scope for unit tests).
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🤖 Claude Code Review

Status: Complete


Current Review:

This PR adds comprehensive test coverage for P2P Client gRPC wrapper methods and Server handler functions. The changes are test-only and follow consistent patterns.

Summary:

  • Client_test.go: Adds 473 lines covering all gRPC wrapper methods (catchup recording, reputation management, peer queries, subtree/block reporting)
  • server_handler_test.go: Adds 378 lines covering edge cases in handleNodeStatusTopic, shouldSkipDuringSync, handleBanEvent, and disconnectBannedPeerByID
  • mock.go: Minor enhancement to MockServerP2PClient for flexible peer list testing

Quality observations:

  • Tests follow the three-path pattern (ok/grpc_error/not_ok or not_success) consistently
  • Good coverage of validation branches: JSON parsing errors, peer ID spoofing, SSRF checks, invalid hashes
  • Edge cases properly tested: channel full, storage updates, sync coordinator logic
  • Mock enhancements are minimal and safe

No issues found. The tests are well-structured, defensive, and align with the project's testing standards in AGENTS.md.


This is an advisory review. Human reviewers make final approval decisions.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 6, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Benchmark Comparison Report

Baseline: main (unknown)

Current: PR-822 (67a58a2)

Summary

  • Regressions: 0
  • Improvements: 0
  • Unchanged: 142
  • Significance level: p < 0.05
All benchmark results (sec/op)
Benchmark Baseline Current Change p-value
_NewBlockFromBytes-4 1.703µ 1.685µ ~ 0.100
SplitSyncedParentMap_SetIfNotExists/256_buckets-4 61.66n 63.47n ~ 0.700
SplitSyncedParentMap_SetIfNotExists/16_buckets-4 61.68n 61.72n ~ 0.400
SplitSyncedParentMap_SetIfNotExists/1_bucket-4 61.68n 61.78n ~ 0.700
SplitSyncedParentMap_ConcurrentSetIfNotExists/256_buckets... 34.09n 33.16n ~ 0.500
SplitSyncedParentMap_ConcurrentSetIfNotExists/16_buckets_... 58.55n 54.58n ~ 0.200
SplitSyncedParentMap_ConcurrentSetIfNotExists/1_bucket_pa... 149.9n 140.9n ~ 0.400
MiningCandidate_Stringify_Short-4 269.4n 267.2n ~ 0.100
MiningCandidate_Stringify_Long-4 1.943µ 1.924µ ~ 0.700
MiningSolution_Stringify-4 990.4n 994.6n ~ 1.000
BlockInfo_MarshalJSON-4 1.810µ 1.784µ ~ 0.500
NewFromBytes-4 126.3n 130.2n ~ 0.200
Mine_EasyDifficulty-4 67.36µ 67.32µ ~ 0.700
Mine_WithAddress-4 7.061µ 6.935µ ~ 0.700
DirectSubtreeAdd/4_per_subtree-4 60.84n 62.04n ~ 1.000
DirectSubtreeAdd/64_per_subtree-4 28.78n 28.29n ~ 0.200
DirectSubtreeAdd/256_per_subtree-4 27.32n 26.82n ~ 0.100
DirectSubtreeAdd/1024_per_subtree-4 26.20n 25.94n ~ 0.100
DirectSubtreeAdd/2048_per_subtree-4 25.89n 25.64n ~ 0.100
SubtreeProcessorAdd/4_per_subtree-4 279.4n 278.7n ~ 0.500
SubtreeProcessorAdd/64_per_subtree-4 270.3n 272.9n ~ 0.300
SubtreeProcessorAdd/256_per_subtree-4 275.5n 275.4n ~ 1.000
SubtreeProcessorAdd/1024_per_subtree-4 267.1n 265.8n ~ 0.100
SubtreeProcessorAdd/2048_per_subtree-4 267.6n 267.2n ~ 0.300
SubtreeProcessorRotate/4_per_subtree-4 272.6n 275.2n ~ 0.200
SubtreeProcessorRotate/64_per_subtree-4 270.8n 270.2n ~ 0.700
SubtreeProcessorRotate/256_per_subtree-4 270.8n 271.4n ~ 0.400
SubtreeProcessorRotate/1024_per_subtree-4 270.6n 270.6n ~ 1.000
SubtreeNodeAddOnly/4_per_subtree-4 54.42n 53.96n ~ 0.200
SubtreeNodeAddOnly/64_per_subtree-4 34.50n 34.44n ~ 1.000
SubtreeNodeAddOnly/256_per_subtree-4 33.51n 33.37n ~ 0.200
SubtreeNodeAddOnly/1024_per_subtree-4 32.71n 32.77n ~ 0.700
SubtreeCreationOnly/4_per_subtree-4 112.3n 111.8n ~ 0.100
SubtreeCreationOnly/64_per_subtree-4 396.3n 391.4n ~ 0.200
SubtreeCreationOnly/256_per_subtree-4 1.333µ 1.427µ ~ 0.100
SubtreeCreationOnly/1024_per_subtree-4 4.384µ 4.598µ ~ 0.200
SubtreeCreationOnly/2048_per_subtree-4 8.038µ 8.113µ ~ 0.400
SubtreeProcessorOverheadBreakdown/64_per_subtree-4 270.3n 270.9n ~ 1.000
SubtreeProcessorOverheadBreakdown/1024_per_subtree-4 269.3n 270.2n ~ 0.200
ParallelGetAndSetIfNotExists/1k_nodes-4 585.4µ 582.2µ ~ 1.000
ParallelGetAndSetIfNotExists/10k_nodes-4 1.327m 1.387m ~ 0.100
ParallelGetAndSetIfNotExists/50k_nodes-4 6.674m 6.698m ~ 0.100
ParallelGetAndSetIfNotExists/100k_nodes-4 13.49m 13.39m ~ 0.700
SequentialGetAndSetIfNotExists/1k_nodes-4 655.1µ 680.5µ ~ 0.100
SequentialGetAndSetIfNotExists/10k_nodes-4 2.755m 2.780m ~ 1.000
SequentialGetAndSetIfNotExists/50k_nodes-4 10.48m 10.51m ~ 0.400
SequentialGetAndSetIfNotExists/100k_nodes-4 20.38m 19.86m ~ 0.700
ProcessOwnBlockSubtreeNodesParallel/1k_nodes-4 631.9µ 623.9µ ~ 0.100
ProcessOwnBlockSubtreeNodesParallel/10k_nodes-4 4.189m 4.141m ~ 0.400
ProcessOwnBlockSubtreeNodesParallel/100k_nodes-4 16.43m 16.48m ~ 0.700
ProcessOwnBlockSubtreeNodesSequential/1k_nodes-4 684.6µ 694.1µ ~ 0.200
ProcessOwnBlockSubtreeNodesSequential/10k_nodes-4 5.679m 5.671m ~ 0.700
ProcessOwnBlockSubtreeNodesSequential/100k_nodes-4 38.11m 38.45m ~ 0.100
DiskTxMap_SetIfNotExists-4 3.538µ 3.559µ ~ 0.700
DiskTxMap_SetIfNotExists_Parallel-4 3.593µ 3.461µ ~ 1.000
DiskTxMap_ExistenceOnly-4 308.8n 307.2n ~ 0.400
Queue-4 191.9n 193.4n ~ 0.600
AtomicPointer-4 4.303n 4.150n ~ 1.000
ReorgOptimizations/DedupFilterPipeline/Old/10K-4 875.0µ 913.0µ ~ 0.200
ReorgOptimizations/DedupFilterPipeline/New/10K-4 828.6µ 882.4µ ~ 0.100
ReorgOptimizations/AllMarkFalse/Old/10K-4 113.9µ 115.1µ ~ 0.700
ReorgOptimizations/AllMarkFalse/New/10K-4 61.66µ 61.83µ ~ 0.800
ReorgOptimizations/HashSlicePool/Old/10K-4 70.02µ 62.85µ ~ 0.100
ReorgOptimizations/HashSlicePool/New/10K-4 11.62µ 12.01µ ~ 0.700
ReorgOptimizations/NodeFlags/Old/10K-4 5.909µ 5.838µ ~ 0.200
ReorgOptimizations/NodeFlags/New/10K-4 2.350µ 2.312µ ~ 0.100
ReorgOptimizations/DedupFilterPipeline/Old/100K-4 10.13m 10.13m ~ 1.000
ReorgOptimizations/DedupFilterPipeline/New/100K-4 9.947m 10.079m ~ 0.400
ReorgOptimizations/AllMarkFalse/Old/100K-4 1.104m 1.159m ~ 0.100
ReorgOptimizations/AllMarkFalse/New/100K-4 682.8µ 678.6µ ~ 0.100
ReorgOptimizations/HashSlicePool/Old/100K-4 696.9µ 687.6µ ~ 1.000
ReorgOptimizations/HashSlicePool/New/100K-4 338.4µ 339.2µ ~ 0.700
ReorgOptimizations/NodeFlags/Old/100K-4 55.80µ 56.74µ ~ 0.100
ReorgOptimizations/NodeFlags/New/100K-4 19.63µ 19.38µ ~ 0.700
TxMapSetIfNotExists-4 52.03n 51.53n ~ 0.400
TxMapSetIfNotExistsDuplicate-4 38.25n 38.13n ~ 0.400
ChannelSendReceive-4 627.0n 607.8n ~ 0.100
BlockAssembler_AddTx-4 0.02388n 0.02379n ~ 0.700
AddNode-4 8.511 8.897 ~ 0.400
AddNodeWithMap-4 8.701 8.508 ~ 1.000
CalcBlockWork-4 368.9n 372.3n ~ 0.400
CalculateWork-4 490.6n 493.2n ~ 1.000
BuildBlockLocatorString_Helpers/Size_10-4 1.042µ 1.035µ ~ 1.000
BuildBlockLocatorString_Helpers/Size_100-4 9.812µ 9.917µ ~ 0.100
BuildBlockLocatorString_Helpers/Size_1000-4 122.1µ 119.9µ ~ 1.000
CatchupWithHeaderCache-4 103.8m 103.7m ~ 0.700
_BufferPoolAllocation/16KB-4 3.561µ 3.542µ ~ 1.000
_BufferPoolAllocation/32KB-4 7.098µ 8.819µ ~ 0.100
_BufferPoolAllocation/64KB-4 17.63µ 16.36µ ~ 0.700
_BufferPoolAllocation/128KB-4 29.31µ 29.27µ ~ 0.700
_BufferPoolAllocation/512KB-4 117.9µ 122.7µ ~ 0.400
_BufferPoolConcurrent/32KB-4 19.56µ 19.78µ ~ 0.400
_BufferPoolConcurrent/64KB-4 29.26µ 31.37µ ~ 0.400
_BufferPoolConcurrent/512KB-4 156.7µ 146.1µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/16KB-4 684.6µ 608.4µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/32KB-4 673.1µ 621.8µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/64KB-4 676.5µ 635.6µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/128KB-4 653.4µ 618.7µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/512KB-4 642.2µ 633.0µ ~ 0.200
_SubtreeDataDeserializationWithBufferSizes/16KB-4 35.47m 35.94m ~ 0.100
_SubtreeDataDeserializationWithBufferSizes/32KB-4 35.22m 35.71m ~ 0.100
_SubtreeDataDeserializationWithBufferSizes/64KB-4 35.66m 35.81m ~ 0.200
_SubtreeDataDeserializationWithBufferSizes/128KB-4 35.62m 35.75m ~ 0.100
_SubtreeDataDeserializationWithBufferSizes/512KB-4 34.90m 35.69m ~ 0.100
_PooledVsNonPooled/Pooled-4 736.3n 737.3n ~ 0.700
_PooledVsNonPooled/NonPooled-4 6.989µ 6.925µ ~ 0.700
_MemoryFootprint/Current_512KB_32concurrent-4 6.516µ 7.041µ ~ 0.100
_MemoryFootprint/Proposed_32KB_32concurrent-4 9.394µ 9.631µ ~ 1.000
_MemoryFootprint/Alternative_64KB_32concurrent-4 8.787µ 9.105µ ~ 0.100
_prepareTxsPerLevel-4 411.1m 414.2m ~ 1.000
_prepareTxsPerLevelOrdered-4 3.689m 3.766m ~ 0.400
_prepareTxsPerLevel_Comparison/Original-4 416.6m 417.7m ~ 0.400
_prepareTxsPerLevel_Comparison/Optimized-4 3.539m 3.528m ~ 1.000
SubtreeSizes/10k_tx_4_per_subtree-4 1.252m 1.227m ~ 0.400
SubtreeSizes/10k_tx_16_per_subtree-4 294.3µ 290.8µ ~ 0.700
SubtreeSizes/10k_tx_64_per_subtree-4 69.68µ 70.85µ ~ 0.100
SubtreeSizes/10k_tx_256_per_subtree-4 17.43µ 17.46µ ~ 1.000
SubtreeSizes/10k_tx_512_per_subtree-4 8.648µ 8.671µ ~ 1.000
SubtreeSizes/10k_tx_1024_per_subtree-4 4.286µ 4.293µ ~ 1.000
SubtreeSizes/10k_tx_2k_per_subtree-4 2.155µ 2.149µ ~ 0.300
BlockSizeScaling/10k_tx_64_per_subtree-4 68.46µ 68.96µ ~ 0.700
BlockSizeScaling/10k_tx_256_per_subtree-4 17.09µ 17.43µ ~ 0.200
BlockSizeScaling/10k_tx_1024_per_subtree-4 4.246µ 4.305µ ~ 0.500
BlockSizeScaling/50k_tx_64_per_subtree-4 359.3µ 363.2µ ~ 0.700
BlockSizeScaling/50k_tx_256_per_subtree-4 85.84µ 88.76µ ~ 0.100
BlockSizeScaling/50k_tx_1024_per_subtree-4 21.18µ 21.25µ ~ 0.700
SubtreeAllocations/small_subtrees_exists_check-4 147.6µ 146.5µ ~ 0.700
SubtreeAllocations/small_subtrees_data_fetch-4 154.8µ 156.0µ ~ 0.700
SubtreeAllocations/small_subtrees_full_validation-4 306.8µ 305.1µ ~ 1.000
SubtreeAllocations/medium_subtrees_exists_check-4 8.735µ 8.713µ ~ 0.200
SubtreeAllocations/medium_subtrees_data_fetch-4 9.074µ 9.129µ ~ 0.400
SubtreeAllocations/medium_subtrees_full_validation-4 17.41µ 17.27µ ~ 0.700
SubtreeAllocations/large_subtrees_exists_check-4 2.124µ 2.084µ ~ 0.200
SubtreeAllocations/large_subtrees_data_fetch-4 2.185µ 2.234µ ~ 0.100
SubtreeAllocations/large_subtrees_full_validation-4 4.282µ 4.341µ ~ 0.200
StoreBlock_Sequential/BelowCSVHeight-4 327.6µ 334.5µ ~ 0.400
StoreBlock_Sequential/AboveCSVHeight-4 329.1µ 340.8µ ~ 0.200
GetUtxoHashes-4 315.4n 319.0n ~ 0.500
GetUtxoHashes_ManyOutputs-4 54.16µ 52.94µ ~ 0.100
_NewMetaDataFromBytes-4 267.5n 267.3n ~ 1.000
_Bytes-4 696.5n 699.7n ~ 0.700
_MetaBytes-4 643.0n 639.2n ~ 0.700

Threshold: >10% with p < 0.05 | Generated: 2026-05-06 16:30 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant