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 }