Skip to content

Test/p2p handler coverage#822

Merged
liam merged 8 commits into
bsv-blockchain:mainfrom
liam:test/p2p-handler-coverage
May 12, 2026
Merged

Test/p2p handler coverage#822
liam merged 8 commits into
bsv-blockchain:mainfrom
liam:test/p2p-handler-coverage

Conversation

@liam

@liam liam commented May 6, 2026

Copy link
Copy Markdown
Collaborator

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

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Status: Complete

Current Review:

No issues found. This PR adds thorough test coverage for P2P client wrapper methods with:

  • Systematic testing of success, gRPC error, and failure response paths for all catchup/reputation methods
  • Proper verification of request parameters passed to mock gRPC client
  • Consistent test patterns following existing conventions
  • Good helper function extraction (newClientWithMock)

The tests correctly validate the three-way error handling in Client.go (gRPC errors, !Ok responses, Success flags) and verify data transformations in GetPeer/GetPeerRegistry/GetPeersForCatchup.

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Benchmark Comparison Report

Baseline: main (unknown)

Current: PR-822 (ebd4b4d)

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.579µ 1.571µ ~ 0.600
SplitSyncedParentMap_SetIfNotExists/256_buckets-4 71.16n 71.38n ~ 0.400
SplitSyncedParentMap_SetIfNotExists/16_buckets-4 71.39n 71.49n ~ 0.700
SplitSyncedParentMap_SetIfNotExists/1_bucket-4 71.24n 71.15n ~ 0.600
SplitSyncedParentMap_ConcurrentSetIfNotExists/256_buckets... 34.86n 33.14n ~ 0.100
SplitSyncedParentMap_ConcurrentSetIfNotExists/16_buckets_... 56.48n 55.88n ~ 0.700
SplitSyncedParentMap_ConcurrentSetIfNotExists/1_bucket_pa... 128.8n 132.8n ~ 0.700
MiningCandidate_Stringify_Short-4 219.3n 217.6n ~ 0.100
MiningCandidate_Stringify_Long-4 1.658µ 1.642µ ~ 0.200
MiningSolution_Stringify-4 863.5n 858.5n ~ 0.200
BlockInfo_MarshalJSON-4 1.759µ 1.743µ ~ 0.100
NewFromBytes-4 128.0n 127.6n ~ 0.800
Mine_EasyDifficulty-4 60.66µ 60.64µ ~ 1.000
Mine_WithAddress-4 6.692µ 6.705µ ~ 0.700
BlockAssembler_AddTx-4 0.02862n 0.02752n ~ 0.400
AddNode-4 10.65 10.78 ~ 0.700
AddNodeWithMap-4 10.87 10.57 ~ 0.700
DirectSubtreeAdd/4_per_subtree-4 59.88n 60.31n ~ 1.000
DirectSubtreeAdd/64_per_subtree-4 28.35n 28.95n ~ 0.400
DirectSubtreeAdd/256_per_subtree-4 27.32n 27.32n ~ 1.000
DirectSubtreeAdd/1024_per_subtree-4 26.20n 26.34n ~ 0.100
DirectSubtreeAdd/2048_per_subtree-4 25.98n 25.91n ~ 0.700
SubtreeProcessorAdd/4_per_subtree-4 281.5n 281.2n ~ 0.400
SubtreeProcessorAdd/64_per_subtree-4 275.2n 273.2n ~ 0.400
SubtreeProcessorAdd/256_per_subtree-4 274.4n 275.4n ~ 1.000
SubtreeProcessorAdd/1024_per_subtree-4 270.5n 266.6n ~ 0.100
SubtreeProcessorAdd/2048_per_subtree-4 269.0n 266.4n ~ 0.100
SubtreeProcessorRotate/4_per_subtree-4 275.3n 273.4n ~ 0.100
SubtreeProcessorRotate/64_per_subtree-4 273.2n 271.4n ~ 0.200
SubtreeProcessorRotate/256_per_subtree-4 273.5n 272.3n ~ 0.100
SubtreeProcessorRotate/1024_per_subtree-4 271.1n 270.4n ~ 1.000
SubtreeNodeAddOnly/4_per_subtree-4 54.14n 54.33n ~ 0.200
SubtreeNodeAddOnly/64_per_subtree-4 34.36n 34.47n ~ 0.700
SubtreeNodeAddOnly/256_per_subtree-4 33.54n 33.40n ~ 0.800
SubtreeNodeAddOnly/1024_per_subtree-4 32.78n 32.77n ~ 1.000
SubtreeCreationOnly/4_per_subtree-4 112.4n 112.6n ~ 1.000
SubtreeCreationOnly/64_per_subtree-4 396.0n 392.8n ~ 0.700
SubtreeCreationOnly/256_per_subtree-4 1.330µ 1.339µ ~ 0.700
SubtreeCreationOnly/1024_per_subtree-4 4.383µ 4.401µ ~ 1.000
SubtreeCreationOnly/2048_per_subtree-4 8.026µ 8.042µ ~ 0.700
SubtreeProcessorOverheadBreakdown/64_per_subtree-4 268.8n 271.2n ~ 1.000
SubtreeProcessorOverheadBreakdown/1024_per_subtree-4 271.1n 270.6n ~ 1.000
ParallelGetAndSetIfNotExists/1k_nodes-4 806.2µ 812.2µ ~ 0.700
ParallelGetAndSetIfNotExists/10k_nodes-4 1.597m 1.542m ~ 0.100
ParallelGetAndSetIfNotExists/50k_nodes-4 6.871m 6.665m ~ 0.100
ParallelGetAndSetIfNotExists/100k_nodes-4 13.75m 13.42m ~ 0.200
SequentialGetAndSetIfNotExists/1k_nodes-4 660.9µ 655.7µ ~ 0.400
SequentialGetAndSetIfNotExists/10k_nodes-4 2.743m 2.776m ~ 0.400
SequentialGetAndSetIfNotExists/50k_nodes-4 10.35m 10.43m ~ 0.100
SequentialGetAndSetIfNotExists/100k_nodes-4 20.16m 19.87m ~ 0.100
ProcessOwnBlockSubtreeNodesParallel/1k_nodes-4 636.4µ 629.0µ ~ 0.100
ProcessOwnBlockSubtreeNodesParallel/10k_nodes-4 4.212m 4.171m ~ 0.400
ProcessOwnBlockSubtreeNodesParallel/100k_nodes-4 16.61m 16.41m ~ 0.100
ProcessOwnBlockSubtreeNodesSequential/1k_nodes-4 711.8µ 690.7µ ~ 0.100
ProcessOwnBlockSubtreeNodesSequential/10k_nodes-4 5.713m 5.744m ~ 1.000
ProcessOwnBlockSubtreeNodesSequential/100k_nodes-4 37.53m 37.55m ~ 1.000
DiskTxMap_SetIfNotExists-4 3.564µ 4.071µ ~ 0.100
DiskTxMap_SetIfNotExists_Parallel-4 3.359µ 3.801µ ~ 0.100
DiskTxMap_ExistenceOnly-4 301.5n 302.9n ~ 0.700
Queue-4 199.3n 196.4n ~ 0.700
AtomicPointer-4 4.750n 4.632n ~ 0.700
ReorgOptimizations/DedupFilterPipeline/Old/10K-4 854.1µ 878.3µ ~ 0.100
ReorgOptimizations/DedupFilterPipeline/New/10K-4 837.0µ 873.0µ ~ 0.700
ReorgOptimizations/AllMarkFalse/Old/10K-4 108.5µ 121.9µ ~ 0.100
ReorgOptimizations/AllMarkFalse/New/10K-4 62.07µ 62.18µ ~ 0.700
ReorgOptimizations/HashSlicePool/Old/10K-4 68.01µ 74.44µ ~ 0.400
ReorgOptimizations/HashSlicePool/New/10K-4 12.41µ 11.82µ ~ 0.400
ReorgOptimizations/NodeFlags/Old/10K-4 5.231µ 5.232µ ~ 1.000
ReorgOptimizations/NodeFlags/New/10K-4 1.775µ 1.819µ ~ 0.200
ReorgOptimizations/DedupFilterPipeline/Old/100K-4 9.818m 9.811m ~ 1.000
ReorgOptimizations/DedupFilterPipeline/New/100K-4 9.339m 9.769m ~ 0.400
ReorgOptimizations/AllMarkFalse/Old/100K-4 1.063m 1.077m ~ 1.000
ReorgOptimizations/AllMarkFalse/New/100K-4 678.9µ 687.9µ ~ 0.100
ReorgOptimizations/HashSlicePool/Old/100K-4 669.1µ 654.1µ ~ 0.700
ReorgOptimizations/HashSlicePool/New/100K-4 305.2µ 337.9µ ~ 0.100
ReorgOptimizations/NodeFlags/Old/100K-4 56.06µ 55.91µ ~ 1.000
ReorgOptimizations/NodeFlags/New/100K-4 19.84µ 19.94µ ~ 0.700
TxMapSetIfNotExists-4 51.75n 51.34n ~ 0.400
TxMapSetIfNotExistsDuplicate-4 38.20n 38.34n ~ 0.400
ChannelSendReceive-4 576.7n 622.4n ~ 0.100
CalcBlockWork-4 545.5n 555.4n ~ 0.400
CalculateWork-4 753.3n 736.1n ~ 0.200
BuildBlockLocatorString_Helpers/Size_10-4 1.296µ 1.294µ ~ 1.000
BuildBlockLocatorString_Helpers/Size_100-4 14.36µ 12.45µ ~ 0.400
BuildBlockLocatorString_Helpers/Size_1000-4 122.5µ 122.8µ ~ 0.400
CatchupWithHeaderCache-4 104.0m 104.3m ~ 0.700
SubtreeSizes/10k_tx_4_per_subtree-4 1.339m 1.363m ~ 0.400
SubtreeSizes/10k_tx_16_per_subtree-4 309.4µ 306.7µ ~ 0.700
SubtreeSizes/10k_tx_64_per_subtree-4 72.27µ 73.48µ ~ 0.700
SubtreeSizes/10k_tx_256_per_subtree-4 18.24µ 18.38µ ~ 0.100
SubtreeSizes/10k_tx_512_per_subtree-4 9.050µ 9.052µ ~ 0.500
SubtreeSizes/10k_tx_1024_per_subtree-4 4.507µ 4.502µ ~ 1.000
SubtreeSizes/10k_tx_2k_per_subtree-4 2.223µ 2.252µ ~ 0.700
BlockSizeScaling/10k_tx_64_per_subtree-4 70.91µ 70.60µ ~ 0.700
BlockSizeScaling/10k_tx_256_per_subtree-4 17.76µ 17.78µ ~ 1.000
BlockSizeScaling/10k_tx_1024_per_subtree-4 4.410µ 4.397µ ~ 0.100
BlockSizeScaling/50k_tx_64_per_subtree-4 377.2µ 386.7µ ~ 0.700
BlockSizeScaling/50k_tx_256_per_subtree-4 89.71µ 88.80µ ~ 1.000
BlockSizeScaling/50k_tx_1024_per_subtree-4 21.73µ 21.96µ ~ 0.700
SubtreeAllocations/small_subtrees_exists_check-4 153.3µ 152.4µ ~ 0.700
SubtreeAllocations/small_subtrees_data_fetch-4 161.8µ 160.9µ ~ 0.400
SubtreeAllocations/small_subtrees_full_validation-4 309.6µ 312.5µ ~ 1.000
SubtreeAllocations/medium_subtrees_exists_check-4 9.011µ 8.991µ ~ 1.000
SubtreeAllocations/medium_subtrees_data_fetch-4 9.438µ 9.558µ ~ 0.400
SubtreeAllocations/medium_subtrees_full_validation-4 17.61µ 17.67µ ~ 1.000
SubtreeAllocations/large_subtrees_exists_check-4 2.129µ 2.105µ ~ 1.000
SubtreeAllocations/large_subtrees_data_fetch-4 2.262µ 2.269µ ~ 0.200
SubtreeAllocations/large_subtrees_full_validation-4 4.401µ 4.428µ ~ 1.000
_BufferPoolAllocation/16KB-4 3.590µ 3.425µ ~ 0.700
_BufferPoolAllocation/32KB-4 10.218µ 8.726µ ~ 0.700
_BufferPoolAllocation/64KB-4 16.77µ 16.65µ ~ 1.000
_BufferPoolAllocation/128KB-4 34.82µ 29.78µ ~ 0.400
_BufferPoolAllocation/512KB-4 124.8µ 125.1µ ~ 1.000
_BufferPoolConcurrent/32KB-4 19.45µ 18.35µ ~ 0.200
_BufferPoolConcurrent/64KB-4 29.56µ 28.39µ ~ 0.100
_BufferPoolConcurrent/512KB-4 183.4µ 169.0µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/16KB-4 781.6µ 713.6µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/32KB-4 792.4µ 716.2µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/64KB-4 760.1µ 705.9µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/128KB-4 776.6µ 708.5µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/512KB-4 768.3µ 721.3µ ~ 0.100
_SubtreeDataDeserializationWithBufferSizes/16KB-4 38.23m 38.30m ~ 1.000
_SubtreeDataDeserializationWithBufferSizes/32KB-4 38.26m 38.38m ~ 0.200
_SubtreeDataDeserializationWithBufferSizes/64KB-4 38.55m 38.22m ~ 0.200
_SubtreeDataDeserializationWithBufferSizes/128KB-4 38.30m 38.37m ~ 0.400
_SubtreeDataDeserializationWithBufferSizes/512KB-4 38.15m 38.04m ~ 0.100
_PooledVsNonPooled/Pooled-4 824.9n 821.7n ~ 0.100
_PooledVsNonPooled/NonPooled-4 7.566µ 7.067µ ~ 0.700
_MemoryFootprint/Current_512KB_32concurrent-4 9.025µ 8.641µ ~ 0.100
_MemoryFootprint/Proposed_32KB_32concurrent-4 13.00µ 12.63µ ~ 0.200
_MemoryFootprint/Alternative_64KB_32concurrent-4 11.68µ 12.78µ ~ 0.100
_prepareTxsPerLevel-4 388.1m 382.8m ~ 0.400
_prepareTxsPerLevelOrdered-4 4.029m 3.871m ~ 0.700
_prepareTxsPerLevel_Comparison/Original-4 386.5m 385.1m ~ 0.700
_prepareTxsPerLevel_Comparison/Optimized-4 3.982m 4.152m ~ 0.100
StoreBlock_Sequential/BelowCSVHeight-4 333.0µ 333.2µ ~ 1.000
StoreBlock_Sequential/AboveCSVHeight-4 328.3µ 337.1µ ~ 1.000
GetUtxoHashes-4 256.9n 257.4n ~ 0.700
GetUtxoHashes_ManyOutputs-4 51.62µ 51.83µ ~ 0.700
_NewMetaDataFromBytes-4 247.1n 252.0n ~ 0.700
_Bytes-4 651.6n 643.4n ~ 0.700
_MetaBytes-4 590.1n 594.3n ~ 0.100

Threshold: >10% with p < 0.05 | Generated: 2026-05-12 12:01 UTC

@liam liam requested review from galt-tr and sugh01 May 7, 2026 13:27
@sonarqubecloud

Copy link
Copy Markdown

@liam liam merged commit 16c7e47 into bsv-blockchain:main May 12, 2026
25 checks passed
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.

3 participants