From 4d54cced433b006724e82bee664069b1b93e5da2 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Fri, 12 Apr 2019 23:32:21 -0400 Subject: [PATCH] more tests --- blockchain_new/pool.go | 2 +- blockchain_new/reactor.go | 15 ++++- blockchain_new/reactor_fsm.go | 1 + blockchain_new/reactor_fsm_test.go | 97 +++++++++++++++++++++++++++--- 4 files changed, 105 insertions(+), 10 deletions(-) diff --git a/blockchain_new/pool.go b/blockchain_new/pool.go index 7c9cc157..8b3c63d7 100644 --- a/blockchain_new/pool.go +++ b/blockchain_new/pool.go @@ -238,7 +238,7 @@ func (pool *blockPool) getNextTwoBlocks() (first, second *blockData, err error) if err == errMissingBlocks { // We need both to sync the first block. - pool.logger.Error("missing first two blocks from height", "height", pool.height) + pool.logger.Error("missing blocks at height and/ or height+1", "height", pool.height) } return } diff --git a/blockchain_new/reactor.go b/blockchain_new/reactor.go index 0324d389..df95e9c7 100644 --- a/blockchain_new/reactor.go +++ b/blockchain_new/reactor.go @@ -203,6 +203,7 @@ func (bcR *BlockchainReactor) sendRemovePeerToFSM(peerID p2p.ID) { event: peerRemoveEv, data: bReactorEventData{ peerId: peerID, + err: errSwitchRemovesPeer, }, } bcR.sendMessageToFSMAsync(msgData) @@ -315,8 +316,18 @@ ForLoop: } _ = sendMessageToFSMSync(bcR.fsm, msgData) - case err := <-bcR.errorsFromFSMCh: - bcR.reportPeerErrorToSwitch(err.err, err.peerID) + case msg := <-bcR.errorsFromFSMCh: + bcR.reportPeerErrorToSwitch(msg.err, msg.peerID) + if msg.err == errNoPeerResponse { + msgData := bReactorMessageData{ + event: peerRemoveEv, + data: bReactorEventData{ + peerId: msg.peerID, + err: msg.err, + }, + } + _ = sendMessageToFSMSync(bcR.fsm, msgData) + } case <-statusUpdateTicker.C: // Ask for status updates. diff --git a/blockchain_new/reactor_fsm.go b/blockchain_new/reactor_fsm.go index a5a62e80..d4dde279 100644 --- a/blockchain_new/reactor_fsm.go +++ b/blockchain_new/reactor_fsm.go @@ -158,6 +158,7 @@ var ( errPeerTooShort = errors.New("peer height too low, old peer removed/ new peer not added") errSlowPeer = errors.New("peer is not sending us data fast enough") errNoPeerFoundForHeight = errors.New("could not find peer for block request") + errSwitchRemovesPeer = errors.New("switch is removing peer") ) func init() { diff --git a/blockchain_new/reactor_fsm_test.go b/blockchain_new/reactor_fsm_test.go index 11481b3e..dcb5193a 100644 --- a/blockchain_new/reactor_fsm_test.go +++ b/blockchain_new/reactor_fsm_test.go @@ -71,6 +71,7 @@ type fsmStepTestValues struct { failBlockReq bool blockReqIncreased bool blocksAdded []int64 + peersNotInPool []p2p.ID expectedLastBlockReq *lastBlockRequestT } @@ -135,6 +136,18 @@ func waitForBlock_BlockRespEv_WantWaitForBlock(peerID p2p.ID, height int64, prev } } +func waitForBlock_PeerRemoveEv_waitForBlock(peerID p2p.ID, err error, peerSet []p2p.ID) fsmStepTestValues { + return fsmStepTestValues{ + currentState: "waitForBlock", event: peerRemoveEv, + data: bReactorEventData{ + peerId: peerID, + err: err, + }, + expectedState: "waitForBlock", + peersNotInPool: peerSet, + } +} + func newTestReactor(height int64) *testReactor { testBcR := &testReactor{logger: log.TestingLogger()} testBcR.fsm = NewFSM(height, testBcR) @@ -264,14 +277,13 @@ func TestFSMBlockVerificationFailure(t *testing.T) { { name: "block verification failure", startingHeight: 1, - maxRequestsPerPeer: 2, + maxRequestsPerPeer: 3, steps: []fsmStepTestValues{ // startFSMEv unknown_StartFSMEv_WantWaitForPeer, // statusResponseEv from P1 waitForPeer_StatusEv_WantWaitForBlock("P1", 3), - // statusResponseEv from P2 - waitForBlock_StatusEv_WantWaitForBlock("P2", 3), + // makeRequestEv waitForBlock_MakeRequestEv_WantWaitForBlock(maxNumPendingRequests), // blockResponseEv for height 1 @@ -279,7 +291,10 @@ func TestFSMBlockVerificationFailure(t *testing.T) { // blockResponseEv for height 2 waitForBlock_BlockRespEv_WantWaitForBlock("P1", 2, []int64{1}), // blockResponseEv for height 3 - waitForBlock_BlockRespEv_WantWaitForBlock("P2", 3, []int64{1, 2}), + waitForBlock_BlockRespEv_WantWaitForBlock("P1", 3, []int64{1, 2}), + + // statusResponseEv from P2 + waitForBlock_StatusEv_WantWaitForBlock("P2", 3), // processedBlockEv with Error waitForBlock_ProcessedBlockEv_Err_WantWaitForBlock, @@ -287,9 +302,11 @@ func TestFSMBlockVerificationFailure(t *testing.T) { // makeRequestEv waitForBlock_MakeRequestEv_WantWaitForBlock(maxNumPendingRequests), // blockResponseEv for height 1 - waitForBlock_BlockRespEv_WantWaitForBlock("P2", 1, []int64{3}), + waitForBlock_BlockRespEv_WantWaitForBlock("P2", 1, []int64{}), // blockResponseEv for height 2 - waitForBlock_BlockRespEv_WantWaitForBlock("P2", 2, []int64{1, 3}), + waitForBlock_BlockRespEv_WantWaitForBlock("P2", 2, []int64{1}), + // blockResponseEv for height 2 + waitForBlock_BlockRespEv_WantWaitForBlock("P2", 3, []int64{1, 2}), waitForBlock_ProcessedBlockEv_WantWaitForBlock, waitForBlock_ProcessedBlockEv_WantFinished, @@ -360,6 +377,68 @@ func TestFSMBlockVerificationFailure(t *testing.T) { } } +func TestFSMPeerRemoveEvent(t *testing.T) { + tests := []struct { + name string + startingHeight int64 + maxRequestsPerPeer int32 + steps []fsmStepTestValues + }{ + { + name: "peer remove event with no blocks", + startingHeight: 1, + maxRequestsPerPeer: 3, + steps: []fsmStepTestValues{ + // startFSMEv + unknown_StartFSMEv_WantWaitForPeer, + // statusResponseEv from P1 + waitForPeer_StatusEv_WantWaitForBlock("P1", 3), + // statusResponseEv from P2 + waitForBlock_StatusEv_WantWaitForBlock("P2", 3), + // statusResponseEv from P3 + waitForBlock_StatusEv_WantWaitForBlock("P3", 3), + + waitForBlock_PeerRemoveEv_waitForBlock("P2", errSwitchRemovesPeer, []p2p.ID{"P2"}), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create test reactor + testBcR := newTestReactor(tt.startingHeight) + resetTestValues() + + if tt.maxRequestsPerPeer != 0 { + maxRequestsPerPeer = tt.maxRequestsPerPeer + } + + for _, step := range tt.steps { + assert.Equal(t, step.currentState, testBcR.fsm.state.name) + failSendStatusRequest = step.failStatusReq + failSendBlockRequest = step.failBlockReq + + oldNumStatusRequests := numStatusRequests + + fsmErr := sendEventToFSM(testBcR.fsm, step.event, step.data) + assert.Equal(t, step.errWanted, fsmErr) + + if step.shouldSendStatusReq { + assert.Equal(t, oldNumStatusRequests+1, numStatusRequests) + } else { + assert.Equal(t, oldNumStatusRequests, numStatusRequests) + } + + for _, peerID := range step.peersNotInPool { + _, ok := testBcR.fsm.pool.peers[peerID] + assert.False(t, ok) + } + assert.Equal(t, step.expectedState, testBcR.fsm.state.name) + } + }) + } +} + const ( maxStartingHeightTest = 100 maxRequestsPerPeerTest = 40 @@ -531,7 +610,7 @@ func TestReactorFSMPeerTimeout(t *testing.T) { assert.Equal(t, 1, numStatusRequests) // Send a status response message to FSM - peerID := p2p.ID(cmn.RandStr(12)) + peerID := p2p.ID("P1") sendStatusResponse(fsm, peerID, 10) time.Sleep(5 * time.Millisecond) @@ -547,6 +626,10 @@ func TestReactorFSMPeerTimeout(t *testing.T) { // let FSM timeout on the block response message time.Sleep(100 * time.Millisecond) + assert.Equal(t, peerID, lastPeerError.peerID) + assert.Equal(t, errNoPeerResponse, lastPeerError.err) + + peerTimeout = 15 * time.Second }