github.com/klaytn/klaytn@v1.12.1/consensus/istanbul/core/prepare_test.go (about) 1 package core 2 3 import ( 4 "math/big" 5 "math/rand" 6 "reflect" 7 "testing" 8 "time" 9 10 "github.com/golang/mock/gomock" 11 "github.com/klaytn/klaytn/blockchain/types" 12 "github.com/klaytn/klaytn/common" 13 "github.com/klaytn/klaytn/consensus/istanbul" 14 mock_istanbul "github.com/klaytn/klaytn/consensus/istanbul/mocks" 15 "github.com/klaytn/klaytn/fork" 16 "github.com/klaytn/klaytn/params" 17 "github.com/stretchr/testify/assert" 18 ) 19 20 func TestCore_sendPrepare(t *testing.T) { 21 fork.SetHardForkBlockNumberConfig(¶ms.ChainConfig{}) 22 defer fork.ClearHardForkBlockNumberConfig() 23 24 validatorAddrs, validatorKeyMap := genValidators(6) 25 mockBackend, mockCtrl := newMockBackend(t, validatorAddrs) 26 27 istConfig := istanbul.DefaultConfig 28 istConfig.ProposerPolicy = istanbul.WeightedRandom 29 30 istCore := New(mockBackend, istConfig).(*core) 31 if err := istCore.Start(); err != nil { 32 t.Fatal(err) 33 } 34 defer istCore.Stop() 35 36 lastProposal, lastProposer := mockBackend.LastProposal() 37 proposal, err := genBlock(lastProposal.(*types.Block), validatorKeyMap[validatorAddrs[0]]) 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 istCore.current.Preprepare = &istanbul.Preprepare{ 43 View: istCore.currentView(), 44 Proposal: proposal, 45 } 46 47 mockCtrl.Finish() 48 49 // invalid case - not committee 50 { 51 // Increase round number until the owner of istanbul.core is not a member of the committee 52 for istCore.valSet.CheckInSubList(lastProposal.Hash(), istCore.currentView(), istCore.Address()) { 53 istCore.current.round.Add(istCore.current.round, common.Big1) 54 istCore.valSet.CalcProposer(lastProposer, istCore.current.round.Uint64()) 55 } 56 57 mockCtrl := gomock.NewController(t) 58 mockBackend := mock_istanbul.NewMockBackend(mockCtrl) 59 mockBackend.EXPECT().Sign(gomock.Any()).Return(nil, nil).Times(0) 60 mockBackend.EXPECT().Broadcast(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(0) 61 62 istCore.backend = mockBackend 63 istCore.sendPrepare() 64 65 // methods of mockBackend should be executed given times 66 mockCtrl.Finish() 67 } 68 69 // valid case 70 { 71 // Increase round number until the owner of istanbul.core become a member of the committee 72 for !istCore.valSet.CheckInSubList(lastProposal.Hash(), istCore.currentView(), istCore.Address()) { 73 istCore.current.round.Add(istCore.current.round, common.Big1) 74 istCore.valSet.CalcProposer(lastProposer, istCore.current.round.Uint64()) 75 } 76 77 mockCtrl := gomock.NewController(t) 78 mockBackend := mock_istanbul.NewMockBackend(mockCtrl) 79 mockBackend.EXPECT().Sign(gomock.Any()).Return(nil, nil).Times(1) 80 mockBackend.EXPECT().Broadcast(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1) 81 82 istCore.backend = mockBackend 83 istCore.sendPrepare() 84 85 // methods of mockBackend should be executed given times 86 mockCtrl.Finish() 87 } 88 } 89 90 func BenchmarkMsgCmp(b *testing.B) { 91 getEmptySubject := func() istanbul.Subject { 92 return istanbul.Subject{ 93 View: &istanbul.View{ 94 Round: big.NewInt(0), 95 Sequence: big.NewInt(0), 96 }, 97 Digest: common.HexToHash("1"), 98 PrevHash: common.HexToHash("2"), 99 } 100 } 101 s1, s2 := getEmptySubject(), getEmptySubject() 102 103 // Worst 104 b.Run("reflect.DeepEqual", func(b *testing.B) { 105 for i := 0; i < b.N; i++ { 106 reflect.DeepEqual(s1, s2) 107 } 108 }) 109 110 // Better 111 b.Run("EqualImpl", func(b *testing.B) { 112 for i := 0; i < b.N; i++ { 113 s1.Equal(&s2) 114 } 115 }) 116 } 117 118 func TestSubjectCmp(t *testing.T) { 119 genRandomHash := func(n int) common.Hash { 120 b := make([]byte, n) 121 _, err := rand.Read(b) 122 assert.Nil(t, err) 123 return common.BytesToHash(b) 124 } 125 genRandomInt := func(min, max int) int64 { 126 return int64(rand.Intn(max-min) + min) 127 } 128 genSubject := func(min, max int) *istanbul.Subject { 129 round, seq := big.NewInt(genRandomInt(min, max)), big.NewInt(genRandomInt(min, max)) 130 digest, prevHash := genRandomHash(max), genRandomHash(max) 131 return &istanbul.Subject{ 132 View: &istanbul.View{ 133 Round: round, 134 Sequence: seq, 135 }, 136 Digest: digest, 137 PrevHash: prevHash, 138 } 139 } 140 copySubject := func(s *istanbul.Subject) *istanbul.Subject { 141 r := new(istanbul.Subject) 142 v := new(istanbul.View) 143 r.Digest = s.Digest 144 r.PrevHash = s.PrevHash 145 v.Round = new(big.Int).SetUint64(s.View.Round.Uint64()) 146 v.Sequence = new(big.Int).SetUint64(s.View.Sequence.Uint64()) 147 r.View = v 148 return r 149 } 150 151 rand.Seed(time.Now().UnixNano()) 152 min, max, n := 1, 9999, 10000 153 var identity bool 154 var s1, s2 *istanbul.Subject 155 for i := 0; i < n; i++ { 156 s1 = genSubject(min, max) 157 if rand.Intn(2) == 0 { 158 identity = true 159 s2 = copySubject(s1) 160 } else { 161 identity = false 162 s2 = genSubject(max+1, max*2) 163 } 164 e := s1.Equal(s2) 165 if identity { 166 assert.Equal(t, e, true) 167 } else { 168 assert.Equal(t, e, false) 169 } 170 assert.Equal(t, e, reflect.DeepEqual(s1, s2)) 171 } 172 } 173 174 func TestNilSubjectCmp(t *testing.T) { 175 sbj := istanbul.Subject{ 176 View: &istanbul.View{ 177 Round: big.NewInt(0), 178 Sequence: big.NewInt(0), 179 }, 180 Digest: common.HexToHash("1"), 181 PrevHash: common.HexToHash("2"), 182 } 183 var nilSbj *istanbul.Subject = nil 184 185 assert.Equal(t, sbj.Equal(nil), false) 186 assert.Equal(t, sbj.Equal(nilSbj), false) 187 assert.Equal(t, nilSbj.Equal(&sbj), false) 188 assert.Equal(t, nilSbj.Equal(nilSbj), true) 189 assert.Equal(t, nilSbj.Equal(nil), true) 190 }