github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/backlog_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 "math/big" 21 "reflect" 22 "sync" 23 "testing" 24 "time" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/consensus/podc" 28 "github.com/ethereum/go-ethereum/consensus/podc/validator" 29 "github.com/ethereum/go-ethereum/event" 30 "github.com/ethereum/go-ethereum/log" 31 "gopkg.in/karalabe/cookiejar.v2/collections/prque" 32 ) 33 34 func TestCheckMessage(t *testing.T) { 35 c := &core{ 36 state: StateAcceptRequest, 37 current: newRoundState(&podc.View{ 38 Sequence: big.NewInt(1), 39 Round: big.NewInt(0), 40 }, newTestValidatorSet(4)), 41 } 42 43 // invalid view format 44 err := c.checkMessage(msgPreprepare, nil) 45 if err != errInvalidMessage { 46 t.Errorf("error mismatch: have %v, want %v", err, errInvalidMessage) 47 } 48 49 testStates := []State{StateAcceptRequest, StateRequestQman, StatePreprepared, StateDSelected, StateCommitted} 50 testCode := []uint64{msgPreprepare, msgDSelect, msgCommit} //msgDSelect 51 52 // future sequence 53 v := &podc.View{ 54 Sequence: big.NewInt(2), 55 Round: big.NewInt(0), 56 } 57 for i := 0; i < len(testStates); i++ { 58 c.state = testStates[i] 59 for j := 0; j < len(testCode); j++ { 60 err := c.checkMessage(testCode[j], v) 61 if err != errFutureMessage { 62 t.Errorf("error mismatch: have %v, want %v", err, errFutureMessage) 63 } 64 } 65 } 66 67 // future round 68 v = &podc.View{ 69 Sequence: big.NewInt(1), 70 Round: big.NewInt(1), 71 } 72 for i := 0; i < len(testStates); i++ { 73 c.state = testStates[i] 74 for j := 0; j < len(testCode); j++ { 75 err := c.checkMessage(testCode[j], v) 76 if err != errFutureMessage { 77 t.Errorf("error mismatch: have %v, want %v", err, errFutureMessage) 78 } 79 } 80 } 81 82 // current view but waiting for round change 83 v = &podc.View{ 84 Sequence: big.NewInt(1), 85 Round: big.NewInt(0), 86 } 87 c.waitingForRoundChange = true 88 for i := 0; i < len(testStates); i++ { 89 c.state = testStates[i] 90 for j := 0; j < len(testCode); j++ { 91 err := c.checkMessage(testCode[j], v) 92 if err != errFutureMessage { 93 t.Errorf("error mismatch: have %v, want %v", err, errFutureMessage) 94 } 95 } 96 } 97 c.waitingForRoundChange = false 98 99 v = c.currentView() 100 // current view, state = StateAcceptRequest 101 c.state = StateAcceptRequest 102 for i := 0; i < len(testCode); i++ { 103 err = c.checkMessage(testCode[i], v) 104 if testCode[i] == msgPreprepare { 105 if err != nil { 106 t.Errorf("error mismatch: have %v, want nil", err) 107 } 108 } else { 109 if err != errFutureMessage { 110 //yicho temp: t.Errorf("error mismatch: have %v, want %v", err, errFutureMessage) 111 } 112 } 113 } 114 115 // current view, state = StatePreprepared 116 c.state = StatePreprepared 117 for i := 0; i < len(testCode); i++ { 118 err = c.checkMessage(testCode[i], v) 119 if err != nil { 120 t.Errorf("error mismatch: have %v, want nil", err) 121 } 122 } 123 124 // current view, state = StatePrepared 125 c.state = StateDSelected //StatePrepared 126 for i := 0; i < len(testCode); i++ { 127 err = c.checkMessage(testCode[i], v) 128 if err != nil { 129 t.Errorf("error mismatch: have %v, want nil", err) 130 } 131 } 132 133 // current view, state = StateCommitted 134 c.state = StateDCommitted 135 for i := 0; i < len(testCode); i++ { 136 err = c.checkMessage(testCode[i], v) 137 if err != nil { 138 t.Errorf("error mismatch: have %v, want nil", err) 139 } 140 } 141 142 } 143 144 func TestStoreBacklog(t *testing.T) { 145 c := &core{ 146 logger: log.New("backend", "test", "id", 0), 147 backlogs: make(map[podc.Validator]*prque.Prque), 148 backlogsMu: new(sync.Mutex), 149 } 150 v := &podc.View{ 151 Round: big.NewInt(10), 152 Sequence: big.NewInt(10), 153 } 154 p := validator.New(common.StringToAddress("12345667890")) 155 // push preprepare msg 156 preprepare := &podc.Preprepare{ 157 View: v, 158 Proposal: makeBlock(1), 159 } 160 prepreparePayload, _ := Encode(preprepare) 161 m := &message{ 162 Code: msgPreprepare, 163 Msg: prepreparePayload, 164 } 165 c.storeBacklog(m, p) 166 msg := c.backlogs[p].PopItem() 167 if !reflect.DeepEqual(msg, m) { 168 t.Errorf("message mismatch: have %v, want %v", msg, m) 169 } 170 171 // push prepare msg 172 subject := &podc.Subject{ 173 View: v, 174 Digest: common.StringToHash("1234567890"), 175 } 176 subjectPayload, _ := Encode(subject) 177 178 m = &message{ 179 Code: msgDSelect, 180 Msg: subjectPayload, 181 } 182 c.storeBacklog(m, p) 183 msg = c.backlogs[p].PopItem() 184 if !reflect.DeepEqual(msg, m) { 185 t.Errorf("message mismatch: have %v, want %v", msg, m) 186 } 187 188 // push commit msg 189 m = &message{ 190 Code: msgDCommit, 191 Msg: subjectPayload, 192 } 193 c.storeBacklog(m, p) 194 msg = c.backlogs[p].PopItem() 195 if !reflect.DeepEqual(msg, m) { 196 t.Errorf("message mismatch: have %v, want %v", msg, m) 197 } 198 } 199 200 func TestProcessFutureBacklog(t *testing.T) { 201 backend := &testSystemBackend{ 202 events: new(event.TypeMux), 203 } 204 var c = &core{ 205 logger: log.New("backend", "test", "id", 0), 206 backlogs: make(map[podc.Validator]*prque.Prque), 207 backlogsMu: new(sync.Mutex), 208 backend: backend, //podc.Backend 209 current: newRoundState(&podc.View{ 210 Sequence: big.NewInt(1), 211 Round: big.NewInt(0), 212 }, newTestValidatorSet(4)), 213 state: StateAcceptRequest, 214 } 215 c.subscribeEvents() 216 defer c.unsubscribeEvents() 217 218 v := &podc.View{ 219 Round: big.NewInt(10), 220 Sequence: big.NewInt(10), 221 } 222 p := validator.New(common.StringToAddress("12345667890")) 223 // push a future msg 224 subject := &podc.Subject{ 225 View: v, 226 Digest: common.StringToHash("1234567890"), 227 } 228 subjectPayload, _ := Encode(subject) 229 m := &message{ 230 Code: msgDCommit, 231 Msg: subjectPayload, 232 } 233 c.storeBacklog(m, p) 234 c.processBacklog() 235 236 const timeoutDura = 2 * time.Second 237 timeout := time.NewTimer(timeoutDura) 238 select { 239 case e := <-c.events.Chan(): 240 t.Errorf("unexpected events comes: %v", e) 241 case <-timeout.C: 242 // success 243 } 244 } 245 246 func TestProcessBacklog(t *testing.T) { 247 v := &podc.View{ 248 Round: big.NewInt(0), 249 Sequence: big.NewInt(1), 250 } 251 preprepare := &podc.Preprepare{ 252 View: v, 253 Proposal: makeBlock(1), 254 } 255 prepreparePayload, _ := Encode(preprepare) 256 257 subject := &podc.Subject{ 258 View: v, 259 Digest: common.StringToHash("1234567890"), 260 } 261 subjectPayload, _ := Encode(subject) 262 263 msgs := []*message{ 264 &message{ 265 Code: msgPreprepare, 266 Msg: prepreparePayload, 267 }, 268 &message{ 269 Code: msgDSelect, 270 Msg: subjectPayload, 271 }, 272 &message{ 273 Code: msgDCommit, 274 Msg: subjectPayload, 275 }, 276 } 277 for i := 0; i < len(msgs); i++ { 278 testProcessBacklog(t, msgs[i]) 279 } 280 } 281 282 func testProcessBacklog(t *testing.T, msg *message) { 283 vset := newTestValidatorSet(1) 284 backend := &testSystemBackend{ 285 events: new(event.TypeMux), 286 peers: vset, 287 } 288 c := &core{ 289 logger: log.New("backend", "test", "id", 0), 290 backlogs: make(map[podc.Validator]*prque.Prque), 291 backlogsMu: new(sync.Mutex), 292 backend: backend, 293 state: State(msg.Code), 294 current: newRoundState(&podc.View{ 295 Sequence: big.NewInt(1), 296 Round: big.NewInt(0), 297 }, newTestValidatorSet(4)), 298 } 299 c.subscribeEvents() 300 defer c.unsubscribeEvents() 301 302 c.storeBacklog(msg, vset.GetByIndex(0)) 303 c.processBacklog() 304 305 const timeoutDura = 2 * time.Second 306 timeout := time.NewTimer(timeoutDura) 307 select { 308 case ev := <-c.events.Chan(): 309 e, ok := ev.Data.(backlogEvent) 310 if !ok { 311 t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data)) 312 } 313 if e.msg.Code != msg.Code { 314 t.Errorf("message code mismatch: have %v, want %v", e.msg.Code, msg.Code) 315 } 316 // success 317 case <-timeout.C: 318 t.Error("unexpected timeout occurs") 319 } 320 }