You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

731 lines
20 KiB

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