bitbucket.org/number571/tendermint@v0.8.14/internal/consensus/msgs_test.go (about)

     1  package consensus
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"math"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/gogo/protobuf/proto"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"bitbucket.org/number571/tendermint/crypto/merkle"
    15  	"bitbucket.org/number571/tendermint/crypto/tmhash"
    16  	cstypes "bitbucket.org/number571/tendermint/internal/consensus/types"
    17  	"bitbucket.org/number571/tendermint/internal/test/factory"
    18  	"bitbucket.org/number571/tendermint/libs/bits"
    19  	"bitbucket.org/number571/tendermint/libs/bytes"
    20  	tmrand "bitbucket.org/number571/tendermint/libs/rand"
    21  	tmcons "bitbucket.org/number571/tendermint/proto/tendermint/consensus"
    22  	tmproto "bitbucket.org/number571/tendermint/proto/tendermint/types"
    23  	"bitbucket.org/number571/tendermint/types"
    24  )
    25  
    26  func TestMsgToProto(t *testing.T) {
    27  	psh := types.PartSetHeader{
    28  		Total: 1,
    29  		Hash:  tmrand.Bytes(32),
    30  	}
    31  	pbPsh := psh.ToProto()
    32  	bi := types.BlockID{
    33  		Hash:          tmrand.Bytes(32),
    34  		PartSetHeader: psh,
    35  	}
    36  	pbBi := bi.ToProto()
    37  	bits := bits.NewBitArray(1)
    38  	pbBits := bits.ToProto()
    39  
    40  	parts := types.Part{
    41  		Index: 1,
    42  		Bytes: []byte("test"),
    43  		Proof: merkle.Proof{
    44  			Total:    1,
    45  			Index:    1,
    46  			LeafHash: tmrand.Bytes(32),
    47  			Aunts:    [][]byte{},
    48  		},
    49  	}
    50  	pbParts, err := parts.ToProto()
    51  	require.NoError(t, err)
    52  
    53  	proposal := types.Proposal{
    54  		Type:      tmproto.ProposalType,
    55  		Height:    1,
    56  		Round:     1,
    57  		POLRound:  1,
    58  		BlockID:   bi,
    59  		Timestamp: time.Now(),
    60  		Signature: tmrand.Bytes(20),
    61  	}
    62  	pbProposal := proposal.ToProto()
    63  
    64  	pv := types.NewMockPV()
    65  	vote, err := factory.MakeVote(pv, factory.DefaultTestChainID,
    66  		0, 1, 0, 2, types.BlockID{}, time.Now())
    67  	require.NoError(t, err)
    68  	pbVote := vote.ToProto()
    69  
    70  	testsCases := []struct {
    71  		testName string
    72  		msg      Message
    73  		want     *tmcons.Message
    74  		wantErr  bool
    75  	}{
    76  		{"successful NewRoundStepMessage", &NewRoundStepMessage{
    77  			Height:                2,
    78  			Round:                 1,
    79  			Step:                  1,
    80  			SecondsSinceStartTime: 1,
    81  			LastCommitRound:       2,
    82  		}, &tmcons.Message{
    83  			Sum: &tmcons.Message_NewRoundStep{
    84  				NewRoundStep: &tmcons.NewRoundStep{
    85  					Height:                2,
    86  					Round:                 1,
    87  					Step:                  1,
    88  					SecondsSinceStartTime: 1,
    89  					LastCommitRound:       2,
    90  				},
    91  			},
    92  		}, false},
    93  
    94  		{"successful NewValidBlockMessage", &NewValidBlockMessage{
    95  			Height:             1,
    96  			Round:              1,
    97  			BlockPartSetHeader: psh,
    98  			BlockParts:         bits,
    99  			IsCommit:           false,
   100  		}, &tmcons.Message{
   101  			Sum: &tmcons.Message_NewValidBlock{
   102  				NewValidBlock: &tmcons.NewValidBlock{
   103  					Height:             1,
   104  					Round:              1,
   105  					BlockPartSetHeader: pbPsh,
   106  					BlockParts:         pbBits,
   107  					IsCommit:           false,
   108  				},
   109  			},
   110  		}, false},
   111  		{"successful BlockPartMessage", &BlockPartMessage{
   112  			Height: 100,
   113  			Round:  1,
   114  			Part:   &parts,
   115  		}, &tmcons.Message{
   116  			Sum: &tmcons.Message_BlockPart{
   117  				BlockPart: &tmcons.BlockPart{
   118  					Height: 100,
   119  					Round:  1,
   120  					Part:   *pbParts,
   121  				},
   122  			},
   123  		}, false},
   124  		{"successful ProposalPOLMessage", &ProposalPOLMessage{
   125  			Height:           1,
   126  			ProposalPOLRound: 1,
   127  			ProposalPOL:      bits,
   128  		}, &tmcons.Message{
   129  			Sum: &tmcons.Message_ProposalPol{
   130  				ProposalPol: &tmcons.ProposalPOL{
   131  					Height:           1,
   132  					ProposalPolRound: 1,
   133  					ProposalPol:      *pbBits,
   134  				},
   135  			}}, false},
   136  		{"successful ProposalMessage", &ProposalMessage{
   137  			Proposal: &proposal,
   138  		}, &tmcons.Message{
   139  			Sum: &tmcons.Message_Proposal{
   140  				Proposal: &tmcons.Proposal{
   141  					Proposal: *pbProposal,
   142  				},
   143  			},
   144  		}, false},
   145  		{"successful VoteMessage", &VoteMessage{
   146  			Vote: vote,
   147  		}, &tmcons.Message{
   148  			Sum: &tmcons.Message_Vote{
   149  				Vote: &tmcons.Vote{
   150  					Vote: pbVote,
   151  				},
   152  			},
   153  		}, false},
   154  		{"successful VoteSetMaj23", &VoteSetMaj23Message{
   155  			Height:  1,
   156  			Round:   1,
   157  			Type:    1,
   158  			BlockID: bi,
   159  		}, &tmcons.Message{
   160  			Sum: &tmcons.Message_VoteSetMaj23{
   161  				VoteSetMaj23: &tmcons.VoteSetMaj23{
   162  					Height:  1,
   163  					Round:   1,
   164  					Type:    1,
   165  					BlockID: pbBi,
   166  				},
   167  			},
   168  		}, false},
   169  		{"successful VoteSetBits", &VoteSetBitsMessage{
   170  			Height:  1,
   171  			Round:   1,
   172  			Type:    1,
   173  			BlockID: bi,
   174  			Votes:   bits,
   175  		}, &tmcons.Message{
   176  			Sum: &tmcons.Message_VoteSetBits{
   177  				VoteSetBits: &tmcons.VoteSetBits{
   178  					Height:  1,
   179  					Round:   1,
   180  					Type:    1,
   181  					BlockID: pbBi,
   182  					Votes:   *pbBits,
   183  				},
   184  			},
   185  		}, false},
   186  		{"failure", nil, &tmcons.Message{}, true},
   187  	}
   188  	for _, tt := range testsCases {
   189  		tt := tt
   190  		t.Run(tt.testName, func(t *testing.T) {
   191  			pb, err := MsgToProto(tt.msg)
   192  			if tt.wantErr == true {
   193  				assert.Equal(t, err != nil, tt.wantErr)
   194  				return
   195  			}
   196  			assert.EqualValues(t, tt.want, pb, tt.testName)
   197  
   198  			msg, err := MsgFromProto(pb)
   199  
   200  			if !tt.wantErr {
   201  				require.NoError(t, err)
   202  				bcm := assert.Equal(t, tt.msg, msg, tt.testName)
   203  				assert.True(t, bcm, tt.testName)
   204  			} else {
   205  				require.Error(t, err, tt.testName)
   206  			}
   207  		})
   208  	}
   209  }
   210  
   211  func TestWALMsgProto(t *testing.T) {
   212  
   213  	parts := types.Part{
   214  		Index: 1,
   215  		Bytes: []byte("test"),
   216  		Proof: merkle.Proof{
   217  			Total:    1,
   218  			Index:    1,
   219  			LeafHash: tmrand.Bytes(32),
   220  			Aunts:    [][]byte{},
   221  		},
   222  	}
   223  	pbParts, err := parts.ToProto()
   224  	require.NoError(t, err)
   225  
   226  	testsCases := []struct {
   227  		testName string
   228  		msg      WALMessage
   229  		want     *tmcons.WALMessage
   230  		wantErr  bool
   231  	}{
   232  		{"successful EventDataRoundState", types.EventDataRoundState{
   233  			Height: 2,
   234  			Round:  1,
   235  			Step:   "ronies",
   236  		}, &tmcons.WALMessage{
   237  			Sum: &tmcons.WALMessage_EventDataRoundState{
   238  				EventDataRoundState: &tmproto.EventDataRoundState{
   239  					Height: 2,
   240  					Round:  1,
   241  					Step:   "ronies",
   242  				},
   243  			},
   244  		}, false},
   245  		{"successful msgInfo", msgInfo{
   246  			Msg: &BlockPartMessage{
   247  				Height: 100,
   248  				Round:  1,
   249  				Part:   &parts,
   250  			},
   251  			PeerID: types.NodeID("string"),
   252  		}, &tmcons.WALMessage{
   253  			Sum: &tmcons.WALMessage_MsgInfo{
   254  				MsgInfo: &tmcons.MsgInfo{
   255  					Msg: tmcons.Message{
   256  						Sum: &tmcons.Message_BlockPart{
   257  							BlockPart: &tmcons.BlockPart{
   258  								Height: 100,
   259  								Round:  1,
   260  								Part:   *pbParts,
   261  							},
   262  						},
   263  					},
   264  					PeerID: "string",
   265  				},
   266  			},
   267  		}, false},
   268  		{"successful timeoutInfo", timeoutInfo{
   269  			Duration: time.Duration(100),
   270  			Height:   1,
   271  			Round:    1,
   272  			Step:     1,
   273  		}, &tmcons.WALMessage{
   274  			Sum: &tmcons.WALMessage_TimeoutInfo{
   275  				TimeoutInfo: &tmcons.TimeoutInfo{
   276  					Duration: time.Duration(100),
   277  					Height:   1,
   278  					Round:    1,
   279  					Step:     1,
   280  				},
   281  			},
   282  		}, false},
   283  		{"successful EndHeightMessage", EndHeightMessage{
   284  			Height: 1,
   285  		}, &tmcons.WALMessage{
   286  			Sum: &tmcons.WALMessage_EndHeight{
   287  				EndHeight: &tmcons.EndHeight{
   288  					Height: 1,
   289  				},
   290  			},
   291  		}, false},
   292  		{"failure", nil, &tmcons.WALMessage{}, true},
   293  	}
   294  	for _, tt := range testsCases {
   295  		tt := tt
   296  		t.Run(tt.testName, func(t *testing.T) {
   297  			pb, err := WALToProto(tt.msg)
   298  			if tt.wantErr == true {
   299  				assert.Equal(t, err != nil, tt.wantErr)
   300  				return
   301  			}
   302  			assert.EqualValues(t, tt.want, pb, tt.testName)
   303  
   304  			msg, err := WALFromProto(pb)
   305  
   306  			if !tt.wantErr {
   307  				require.NoError(t, err)
   308  				assert.Equal(t, tt.msg, msg, tt.testName) // need the concrete type as WAL Message is a empty interface
   309  			} else {
   310  				require.Error(t, err, tt.testName)
   311  			}
   312  		})
   313  	}
   314  }
   315  
   316  // nolint:lll //ignore line length for tests
   317  func TestConsMsgsVectors(t *testing.T) {
   318  	date := time.Date(2018, 8, 30, 12, 0, 0, 0, time.UTC)
   319  	psh := types.PartSetHeader{
   320  		Total: 1,
   321  		Hash:  []byte("add_more_exclamation_marks_code-"),
   322  	}
   323  	pbPsh := psh.ToProto()
   324  
   325  	bi := types.BlockID{
   326  		Hash:          []byte("add_more_exclamation_marks_code-"),
   327  		PartSetHeader: psh,
   328  	}
   329  	pbBi := bi.ToProto()
   330  	bits := bits.NewBitArray(1)
   331  	pbBits := bits.ToProto()
   332  
   333  	parts := types.Part{
   334  		Index: 1,
   335  		Bytes: []byte("test"),
   336  		Proof: merkle.Proof{
   337  			Total:    1,
   338  			Index:    1,
   339  			LeafHash: []byte("add_more_exclamation_marks_code-"),
   340  			Aunts:    [][]byte{},
   341  		},
   342  	}
   343  	pbParts, err := parts.ToProto()
   344  	require.NoError(t, err)
   345  
   346  	proposal := types.Proposal{
   347  		Type:      tmproto.ProposalType,
   348  		Height:    1,
   349  		Round:     1,
   350  		POLRound:  1,
   351  		BlockID:   bi,
   352  		Timestamp: date,
   353  		Signature: []byte("add_more_exclamation"),
   354  	}
   355  	pbProposal := proposal.ToProto()
   356  
   357  	v := &types.Vote{
   358  		ValidatorAddress: []byte("add_more_exclamation"),
   359  		ValidatorIndex:   1,
   360  		Height:           1,
   361  		Round:            0,
   362  		Timestamp:        date,
   363  		Type:             tmproto.PrecommitType,
   364  		BlockID:          bi,
   365  	}
   366  	vpb := v.ToProto()
   367  
   368  	testCases := []struct {
   369  		testName string
   370  		cMsg     proto.Message
   371  		expBytes string
   372  	}{
   373  		{"NewRoundStep", &tmcons.Message{Sum: &tmcons.Message_NewRoundStep{NewRoundStep: &tmcons.NewRoundStep{
   374  			Height:                1,
   375  			Round:                 1,
   376  			Step:                  1,
   377  			SecondsSinceStartTime: 1,
   378  			LastCommitRound:       1,
   379  		}}}, "0a0a08011001180120012801"},
   380  		{"NewRoundStep Max", &tmcons.Message{Sum: &tmcons.Message_NewRoundStep{NewRoundStep: &tmcons.NewRoundStep{
   381  			Height:                math.MaxInt64,
   382  			Round:                 math.MaxInt32,
   383  			Step:                  math.MaxUint32,
   384  			SecondsSinceStartTime: math.MaxInt64,
   385  			LastCommitRound:       math.MaxInt32,
   386  		}}}, "0a2608ffffffffffffffff7f10ffffffff0718ffffffff0f20ffffffffffffffff7f28ffffffff07"},
   387  		{"NewValidBlock", &tmcons.Message{Sum: &tmcons.Message_NewValidBlock{
   388  			NewValidBlock: &tmcons.NewValidBlock{
   389  				Height: 1, Round: 1, BlockPartSetHeader: pbPsh, BlockParts: pbBits, IsCommit: false}}},
   390  			"1231080110011a24080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d22050801120100"},
   391  		{"Proposal", &tmcons.Message{Sum: &tmcons.Message_Proposal{Proposal: &tmcons.Proposal{Proposal: *pbProposal}}},
   392  			"1a720a7008201001180120012a480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d320608c0b89fdc053a146164645f6d6f72655f6578636c616d6174696f6e"},
   393  		{"ProposalPol", &tmcons.Message{Sum: &tmcons.Message_ProposalPol{
   394  			ProposalPol: &tmcons.ProposalPOL{Height: 1, ProposalPolRound: 1}}},
   395  			"2206080110011a00"},
   396  		{"BlockPart", &tmcons.Message{Sum: &tmcons.Message_BlockPart{
   397  			BlockPart: &tmcons.BlockPart{Height: 1, Round: 1, Part: *pbParts}}},
   398  			"2a36080110011a3008011204746573741a26080110011a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d"},
   399  		{"Vote", &tmcons.Message{Sum: &tmcons.Message_Vote{
   400  			Vote: &tmcons.Vote{Vote: vpb}}},
   401  			"32700a6e0802100122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a0608c0b89fdc0532146164645f6d6f72655f6578636c616d6174696f6e3801"},
   402  		{"HasVote", &tmcons.Message{Sum: &tmcons.Message_HasVote{
   403  			HasVote: &tmcons.HasVote{Height: 1, Round: 1, Type: tmproto.PrevoteType, Index: 1}}},
   404  			"3a080801100118012001"},
   405  		{"HasVote", &tmcons.Message{Sum: &tmcons.Message_HasVote{
   406  			HasVote: &tmcons.HasVote{Height: math.MaxInt64, Round: math.MaxInt32,
   407  				Type: tmproto.PrevoteType, Index: math.MaxInt32}}},
   408  			"3a1808ffffffffffffffff7f10ffffffff07180120ffffffff07"},
   409  		{"VoteSetMaj23", &tmcons.Message{Sum: &tmcons.Message_VoteSetMaj23{
   410  			VoteSetMaj23: &tmcons.VoteSetMaj23{Height: 1, Round: 1, Type: tmproto.PrevoteType, BlockID: pbBi}}},
   411  			"425008011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d"},
   412  		{"VoteSetBits", &tmcons.Message{Sum: &tmcons.Message_VoteSetBits{
   413  			VoteSetBits: &tmcons.VoteSetBits{Height: 1, Round: 1, Type: tmproto.PrevoteType, BlockID: pbBi, Votes: *pbBits}}},
   414  			"4a5708011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a050801120100"},
   415  	}
   416  
   417  	for _, tc := range testCases {
   418  		tc := tc
   419  		t.Run(tc.testName, func(t *testing.T) {
   420  			bz, err := proto.Marshal(tc.cMsg)
   421  			require.NoError(t, err)
   422  
   423  			require.Equal(t, tc.expBytes, hex.EncodeToString(bz))
   424  		})
   425  	}
   426  }
   427  
   428  func TestVoteSetMaj23MessageValidateBasic(t *testing.T) {
   429  	const (
   430  		validSignedMsgType   tmproto.SignedMsgType = 0x01
   431  		invalidSignedMsgType tmproto.SignedMsgType = 0x03
   432  	)
   433  
   434  	validBlockID := types.BlockID{}
   435  	invalidBlockID := types.BlockID{
   436  		Hash: bytes.HexBytes{},
   437  		PartSetHeader: types.PartSetHeader{
   438  			Total: 1,
   439  			Hash:  []byte{0},
   440  		},
   441  	}
   442  
   443  	testCases := []struct { // nolint: maligned
   444  		expectErr      bool
   445  		messageRound   int32
   446  		messageHeight  int64
   447  		testName       string
   448  		messageType    tmproto.SignedMsgType
   449  		messageBlockID types.BlockID
   450  	}{
   451  		{false, 0, 0, "Valid Message", validSignedMsgType, validBlockID},
   452  		{true, -1, 0, "Invalid Message", validSignedMsgType, validBlockID},
   453  		{true, 0, -1, "Invalid Message", validSignedMsgType, validBlockID},
   454  		{true, 0, 0, "Invalid Message", invalidSignedMsgType, validBlockID},
   455  		{true, 0, 0, "Invalid Message", validSignedMsgType, invalidBlockID},
   456  	}
   457  
   458  	for _, tc := range testCases {
   459  		tc := tc
   460  		t.Run(tc.testName, func(t *testing.T) {
   461  			message := VoteSetMaj23Message{
   462  				Height:  tc.messageHeight,
   463  				Round:   tc.messageRound,
   464  				Type:    tc.messageType,
   465  				BlockID: tc.messageBlockID,
   466  			}
   467  
   468  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   469  		})
   470  	}
   471  }
   472  
   473  func TestVoteSetBitsMessageValidateBasic(t *testing.T) {
   474  	testCases := []struct {
   475  		malleateFn func(*VoteSetBitsMessage)
   476  		expErr     string
   477  	}{
   478  		{func(msg *VoteSetBitsMessage) {}, ""},
   479  		{func(msg *VoteSetBitsMessage) { msg.Height = -1 }, "negative Height"},
   480  		{func(msg *VoteSetBitsMessage) { msg.Type = 0x03 }, "invalid Type"},
   481  		{func(msg *VoteSetBitsMessage) {
   482  			msg.BlockID = types.BlockID{
   483  				Hash: bytes.HexBytes{},
   484  				PartSetHeader: types.PartSetHeader{
   485  					Total: 1,
   486  					Hash:  []byte{0},
   487  				},
   488  			}
   489  		}, "wrong BlockID: wrong PartSetHeader: wrong Hash:"},
   490  		{func(msg *VoteSetBitsMessage) { msg.Votes = bits.NewBitArray(types.MaxVotesCount + 1) },
   491  			"votes bit array is too big: 10001, max: 10000"},
   492  	}
   493  
   494  	for i, tc := range testCases {
   495  		tc := tc
   496  		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
   497  			msg := &VoteSetBitsMessage{
   498  				Height:  1,
   499  				Round:   0,
   500  				Type:    0x01,
   501  				Votes:   bits.NewBitArray(1),
   502  				BlockID: types.BlockID{},
   503  			}
   504  
   505  			tc.malleateFn(msg)
   506  			err := msg.ValidateBasic()
   507  			if tc.expErr != "" && assert.Error(t, err) {
   508  				assert.Contains(t, err.Error(), tc.expErr)
   509  			}
   510  		})
   511  	}
   512  }
   513  
   514  func TestNewRoundStepMessageValidateBasic(t *testing.T) {
   515  	testCases := []struct { // nolint: maligned
   516  		expectErr              bool
   517  		messageRound           int32
   518  		messageLastCommitRound int32
   519  		messageHeight          int64
   520  		testName               string
   521  		messageStep            cstypes.RoundStepType
   522  	}{
   523  		{false, 0, 0, 0, "Valid Message", cstypes.RoundStepNewHeight},
   524  		{true, -1, 0, 0, "Negative round", cstypes.RoundStepNewHeight},
   525  		{true, 0, 0, -1, "Negative height", cstypes.RoundStepNewHeight},
   526  		{true, 0, 0, 0, "Invalid Step", cstypes.RoundStepCommit + 1},
   527  		// The following cases will be handled by ValidateHeight
   528  		{false, 0, 0, 1, "H == 1 but LCR != -1 ", cstypes.RoundStepNewHeight},
   529  		{false, 0, -1, 2, "H > 1 but LCR < 0", cstypes.RoundStepNewHeight},
   530  	}
   531  
   532  	for _, tc := range testCases {
   533  		tc := tc
   534  		t.Run(tc.testName, func(t *testing.T) {
   535  			message := NewRoundStepMessage{
   536  				Height:          tc.messageHeight,
   537  				Round:           tc.messageRound,
   538  				Step:            tc.messageStep,
   539  				LastCommitRound: tc.messageLastCommitRound,
   540  			}
   541  
   542  			err := message.ValidateBasic()
   543  			if tc.expectErr {
   544  				require.Error(t, err)
   545  			} else {
   546  				require.NoError(t, err)
   547  			}
   548  		})
   549  	}
   550  }
   551  
   552  func TestNewRoundStepMessageValidateHeight(t *testing.T) {
   553  	initialHeight := int64(10)
   554  	testCases := []struct { // nolint: maligned
   555  		expectErr              bool
   556  		messageLastCommitRound int32
   557  		messageHeight          int64
   558  		testName               string
   559  	}{
   560  		{false, 0, 11, "Valid Message"},
   561  		{true, 0, -1, "Negative height"},
   562  		{true, 0, 0, "Zero height"},
   563  		{true, 0, 10, "Initial height but LCR != -1 "},
   564  		{true, -1, 11, "Normal height but LCR < 0"},
   565  	}
   566  
   567  	for _, tc := range testCases {
   568  		tc := tc
   569  		t.Run(tc.testName, func(t *testing.T) {
   570  			message := NewRoundStepMessage{
   571  				Height:          tc.messageHeight,
   572  				Round:           0,
   573  				Step:            cstypes.RoundStepNewHeight,
   574  				LastCommitRound: tc.messageLastCommitRound,
   575  			}
   576  
   577  			err := message.ValidateHeight(initialHeight)
   578  			if tc.expectErr {
   579  				require.Error(t, err)
   580  			} else {
   581  				require.NoError(t, err)
   582  			}
   583  		})
   584  	}
   585  }
   586  
   587  func TestNewValidBlockMessageValidateBasic(t *testing.T) {
   588  	testCases := []struct {
   589  		malleateFn func(*NewValidBlockMessage)
   590  		expErr     string
   591  	}{
   592  		{func(msg *NewValidBlockMessage) {}, ""},
   593  		{func(msg *NewValidBlockMessage) { msg.Height = -1 }, "negative Height"},
   594  		{func(msg *NewValidBlockMessage) { msg.Round = -1 }, "negative Round"},
   595  		{
   596  			func(msg *NewValidBlockMessage) { msg.BlockPartSetHeader.Total = 2 },
   597  			"blockParts bit array size 1 not equal to BlockPartSetHeader.Total 2",
   598  		},
   599  		{
   600  			func(msg *NewValidBlockMessage) {
   601  				msg.BlockPartSetHeader.Total = 0
   602  				msg.BlockParts = bits.NewBitArray(0)
   603  			},
   604  			"empty blockParts",
   605  		},
   606  		{
   607  			func(msg *NewValidBlockMessage) { msg.BlockParts = bits.NewBitArray(int(types.MaxBlockPartsCount) + 1) },
   608  			"blockParts bit array size 1602 not equal to BlockPartSetHeader.Total 1",
   609  		},
   610  	}
   611  
   612  	for i, tc := range testCases {
   613  		tc := tc
   614  		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
   615  			msg := &NewValidBlockMessage{
   616  				Height: 1,
   617  				Round:  0,
   618  				BlockPartSetHeader: types.PartSetHeader{
   619  					Total: 1,
   620  				},
   621  				BlockParts: bits.NewBitArray(1),
   622  			}
   623  
   624  			tc.malleateFn(msg)
   625  			err := msg.ValidateBasic()
   626  			if tc.expErr != "" && assert.Error(t, err) {
   627  				assert.Contains(t, err.Error(), tc.expErr)
   628  			}
   629  		})
   630  	}
   631  }
   632  
   633  func TestProposalPOLMessageValidateBasic(t *testing.T) {
   634  	testCases := []struct {
   635  		malleateFn func(*ProposalPOLMessage)
   636  		expErr     string
   637  	}{
   638  		{func(msg *ProposalPOLMessage) {}, ""},
   639  		{func(msg *ProposalPOLMessage) { msg.Height = -1 }, "negative Height"},
   640  		{func(msg *ProposalPOLMessage) { msg.ProposalPOLRound = -1 }, "negative ProposalPOLRound"},
   641  		{func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(0) }, "empty ProposalPOL bit array"},
   642  		{func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(types.MaxVotesCount + 1) },
   643  			"proposalPOL bit array is too big: 10001, max: 10000"},
   644  	}
   645  
   646  	for i, tc := range testCases {
   647  		tc := tc
   648  		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
   649  			msg := &ProposalPOLMessage{
   650  				Height:           1,
   651  				ProposalPOLRound: 1,
   652  				ProposalPOL:      bits.NewBitArray(1),
   653  			}
   654  
   655  			tc.malleateFn(msg)
   656  			err := msg.ValidateBasic()
   657  			if tc.expErr != "" && assert.Error(t, err) {
   658  				assert.Contains(t, err.Error(), tc.expErr)
   659  			}
   660  		})
   661  	}
   662  }
   663  
   664  func TestBlockPartMessageValidateBasic(t *testing.T) {
   665  	testPart := new(types.Part)
   666  	testPart.Proof.LeafHash = tmhash.Sum([]byte("leaf"))
   667  	testCases := []struct {
   668  		testName      string
   669  		messageHeight int64
   670  		messageRound  int32
   671  		messagePart   *types.Part
   672  		expectErr     bool
   673  	}{
   674  		{"Valid Message", 0, 0, testPart, false},
   675  		{"Invalid Message", -1, 0, testPart, true},
   676  		{"Invalid Message", 0, -1, testPart, true},
   677  	}
   678  
   679  	for _, tc := range testCases {
   680  		tc := tc
   681  		t.Run(tc.testName, func(t *testing.T) {
   682  			message := BlockPartMessage{
   683  				Height: tc.messageHeight,
   684  				Round:  tc.messageRound,
   685  				Part:   tc.messagePart,
   686  			}
   687  
   688  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   689  		})
   690  	}
   691  
   692  	message := BlockPartMessage{Height: 0, Round: 0, Part: new(types.Part)}
   693  	message.Part.Index = 1
   694  
   695  	assert.Equal(t, true, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   696  }
   697  
   698  func TestHasVoteMessageValidateBasic(t *testing.T) {
   699  	const (
   700  		validSignedMsgType   tmproto.SignedMsgType = 0x01
   701  		invalidSignedMsgType tmproto.SignedMsgType = 0x03
   702  	)
   703  
   704  	testCases := []struct { // nolint: maligned
   705  		expectErr     bool
   706  		messageRound  int32
   707  		messageIndex  int32
   708  		messageHeight int64
   709  		testName      string
   710  		messageType   tmproto.SignedMsgType
   711  	}{
   712  		{false, 0, 0, 0, "Valid Message", validSignedMsgType},
   713  		{true, -1, 0, 0, "Invalid Message", validSignedMsgType},
   714  		{true, 0, -1, 0, "Invalid Message", validSignedMsgType},
   715  		{true, 0, 0, 0, "Invalid Message", invalidSignedMsgType},
   716  		{true, 0, 0, -1, "Invalid Message", validSignedMsgType},
   717  	}
   718  
   719  	for _, tc := range testCases {
   720  		tc := tc
   721  		t.Run(tc.testName, func(t *testing.T) {
   722  			message := HasVoteMessage{
   723  				Height: tc.messageHeight,
   724  				Round:  tc.messageRound,
   725  				Type:   tc.messageType,
   726  				Index:  tc.messageIndex,
   727  			}
   728  
   729  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   730  		})
   731  	}
   732  }