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.

140 lines
3.9 KiB

  1. package types
  2. import (
  3. "math"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. "github.com/tendermint/tendermint/crypto/tmhash"
  9. )
  10. var testProposal *Proposal
  11. func init() {
  12. var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z")
  13. if err != nil {
  14. panic(err)
  15. }
  16. testProposal = &Proposal{
  17. Height: 12345,
  18. Round: 23456,
  19. BlockID: BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}},
  20. POLRound: -1,
  21. Timestamp: stamp,
  22. }
  23. }
  24. func TestProposalSignable(t *testing.T) {
  25. chainID := "test_chain_id"
  26. signBytes := testProposal.SignBytes(chainID)
  27. expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, testProposal))
  28. require.NoError(t, err)
  29. require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal")
  30. }
  31. func TestProposalString(t *testing.T) {
  32. str := testProposal.String()
  33. expected := `Proposal{12345/23456 (010203:111:626C6F636B70, -1) 000000000000 @ 2018-02-11T07:09:22.765Z}`
  34. if str != expected {
  35. t.Errorf("Got unexpected string for Proposal. Expected:\n%v\nGot:\n%v", expected, str)
  36. }
  37. }
  38. func TestProposalVerifySignature(t *testing.T) {
  39. privVal := NewMockPV()
  40. pubKey := privVal.GetPubKey()
  41. prop := NewProposal(
  42. 4, 2, 2,
  43. BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}})
  44. signBytes := prop.SignBytes("test_chain_id")
  45. // sign it
  46. err := privVal.SignProposal("test_chain_id", prop)
  47. require.NoError(t, err)
  48. // verify the same proposal
  49. valid := pubKey.VerifyBytes(signBytes, prop.Signature)
  50. require.True(t, valid)
  51. // serialize, deserialize and verify again....
  52. newProp := new(Proposal)
  53. bs, err := cdc.MarshalBinaryLengthPrefixed(prop)
  54. require.NoError(t, err)
  55. err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp)
  56. require.NoError(t, err)
  57. // verify the transmitted proposal
  58. newSignBytes := newProp.SignBytes("test_chain_id")
  59. require.Equal(t, string(signBytes), string(newSignBytes))
  60. valid = pubKey.VerifyBytes(newSignBytes, newProp.Signature)
  61. require.True(t, valid)
  62. }
  63. func BenchmarkProposalWriteSignBytes(b *testing.B) {
  64. for i := 0; i < b.N; i++ {
  65. testProposal.SignBytes("test_chain_id")
  66. }
  67. }
  68. func BenchmarkProposalSign(b *testing.B) {
  69. privVal := NewMockPV()
  70. for i := 0; i < b.N; i++ {
  71. err := privVal.SignProposal("test_chain_id", testProposal)
  72. if err != nil {
  73. b.Error(err)
  74. }
  75. }
  76. }
  77. func BenchmarkProposalVerifySignature(b *testing.B) {
  78. privVal := NewMockPV()
  79. err := privVal.SignProposal("test_chain_id", testProposal)
  80. require.Nil(b, err)
  81. pubKey := privVal.GetPubKey()
  82. for i := 0; i < b.N; i++ {
  83. pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature)
  84. }
  85. }
  86. func TestProposalValidateBasic(t *testing.T) {
  87. privVal := NewMockPV()
  88. testCases := []struct {
  89. testName string
  90. malleateProposal func(*Proposal)
  91. expectErr bool
  92. }{
  93. {"Good Proposal", func(p *Proposal) {}, false},
  94. {"Invalid Type", func(p *Proposal) { p.Type = PrecommitType }, true},
  95. {"Invalid Height", func(p *Proposal) { p.Height = -1 }, true},
  96. {"Invalid Round", func(p *Proposal) { p.Round = -1 }, true},
  97. {"Invalid POLRound", func(p *Proposal) { p.POLRound = -2 }, true},
  98. {"Invalid BlockId", func(p *Proposal) {
  99. p.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}}
  100. }, true},
  101. {"Invalid Signature", func(p *Proposal) {
  102. p.Signature = make([]byte, 0)
  103. }, true},
  104. {"Too big Signature", func(p *Proposal) {
  105. p.Signature = make([]byte, MaxSignatureSize+1)
  106. }, true},
  107. }
  108. blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
  109. for _, tc := range testCases {
  110. t.Run(tc.testName, func(t *testing.T) {
  111. prop := NewProposal(
  112. 4, 2, 2,
  113. blockID)
  114. err := privVal.SignProposal("test_chain_id", prop)
  115. require.NoError(t, err)
  116. tc.malleateProposal(prop)
  117. assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result")
  118. })
  119. }
  120. }