diff --git a/internal/consensus/state_test.go b/internal/consensus/state_test.go index f1cfc225c..26d6b63d4 100644 --- a/internal/consensus/state_test.go +++ b/internal/consensus/state_test.go @@ -1965,6 +1965,81 @@ func TestProcessProposalAccept(t *testing.T) { } } +func TestFinalizeBlockCalled(t *testing.T) { + for _, testCase := range []struct { + name string + voteNil bool + expectCalled bool + }{ + { + name: "finalze block called when block commited", + voteNil: false, + expectCalled: true, + }, + { + name: "not called when block not commited", + voteNil: true, + expectCalled: false, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + config := configSetup(t) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + m := abcimocks.NewBaseMock() + m.On("ProcessProposal", mock.Anything).Return(abcitypes.ResponseProcessProposal{Accept: true}) + m.On("VerifyVoteExtension", mock.Anything).Return(abcitypes.ResponseVerifyVoteExtension{ + Result: abcitypes.ResponseVerifyVoteExtension_ACCEPT, + }) + if testCase.expectCalled { + m.On("FinalizeBlock", mock.Anything).Return(abcitypes.ResponseFinalizeBlock{}) + } + cs1, vss := makeState(ctx, t, makeStateArgs{config: config, application: m, logger: log.NewTestingLogger(t)}) + height, round := cs1.Height, cs1.Round + + proposalCh := subscribe(ctx, t, cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(ctx, t, cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey(ctx) + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(ctx, t, cs1, addr) + + startTestRound(ctx, cs1, cs1.Height, round) + ensureNewRound(t, newRoundCh, height, round) + ensureNewProposal(t, proposalCh, height, round) + rs := cs1.GetRoundState() + + blockID := types.BlockID{} + var polRound int32 = -1 + nextRound := round + 1 + nextHeight := height + if !testCase.voteNil { + polRound = 0 + nextRound = 0 + nextHeight = height + 1 + blockID = types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + } + + signAddVotes(ctx, t, cs1, tmproto.PrevoteType, config.ChainID(), blockID, vss[1:]...) + ensurePrevoteMatch(t, voteCh, height, round, rs.ProposalBlock.Hash()) + + signAddVotes(ctx, t, cs1, tmproto.PrecommitType, config.ChainID(), blockID, vss[1:]...) + ensurePrecommit(t, voteCh, height, round) + validatePrecommit(ctx, t, cs1, round, polRound, vss[0], blockID.Hash, blockID.Hash) + + ensureNewRound(t, newRoundCh, nextHeight, nextRound) + m.AssertExpectations(t) + if testCase.voteNil { + m.AssertNotCalled(t, "FinalizeBlock", mock.Anything) + } + }) + } +} + // 4 vals, 3 Nil Precommits at P0 // What we want: // P0 waits for timeoutPrecommit before starting next round