package consensus import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/libs/bits" tmrand "github.com/tendermint/tendermint/libs/rand" "github.com/tendermint/tendermint/p2p" tmcons "github.com/tendermint/tendermint/proto/consensus" tmproto "github.com/tendermint/tendermint/proto/types" "github.com/tendermint/tendermint/types" ) func TestMsgToProto(t *testing.T) { psh := types.PartSetHeader{ Total: 1, Hash: tmrand.Bytes(32), } pbPsh := psh.ToProto() bi := types.BlockID{ Hash: tmrand.Bytes(32), PartsHeader: psh, } pbBi := bi.ToProto() bits := bits.NewBitArray(1) pbBits := bits.ToProto() parts := types.Part{ Index: 1, Bytes: []byte("test"), Proof: merkle.Proof{ Total: 1, Index: 1, LeafHash: tmrand.Bytes(32), Aunts: [][]byte{}, }, } pbParts, err := parts.ToProto() require.NoError(t, err) proposal := types.Proposal{ Type: tmproto.ProposalType, Height: 1, Round: 1, POLRound: 1, BlockID: bi, Timestamp: time.Now(), Signature: tmrand.Bytes(20), } pbProposal := proposal.ToProto() pv := types.NewMockPV() pk, err := pv.GetPubKey() require.NoError(t, err) val := types.NewValidator(pk, 100) vote, err := types.MakeVote( 1, types.BlockID{}, &types.ValidatorSet{Proposer: val, Validators: []*types.Validator{val}}, pv, "chainID", time.Now()) require.NoError(t, err) pbVote := vote.ToProto() testsCases := []struct { testName string msg Message want *tmcons.Message wantErr bool }{ {"successful NewRoundStepMessage", &NewRoundStepMessage{ Height: 2, Round: 1, Step: 1, SecondsSinceStartTime: 1, LastCommitRound: 2, }, &tmcons.Message{ Sum: &tmcons.Message_NewRoundStep{ NewRoundStep: &tmcons.NewRoundStep{ Height: 2, Round: 1, Step: 1, SecondsSinceStartTime: 1, LastCommitRound: 2, }, }, }, false}, {"successful NewValidBlockMessage", &NewValidBlockMessage{ Height: 1, Round: 1, BlockPartsHeader: psh, BlockParts: bits, IsCommit: false, }, &tmcons.Message{ Sum: &tmcons.Message_NewValidBlock{ NewValidBlock: &tmcons.NewValidBlock{ Height: 1, Round: 1, BlockPartsHeader: pbPsh, BlockParts: pbBits, IsCommit: false, }, }, }, false}, {"successful BlockPartMessage", &BlockPartMessage{ Height: 100, Round: 1, Part: &parts, }, &tmcons.Message{ Sum: &tmcons.Message_BlockPart{ BlockPart: &tmcons.BlockPart{ Height: 100, Round: 1, Part: *pbParts, }, }, }, false}, {"successful ProposalPOLMessage", &ProposalPOLMessage{ Height: 1, ProposalPOLRound: 1, ProposalPOL: bits, }, &tmcons.Message{ Sum: &tmcons.Message_ProposalPol{ ProposalPol: &tmcons.ProposalPOL{ Height: 1, ProposalPolRound: 1, ProposalPol: *pbBits, }, }}, false}, {"successful ProposalMessage", &ProposalMessage{ Proposal: &proposal, }, &tmcons.Message{ Sum: &tmcons.Message_Proposal{ Proposal: &tmcons.Proposal{ Proposal: *pbProposal, }, }, }, false}, {"successful VoteMessage", &VoteMessage{ Vote: vote, }, &tmcons.Message{ Sum: &tmcons.Message_Vote{ Vote: &tmcons.Vote{ Vote: pbVote, }, }, }, false}, {"successful VoteSetMaj23", &VoteSetMaj23Message{ Height: 1, Round: 1, Type: 1, BlockID: bi, }, &tmcons.Message{ Sum: &tmcons.Message_VoteSetMaj23{ VoteSetMaj23: &tmcons.VoteSetMaj23{ Height: 1, Round: 1, Type: 1, BlockID: pbBi, }, }, }, false}, {"successful VoteSetBits", &VoteSetBitsMessage{ Height: 1, Round: 1, Type: 1, BlockID: bi, Votes: bits, }, &tmcons.Message{ Sum: &tmcons.Message_VoteSetBits{ VoteSetBits: &tmcons.VoteSetBits{ Height: 1, Round: 1, Type: 1, BlockID: pbBi, Votes: *pbBits, }, }, }, false}, {"failure", nil, &tmcons.Message{}, true}, } for _, tt := range testsCases { tt := tt t.Run(tt.testName, func(t *testing.T) { pb, err := MsgToProto(tt.msg) if tt.wantErr == true { assert.Equal(t, err != nil, tt.wantErr) return } assert.EqualValues(t, tt.want, pb, tt.testName) msg, err := MsgFromProto(pb) if !tt.wantErr { require.NoError(t, err) bcm := assert.Equal(t, tt.msg, msg, tt.testName) assert.True(t, bcm, tt.testName) } else { require.Error(t, err, tt.testName) } }) } } func TestWALMsgProto(t *testing.T) { parts := types.Part{ Index: 1, Bytes: []byte("test"), Proof: merkle.Proof{ Total: 1, Index: 1, LeafHash: tmrand.Bytes(32), Aunts: [][]byte{}, }, } pbParts, err := parts.ToProto() require.NoError(t, err) testsCases := []struct { testName string msg WALMessage want *tmcons.WALMessage wantErr bool }{ {"successful EventDataRoundState", types.EventDataRoundState{ Height: 2, Round: 1, Step: "ronies", }, &tmcons.WALMessage{ Sum: &tmcons.WALMessage_EventDataRoundState{ EventDataRoundState: &tmproto.EventDataRoundState{ Height: 2, Round: 1, Step: "ronies", }, }, }, false}, {"successful msgInfo", msgInfo{ Msg: &BlockPartMessage{ Height: 100, Round: 1, Part: &parts, }, PeerID: p2p.ID("string"), }, &tmcons.WALMessage{ Sum: &tmcons.WALMessage_MsgInfo{ MsgInfo: &tmcons.MsgInfo{ Msg: tmcons.Message{ Sum: &tmcons.Message_BlockPart{ BlockPart: &tmcons.BlockPart{ Height: 100, Round: 1, Part: *pbParts, }, }, }, PeerID: "string", }, }, }, false}, {"successful timeoutInfo", timeoutInfo{ Duration: time.Duration(100), Height: 1, Round: 1, Step: 1, }, &tmcons.WALMessage{ Sum: &tmcons.WALMessage_TimeoutInfo{ TimeoutInfo: &tmcons.TimeoutInfo{ Duration: time.Duration(100), Height: 1, Round: 1, Step: 1, }, }, }, false}, {"successful EndHeightMessage", EndHeightMessage{ Height: 1, }, &tmcons.WALMessage{ Sum: &tmcons.WALMessage_EndHeight{ EndHeight: &tmcons.EndHeight{ Height: 1, }, }, }, false}, {"failure", nil, &tmcons.WALMessage{}, true}, } for _, tt := range testsCases { tt := tt t.Run(tt.testName, func(t *testing.T) { pb, err := WALToProto(tt.msg) if tt.wantErr == true { assert.Equal(t, err != nil, tt.wantErr) return } assert.EqualValues(t, tt.want, pb, tt.testName) msg, err := WALFromProto(pb) if !tt.wantErr { require.NoError(t, err) assert.Equal(t, tt.msg, msg, tt.testName) // need the concrete type as WAL Message is a empty interface } else { require.Error(t, err, tt.testName) } }) } }