github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/preprepare_test.go (about) 1 // Copyright 2017 AMIS Technologies 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "github.com/ethereum/go-ethereum/log" 21 //"github.com/ethereum/go-ethereum/log" 22 "math/big" 23 "reflect" 24 "testing" 25 26 "github.com/ethereum/go-ethereum/consensus/podc" 27 ) 28 29 func newTestPreprepare(v *podc.View) *podc.Preprepare { 30 return &podc.Preprepare{ 31 View: v, 32 Proposal: newTestProposal(), 33 } 34 } 35 36 func TestHandlePreprepare(t *testing.T) { 37 N := uint64(20) // replica 0 is primary, it will send messages to others 38 F := uint64(1) // F does not affect tests 39 40 testCases := []struct { 41 system *testSystem 42 expectedRequest podc.Proposal 43 expectedErr error 44 }{ 45 { 46 // normal case 47 func() *testSystem { 48 sys := NewTestSystemWithBackend(N, F) 49 50 for i, backend := range sys.backends { 51 c := backend.engine.(*core) 52 c.valSet = backend.peers 53 if i != 0 { 54 c.state = StateAcceptRequest 55 } 56 } 57 return sys 58 }(), 59 newTestProposal(), 60 nil, 61 }, 62 { 63 // future message 64 func() *testSystem { 65 sys := NewTestSystemWithBackend(N, F) 66 67 for i, backend := range sys.backends { 68 c := backend.engine.(*core) 69 c.valSet = backend.peers 70 if i != 0 { 71 c.state = StateAcceptRequest 72 // hack: force set subject that future message can be simulated 73 c.current = newTestRoundState( 74 &podc.View{ 75 Round: big.NewInt(0), 76 Sequence: big.NewInt(0), 77 }, 78 c.valSet, 79 ) 80 81 } else { 82 c.current.SetSequence(big.NewInt(10)) 83 } 84 } 85 return sys 86 }(), 87 makeBlock(1), 88 errFutureMessage, 89 }, 90 { 91 // non-proposer 92 func() *testSystem { 93 sys := NewTestSystemWithBackend(N, F) 94 95 // force remove replica 0, let replica 1 become primary 96 sys.backends = sys.backends[1:] 97 98 for i, backend := range sys.backends { 99 c := backend.engine.(*core) 100 c.valSet = backend.peers 101 if i != 0 { 102 // replica 0 is primary 103 c.state = StatePreprepared 104 } 105 } 106 return sys 107 }(), 108 makeBlock(1), 109 errNotFromProposer, 110 }, 111 { 112 // ErrInvalidMessage 113 func() *testSystem { 114 sys := NewTestSystemWithBackend(N, F) 115 116 for i, backend := range sys.backends { 117 c := backend.engine.(*core) 118 c.valSet = backend.peers 119 if i != 0 { 120 c.state = StatePreprepared 121 c.current.SetSequence(big.NewInt(10)) 122 c.current.SetRound(big.NewInt(10)) 123 } 124 } 125 return sys 126 }(), 127 makeBlock(1), 128 errOldMessage, 129 }, 130 } 131 132 OUTER: 133 for _, test := range testCases { 134 test.system.Run(false) 135 136 v0 := test.system.backends[0] 137 r0 := v0.engine.(*core) 138 139 curView := r0.currentView() 140 141 preprepare := &podc.Preprepare{ 142 View: curView, 143 Proposal: test.expectedRequest, 144 } 145 146 for i, v := range test.system.backends { 147 // i == 0 is primary backend, it is responsible for send preprepare messages to others. 148 if i == 0 { 149 continue 150 } 151 152 c := v.engine.(*core) 153 154 m, _ := Encode(preprepare) 155 _, val := r0.valSet.GetByAddress(v0.Address()) 156 // run each backends and verify handlePreprepare function. 157 log.Info("Address", "Address", v0.Address() ) 158 if err := c.handlePreprepare(&message{ 159 Code: msgPreprepare, 160 Msg: m, 161 Address: v0.Address(), 162 }, val); err != nil { 163 if err != test.expectedErr { 164 t.Errorf("error mismatch: have %v, want %v", err, test.expectedErr) 165 } 166 continue OUTER 167 } 168 169 if c.state != StatePreprepared { 170 t.Errorf("state mismatch: have %v, want %v", c.state, StatePreprepared) 171 } 172 173 if !reflect.DeepEqual(c.current.Subject().View, curView) { 174 t.Errorf("view mismatch: have %v, want %v", c.current.Subject().View, curView) 175 } 176 177 // verify prepare messages 178 //log.Info("message=", "message",message) 179 //testmsg := &message{ 180 // Code: msgPreprepare, 181 // Msg: m, 182 // Address: v0.Address(), 183 //} 184 decodedMsg := new(message) 185 err := decodedMsg.FromPayload(v.sentMsgs[0], nil) 186 if err != nil { 187 t.Errorf("error mismatch: have %v, want nil", err) 188 } 189 190 if decodedMsg.Code != msgDSelect { 191 t.Errorf("message code mismatch: have %v, want %v", decodedMsg.Code, msgDSelect) 192 } 193 var subject *podc.Subject 194 err = decodedMsg.Decode(&subject) 195 if err != nil { 196 t.Errorf("error mismatch: have %v, want nil", err) 197 } 198 if !reflect.DeepEqual(subject, c.current.Subject()) { 199 t.Errorf("subject mismatch: have %v, want %v", subject, c.current.Subject()) 200 } 201 } 202 } 203 }