gitlab.com/gpdionisio/tendermint@v0.34.19-dev2/blockchain/v1/pool_test.go (about) 1 package v1 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/stretchr/testify/assert" 8 9 "github.com/tendermint/tendermint/libs/log" 10 "github.com/tendermint/tendermint/p2p" 11 "github.com/tendermint/tendermint/types" 12 ) 13 14 type testPeer struct { 15 id p2p.ID 16 base int64 17 height int64 18 } 19 20 type testBcR struct { 21 logger log.Logger 22 } 23 24 type testValues struct { 25 numRequestsSent int 26 } 27 28 var testResults testValues 29 30 func resetPoolTestResults() { 31 testResults.numRequestsSent = 0 32 } 33 34 func (testR *testBcR) sendPeerError(err error, peerID p2p.ID) { 35 } 36 37 func (testR *testBcR) sendStatusRequest() { 38 } 39 40 func (testR *testBcR) sendBlockRequest(peerID p2p.ID, height int64) error { 41 testResults.numRequestsSent++ 42 return nil 43 } 44 45 func (testR *testBcR) resetStateTimer(name string, timer **time.Timer, timeout time.Duration) { 46 } 47 48 func (testR *testBcR) switchToConsensus() { 49 50 } 51 52 func newTestBcR() *testBcR { 53 testBcR := &testBcR{logger: log.TestingLogger()} 54 return testBcR 55 } 56 57 type tPBlocks struct { 58 id p2p.ID 59 create bool 60 } 61 62 // Makes a block pool with specified current height, list of peers, block requests and block responses 63 func makeBlockPool(bcr *testBcR, height int64, peers []BpPeer, blocks map[int64]tPBlocks) *BlockPool { 64 bPool := NewBlockPool(height, bcr) 65 bPool.SetLogger(bcr.logger) 66 67 txs := []types.Tx{types.Tx("foo"), types.Tx("bar")} 68 69 var maxH int64 70 for _, p := range peers { 71 if p.Height > maxH { 72 maxH = p.Height 73 } 74 bPool.peers[p.ID] = NewBpPeer(p.ID, p.Base, p.Height, bcr.sendPeerError, nil) 75 bPool.peers[p.ID].SetLogger(bcr.logger) 76 77 } 78 bPool.MaxPeerHeight = maxH 79 for h, p := range blocks { 80 bPool.blocks[h] = p.id 81 bPool.peers[p.id].RequestSent(h) 82 if p.create { 83 // simulate that a block at height h has been received 84 _ = bPool.peers[p.id].AddBlock(types.MakeBlock(h, txs, nil, nil), 100) 85 } 86 } 87 return bPool 88 } 89 90 func assertPeerSetsEquivalent(t *testing.T, set1 map[p2p.ID]*BpPeer, set2 map[p2p.ID]*BpPeer) { 91 assert.Equal(t, len(set1), len(set2)) 92 for peerID, peer1 := range set1 { 93 peer2 := set2[peerID] 94 assert.NotNil(t, peer2) 95 assert.Equal(t, peer1.NumPendingBlockRequests, peer2.NumPendingBlockRequests) 96 assert.Equal(t, peer1.Height, peer2.Height) 97 assert.Equal(t, peer1.Base, peer2.Base) 98 assert.Equal(t, len(peer1.blocks), len(peer2.blocks)) 99 for h, block1 := range peer1.blocks { 100 block2 := peer2.blocks[h] 101 // block1 and block2 could be nil if a request was made but no block was received 102 assert.Equal(t, block1, block2) 103 } 104 } 105 } 106 107 func assertBlockPoolEquivalent(t *testing.T, poolWanted, pool *BlockPool) { 108 assert.Equal(t, poolWanted.blocks, pool.blocks) 109 assertPeerSetsEquivalent(t, poolWanted.peers, pool.peers) 110 assert.Equal(t, poolWanted.MaxPeerHeight, pool.MaxPeerHeight) 111 assert.Equal(t, poolWanted.Height, pool.Height) 112 113 } 114 115 func TestBlockPoolUpdatePeer(t *testing.T) { 116 testBcR := newTestBcR() 117 118 tests := []struct { 119 name string 120 pool *BlockPool 121 args testPeer 122 poolWanted *BlockPool 123 errWanted error 124 }{ 125 { 126 name: "add a first short peer", 127 pool: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 128 args: testPeer{"P1", 0, 50}, 129 errWanted: errPeerTooShort, 130 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 131 }, 132 { 133 name: "add a first good peer", 134 pool: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 135 args: testPeer{"P1", 0, 101}, 136 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 101}}, map[int64]tPBlocks{}), 137 }, 138 { 139 name: "add a first good peer with base", 140 pool: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 141 args: testPeer{"P1", 10, 101}, 142 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Base: 10, Height: 101}}, map[int64]tPBlocks{}), 143 }, 144 { 145 name: "increase the height of P1 from 120 to 123", 146 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, map[int64]tPBlocks{}), 147 args: testPeer{"P1", 0, 123}, 148 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 123}}, map[int64]tPBlocks{}), 149 }, 150 { 151 name: "decrease the height of P1 from 120 to 110", 152 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, map[int64]tPBlocks{}), 153 args: testPeer{"P1", 0, 110}, 154 errWanted: errPeerLowersItsHeight, 155 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 156 }, 157 { 158 name: "decrease the height of P1 from 105 to 102 with blocks", 159 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 105}}, 160 map[int64]tPBlocks{ 161 100: {"P1", true}, 101: {"P1", true}, 102: {"P1", true}}), 162 args: testPeer{"P1", 0, 102}, 163 errWanted: errPeerLowersItsHeight, 164 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, 165 map[int64]tPBlocks{}), 166 }, 167 } 168 169 for _, tt := range tests { 170 tt := tt 171 t.Run(tt.name, func(t *testing.T) { 172 pool := tt.pool 173 err := pool.UpdatePeer(tt.args.id, tt.args.base, tt.args.height) 174 assert.Equal(t, tt.errWanted, err) 175 assert.Equal(t, tt.poolWanted.blocks, tt.pool.blocks) 176 assertPeerSetsEquivalent(t, tt.poolWanted.peers, tt.pool.peers) 177 assert.Equal(t, tt.poolWanted.MaxPeerHeight, tt.pool.MaxPeerHeight) 178 }) 179 } 180 } 181 182 func TestBlockPoolRemovePeer(t *testing.T) { 183 testBcR := newTestBcR() 184 185 type args struct { 186 peerID p2p.ID 187 err error 188 } 189 190 tests := []struct { 191 name string 192 pool *BlockPool 193 args args 194 poolWanted *BlockPool 195 }{ 196 { 197 name: "attempt to delete non-existing peer", 198 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, map[int64]tPBlocks{}), 199 args: args{"P99", nil}, 200 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, map[int64]tPBlocks{}), 201 }, 202 { 203 name: "delete the only peer without blocks", 204 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, map[int64]tPBlocks{}), 205 args: args{"P1", nil}, 206 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 207 }, 208 { 209 name: "delete the shortest of two peers without blocks", 210 pool: makeBlockPool( 211 testBcR, 212 100, 213 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 120}}, 214 map[int64]tPBlocks{}), 215 args: args{"P1", nil}, 216 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P2", Height: 120}}, map[int64]tPBlocks{}), 217 }, 218 { 219 name: "delete the tallest of two peers without blocks", 220 pool: makeBlockPool( 221 testBcR, 222 100, 223 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 120}}, 224 map[int64]tPBlocks{}), 225 args: args{"P2", nil}, 226 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 100}}, map[int64]tPBlocks{}), 227 }, 228 { 229 name: "delete the only peer with block requests sent and blocks received", 230 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, 231 map[int64]tPBlocks{100: {"P1", true}, 101: {"P1", false}}), 232 args: args{"P1", nil}, 233 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 234 }, 235 { 236 name: "delete the shortest of two peers with block requests sent and blocks received", 237 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}, {ID: "P2", Height: 200}}, 238 map[int64]tPBlocks{100: {"P1", true}, 101: {"P1", false}}), 239 args: args{"P1", nil}, 240 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P2", Height: 200}}, map[int64]tPBlocks{}), 241 }, 242 { 243 name: "delete the tallest of two peers with block requests sent and blocks received", 244 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}, {ID: "P2", Height: 110}}, 245 map[int64]tPBlocks{100: {"P1", true}, 101: {"P1", false}}), 246 args: args{"P1", nil}, 247 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P2", Height: 110}}, map[int64]tPBlocks{}), 248 }, 249 } 250 251 for _, tt := range tests { 252 tt := tt 253 t.Run(tt.name, func(t *testing.T) { 254 tt.pool.RemovePeer(tt.args.peerID, tt.args.err) 255 assertBlockPoolEquivalent(t, tt.poolWanted, tt.pool) 256 }) 257 } 258 } 259 260 func TestBlockPoolRemoveShortPeers(t *testing.T) { 261 testBcR := newTestBcR() 262 263 tests := []struct { 264 name string 265 pool *BlockPool 266 poolWanted *BlockPool 267 }{ 268 { 269 name: "no short peers", 270 pool: makeBlockPool(testBcR, 100, 271 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 110}, {ID: "P3", Height: 120}}, map[int64]tPBlocks{}), 272 poolWanted: makeBlockPool(testBcR, 100, 273 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 110}, {ID: "P3", Height: 120}}, map[int64]tPBlocks{}), 274 }, 275 276 { 277 name: "one short peer", 278 pool: makeBlockPool(testBcR, 100, 279 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 90}, {ID: "P3", Height: 120}}, map[int64]tPBlocks{}), 280 poolWanted: makeBlockPool(testBcR, 100, 281 []BpPeer{{ID: "P1", Height: 100}, {ID: "P3", Height: 120}}, map[int64]tPBlocks{}), 282 }, 283 284 { 285 name: "all short peers", 286 pool: makeBlockPool(testBcR, 100, 287 []BpPeer{{ID: "P1", Height: 90}, {ID: "P2", Height: 91}, {ID: "P3", Height: 92}}, map[int64]tPBlocks{}), 288 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 289 }, 290 } 291 292 for _, tt := range tests { 293 tt := tt 294 t.Run(tt.name, func(t *testing.T) { 295 pool := tt.pool 296 pool.removeShortPeers() 297 assertBlockPoolEquivalent(t, tt.poolWanted, tt.pool) 298 }) 299 } 300 } 301 302 func TestBlockPoolSendRequestBatch(t *testing.T) { 303 type testPeerResult struct { 304 id p2p.ID 305 numPendingBlockRequests int 306 } 307 308 testBcR := newTestBcR() 309 310 tests := []struct { 311 name string 312 pool *BlockPool 313 maxRequestsPerPeer int 314 expRequests map[int64]bool 315 expRequestsSent int 316 expPeerResults []testPeerResult 317 }{ 318 { 319 name: "one peer - send up to maxRequestsPerPeer block requests", 320 pool: makeBlockPool(testBcR, 10, []BpPeer{{ID: "P1", Height: 100}}, map[int64]tPBlocks{}), 321 maxRequestsPerPeer: 2, 322 expRequests: map[int64]bool{10: true, 11: true}, 323 expRequestsSent: 2, 324 expPeerResults: []testPeerResult{{id: "P1", numPendingBlockRequests: 2}}, 325 }, 326 { 327 name: "multiple peers - stops at gap between height and base", 328 pool: makeBlockPool(testBcR, 10, []BpPeer{ 329 {ID: "P1", Base: 1, Height: 12}, 330 {ID: "P2", Base: 15, Height: 100}, 331 }, map[int64]tPBlocks{}), 332 maxRequestsPerPeer: 10, 333 expRequests: map[int64]bool{10: true, 11: true, 12: true}, 334 expRequestsSent: 3, 335 expPeerResults: []testPeerResult{ 336 {id: "P1", numPendingBlockRequests: 3}, 337 {id: "P2", numPendingBlockRequests: 0}, 338 }, 339 }, 340 { 341 name: "n peers - send n*maxRequestsPerPeer block requests", 342 pool: makeBlockPool( 343 testBcR, 344 10, 345 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 346 map[int64]tPBlocks{}), 347 maxRequestsPerPeer: 2, 348 expRequests: map[int64]bool{10: true, 11: true}, 349 expRequestsSent: 4, 350 expPeerResults: []testPeerResult{ 351 {id: "P1", numPendingBlockRequests: 2}, 352 {id: "P2", numPendingBlockRequests: 2}}, 353 }, 354 } 355 356 for _, tt := range tests { 357 tt := tt 358 t.Run(tt.name, func(t *testing.T) { 359 resetPoolTestResults() 360 361 var pool = tt.pool 362 maxRequestsPerPeer = tt.maxRequestsPerPeer 363 pool.MakeNextRequests(10) 364 365 assert.Equal(t, tt.expRequestsSent, testResults.numRequestsSent) 366 for _, tPeer := range tt.expPeerResults { 367 var peer = pool.peers[tPeer.id] 368 assert.NotNil(t, peer) 369 assert.Equal(t, tPeer.numPendingBlockRequests, peer.NumPendingBlockRequests) 370 } 371 }) 372 } 373 } 374 375 func TestBlockPoolAddBlock(t *testing.T) { 376 testBcR := newTestBcR() 377 txs := []types.Tx{types.Tx("foo"), types.Tx("bar")} 378 379 type args struct { 380 peerID p2p.ID 381 block *types.Block 382 blockSize int 383 } 384 tests := []struct { 385 name string 386 pool *BlockPool 387 args args 388 poolWanted *BlockPool 389 errWanted error 390 }{ 391 {name: "block from unknown peer", 392 pool: makeBlockPool(testBcR, 10, []BpPeer{{ID: "P1", Height: 100}}, map[int64]tPBlocks{}), 393 args: args{ 394 peerID: "P2", 395 block: types.MakeBlock(int64(10), txs, nil, nil), 396 blockSize: 100, 397 }, 398 poolWanted: makeBlockPool(testBcR, 10, []BpPeer{{ID: "P1", Height: 100}}, map[int64]tPBlocks{}), 399 errWanted: errBadDataFromPeer, 400 }, 401 {name: "unexpected block 11 from known peer - waiting for 10", 402 pool: makeBlockPool(testBcR, 10, 403 []BpPeer{{ID: "P1", Height: 100}}, 404 map[int64]tPBlocks{10: {"P1", false}}), 405 args: args{ 406 peerID: "P1", 407 block: types.MakeBlock(int64(11), txs, nil, nil), 408 blockSize: 100, 409 }, 410 poolWanted: makeBlockPool(testBcR, 10, 411 []BpPeer{{ID: "P1", Height: 100}}, 412 map[int64]tPBlocks{10: {"P1", false}}), 413 errWanted: errMissingBlock, 414 }, 415 {name: "unexpected block 10 from known peer - already have 10", 416 pool: makeBlockPool(testBcR, 10, 417 []BpPeer{{ID: "P1", Height: 100}}, 418 map[int64]tPBlocks{10: {"P1", true}, 11: {"P1", false}}), 419 args: args{ 420 peerID: "P1", 421 block: types.MakeBlock(int64(10), txs, nil, nil), 422 blockSize: 100, 423 }, 424 poolWanted: makeBlockPool(testBcR, 10, 425 []BpPeer{{ID: "P1", Height: 100}}, 426 map[int64]tPBlocks{10: {"P1", true}, 11: {"P1", false}}), 427 errWanted: errDuplicateBlock, 428 }, 429 {name: "unexpected block 10 from known peer P2 - expected 10 to come from P1", 430 pool: makeBlockPool(testBcR, 10, 431 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 432 map[int64]tPBlocks{10: {"P1", false}}), 433 args: args{ 434 peerID: "P2", 435 block: types.MakeBlock(int64(10), txs, nil, nil), 436 blockSize: 100, 437 }, 438 poolWanted: makeBlockPool(testBcR, 10, 439 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 440 map[int64]tPBlocks{10: {"P1", false}}), 441 errWanted: errBadDataFromPeer, 442 }, 443 {name: "expected block from known peer", 444 pool: makeBlockPool(testBcR, 10, 445 []BpPeer{{ID: "P1", Height: 100}}, 446 map[int64]tPBlocks{10: {"P1", false}}), 447 args: args{ 448 peerID: "P1", 449 block: types.MakeBlock(int64(10), txs, nil, nil), 450 blockSize: 100, 451 }, 452 poolWanted: makeBlockPool(testBcR, 10, 453 []BpPeer{{ID: "P1", Height: 100}}, 454 map[int64]tPBlocks{10: {"P1", true}}), 455 errWanted: nil, 456 }, 457 } 458 459 for _, tt := range tests { 460 tt := tt 461 t.Run(tt.name, func(t *testing.T) { 462 err := tt.pool.AddBlock(tt.args.peerID, tt.args.block, tt.args.blockSize) 463 assert.Equal(t, tt.errWanted, err) 464 assertBlockPoolEquivalent(t, tt.poolWanted, tt.pool) 465 }) 466 } 467 } 468 469 func TestBlockPoolFirstTwoBlocksAndPeers(t *testing.T) { 470 testBcR := newTestBcR() 471 472 tests := []struct { 473 name string 474 pool *BlockPool 475 firstWanted int64 476 secondWanted int64 477 errWanted error 478 }{ 479 { 480 name: "both blocks missing", 481 pool: makeBlockPool(testBcR, 10, 482 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 483 map[int64]tPBlocks{15: {"P1", true}, 16: {"P2", true}}), 484 errWanted: errMissingBlock, 485 }, 486 { 487 name: "second block missing", 488 pool: makeBlockPool(testBcR, 15, 489 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 490 map[int64]tPBlocks{15: {"P1", true}, 18: {"P2", true}}), 491 firstWanted: 15, 492 errWanted: errMissingBlock, 493 }, 494 { 495 name: "first block missing", 496 pool: makeBlockPool(testBcR, 15, 497 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 498 map[int64]tPBlocks{16: {"P2", true}, 18: {"P2", true}}), 499 secondWanted: 16, 500 errWanted: errMissingBlock, 501 }, 502 { 503 name: "both blocks present", 504 pool: makeBlockPool(testBcR, 10, 505 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 506 map[int64]tPBlocks{10: {"P1", true}, 11: {"P2", true}}), 507 firstWanted: 10, 508 secondWanted: 11, 509 }, 510 } 511 512 for _, tt := range tests { 513 tt := tt 514 t.Run(tt.name, func(t *testing.T) { 515 pool := tt.pool 516 gotFirst, gotSecond, err := pool.FirstTwoBlocksAndPeers() 517 assert.Equal(t, tt.errWanted, err) 518 519 if tt.firstWanted != 0 { 520 peer := pool.blocks[tt.firstWanted] 521 block := pool.peers[peer].blocks[tt.firstWanted] 522 assert.Equal(t, block, gotFirst.block, 523 "BlockPool.FirstTwoBlocksAndPeers() gotFirst = %v, want %v", 524 tt.firstWanted, gotFirst.block.Height) 525 } 526 527 if tt.secondWanted != 0 { 528 peer := pool.blocks[tt.secondWanted] 529 block := pool.peers[peer].blocks[tt.secondWanted] 530 assert.Equal(t, block, gotSecond.block, 531 "BlockPool.FirstTwoBlocksAndPeers() gotFirst = %v, want %v", 532 tt.secondWanted, gotSecond.block.Height) 533 } 534 }) 535 } 536 } 537 538 func TestBlockPoolInvalidateFirstTwoBlocks(t *testing.T) { 539 testBcR := newTestBcR() 540 541 tests := []struct { 542 name string 543 pool *BlockPool 544 poolWanted *BlockPool 545 }{ 546 { 547 name: "both blocks missing", 548 pool: makeBlockPool(testBcR, 10, 549 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 550 map[int64]tPBlocks{15: {"P1", true}, 16: {"P2", true}}), 551 poolWanted: makeBlockPool(testBcR, 10, 552 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 553 map[int64]tPBlocks{15: {"P1", true}, 16: {"P2", true}}), 554 }, 555 { 556 name: "second block missing", 557 pool: makeBlockPool(testBcR, 15, 558 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 559 map[int64]tPBlocks{15: {"P1", true}, 18: {"P2", true}}), 560 poolWanted: makeBlockPool(testBcR, 15, 561 []BpPeer{{ID: "P2", Height: 100}}, 562 map[int64]tPBlocks{18: {"P2", true}}), 563 }, 564 { 565 name: "first block missing", 566 pool: makeBlockPool(testBcR, 15, 567 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 568 map[int64]tPBlocks{18: {"P1", true}, 16: {"P2", true}}), 569 poolWanted: makeBlockPool(testBcR, 15, 570 []BpPeer{{ID: "P1", Height: 100}}, 571 map[int64]tPBlocks{18: {"P1", true}}), 572 }, 573 { 574 name: "both blocks present", 575 pool: makeBlockPool(testBcR, 10, 576 []BpPeer{{ID: "P1", Height: 100}, {ID: "P2", Height: 100}}, 577 map[int64]tPBlocks{10: {"P1", true}, 11: {"P2", true}}), 578 poolWanted: makeBlockPool(testBcR, 10, 579 []BpPeer{}, 580 map[int64]tPBlocks{}), 581 }, 582 } 583 584 for _, tt := range tests { 585 tt := tt 586 t.Run(tt.name, func(t *testing.T) { 587 tt.pool.InvalidateFirstTwoBlocks(errNoPeerResponse) 588 assertBlockPoolEquivalent(t, tt.poolWanted, tt.pool) 589 }) 590 } 591 } 592 593 func TestProcessedCurrentHeightBlock(t *testing.T) { 594 testBcR := newTestBcR() 595 596 tests := []struct { 597 name string 598 pool *BlockPool 599 poolWanted *BlockPool 600 }{ 601 { 602 name: "one peer", 603 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, 604 map[int64]tPBlocks{100: {"P1", true}, 101: {"P1", true}}), 605 poolWanted: makeBlockPool(testBcR, 101, []BpPeer{{ID: "P1", Height: 120}}, 606 map[int64]tPBlocks{101: {"P1", true}}), 607 }, 608 { 609 name: "multiple peers", 610 pool: makeBlockPool(testBcR, 100, 611 []BpPeer{{ID: "P1", Height: 120}, {ID: "P2", Height: 120}, {ID: "P3", Height: 130}}, 612 map[int64]tPBlocks{ 613 100: {"P1", true}, 104: {"P1", true}, 105: {"P1", false}, 614 101: {"P2", true}, 103: {"P2", false}, 615 102: {"P3", true}, 106: {"P3", true}}), 616 poolWanted: makeBlockPool(testBcR, 101, 617 []BpPeer{{ID: "P1", Height: 120}, {ID: "P2", Height: 120}, {ID: "P3", Height: 130}}, 618 map[int64]tPBlocks{ 619 104: {"P1", true}, 105: {"P1", false}, 620 101: {"P2", true}, 103: {"P2", false}, 621 102: {"P3", true}, 106: {"P3", true}}), 622 }, 623 } 624 625 for _, tt := range tests { 626 tt := tt 627 t.Run(tt.name, func(t *testing.T) { 628 tt.pool.ProcessedCurrentHeightBlock() 629 assertBlockPoolEquivalent(t, tt.poolWanted, tt.pool) 630 }) 631 } 632 } 633 634 func TestRemovePeerAtCurrentHeight(t *testing.T) { 635 testBcR := newTestBcR() 636 637 tests := []struct { 638 name string 639 pool *BlockPool 640 poolWanted *BlockPool 641 }{ 642 { 643 name: "one peer, remove peer for block at H", 644 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, 645 map[int64]tPBlocks{100: {"P1", false}, 101: {"P1", true}}), 646 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 647 }, 648 { 649 name: "one peer, remove peer for block at H+1", 650 pool: makeBlockPool(testBcR, 100, []BpPeer{{ID: "P1", Height: 120}}, 651 map[int64]tPBlocks{100: {"P1", true}, 101: {"P1", false}}), 652 poolWanted: makeBlockPool(testBcR, 100, []BpPeer{}, map[int64]tPBlocks{}), 653 }, 654 { 655 name: "multiple peers, remove peer for block at H", 656 pool: makeBlockPool(testBcR, 100, 657 []BpPeer{{ID: "P1", Height: 120}, {ID: "P2", Height: 120}, {ID: "P3", Height: 130}}, 658 map[int64]tPBlocks{ 659 100: {"P1", false}, 104: {"P1", true}, 105: {"P1", false}, 660 101: {"P2", true}, 103: {"P2", false}, 661 102: {"P3", true}, 106: {"P3", true}}), 662 poolWanted: makeBlockPool(testBcR, 100, 663 []BpPeer{{ID: "P2", Height: 120}, {ID: "P3", Height: 130}}, 664 map[int64]tPBlocks{ 665 101: {"P2", true}, 103: {"P2", false}, 666 102: {"P3", true}, 106: {"P3", true}}), 667 }, 668 { 669 name: "multiple peers, remove peer for block at H+1", 670 pool: makeBlockPool(testBcR, 100, 671 []BpPeer{{ID: "P1", Height: 120}, {ID: "P2", Height: 120}, {ID: "P3", Height: 130}}, 672 map[int64]tPBlocks{ 673 100: {"P1", true}, 104: {"P1", true}, 105: {"P1", false}, 674 101: {"P2", false}, 103: {"P2", false}, 675 102: {"P3", true}, 106: {"P3", true}}), 676 poolWanted: makeBlockPool(testBcR, 100, 677 []BpPeer{{ID: "P1", Height: 120}, {ID: "P3", Height: 130}}, 678 map[int64]tPBlocks{ 679 100: {"P1", true}, 104: {"P1", true}, 105: {"P1", false}, 680 102: {"P3", true}, 106: {"P3", true}}), 681 }, 682 } 683 684 for _, tt := range tests { 685 tt := tt 686 t.Run(tt.name, func(t *testing.T) { 687 tt.pool.RemovePeerAtCurrentHeights(errNoPeerResponse) 688 assertBlockPoolEquivalent(t, tt.poolWanted, tt.pool) 689 }) 690 } 691 }