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