github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/orderer/common/deliver/deliver_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package deliver 18 19 import ( 20 "fmt" 21 "testing" 22 "time" 23 24 "github.com/hyperledger/fabric/common/configtx/tool/provisional" 25 mockpolicies "github.com/hyperledger/fabric/common/mocks/policies" 26 "github.com/hyperledger/fabric/common/policies" 27 "github.com/hyperledger/fabric/orderer/ledger" 28 ramledger "github.com/hyperledger/fabric/orderer/ledger/ram" 29 cb "github.com/hyperledger/fabric/protos/common" 30 ab "github.com/hyperledger/fabric/protos/orderer" 31 "github.com/hyperledger/fabric/protos/utils" 32 logging "github.com/op/go-logging" 33 "google.golang.org/grpc" 34 ) 35 36 var genesisBlock = cb.NewBlock(0, nil) 37 38 var systemChainID = "systemChain" 39 40 const ledgerSize = 10 41 42 func init() { 43 logging.SetLevel(logging.DEBUG, "") 44 } 45 46 type mockD struct { 47 grpc.ServerStream 48 recvChan chan *cb.Envelope 49 sendChan chan *ab.DeliverResponse 50 } 51 52 func newMockD() *mockD { 53 return &mockD{ 54 recvChan: make(chan *cb.Envelope), 55 sendChan: make(chan *ab.DeliverResponse), 56 } 57 } 58 59 func (m *mockD) Send(br *ab.DeliverResponse) error { 60 m.sendChan <- br 61 return nil 62 } 63 64 func (m *mockD) Recv() (*cb.Envelope, error) { 65 msg, ok := <-m.recvChan 66 if !ok { 67 return msg, fmt.Errorf("Channel closed") 68 } 69 return msg, nil 70 } 71 72 type mockSupportManager struct { 73 chains map[string]*mockSupport 74 } 75 76 func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) { 77 cs, ok := mm.chains[chainID] 78 return cs, ok 79 } 80 81 type mockSupport struct { 82 ledger ledger.ReadWriter 83 policyManager *mockpolicies.Manager 84 } 85 86 func (mcs *mockSupport) PolicyManager() policies.Manager { 87 return mcs.policyManager 88 } 89 90 func (mcs *mockSupport) Reader() ledger.Reader { 91 return mcs.ledger 92 } 93 94 func NewRAMLedger() ledger.ReadWriter { 95 rlf := ramledger.New(ledgerSize + 1) 96 rl, _ := rlf.GetOrCreate(provisional.TestChainID) 97 rl.Append(genesisBlock) 98 return rl 99 } 100 101 func newMockMultichainManager() *mockSupportManager { 102 rl := NewRAMLedger() 103 mm := &mockSupportManager{ 104 chains: make(map[string]*mockSupport), 105 } 106 mm.chains[systemChainID] = &mockSupport{ 107 ledger: rl, 108 policyManager: &mockpolicies.Manager{Policy: &mockpolicies.Policy{}}, 109 } 110 return mm 111 } 112 113 var seekOldest = &ab.SeekPosition{Type: &ab.SeekPosition_Oldest{Oldest: &ab.SeekOldest{}}} 114 var seekNewest = &ab.SeekPosition{Type: &ab.SeekPosition_Newest{Newest: &ab.SeekNewest{}}} 115 116 func seekSpecified(number uint64) *ab.SeekPosition { 117 return &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: number}}} 118 } 119 120 func makeSeek(chainID string, seekInfo *ab.SeekInfo) *cb.Envelope { 121 return &cb.Envelope{ 122 Payload: utils.MarshalOrPanic(&cb.Payload{ 123 Header: &cb.Header{ 124 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 125 ChannelId: chainID, 126 }), 127 SignatureHeader: utils.MarshalOrPanic(&cb.SignatureHeader{}), 128 }, 129 Data: utils.MarshalOrPanic(seekInfo), 130 }), 131 } 132 } 133 134 func TestOldestSeek(t *testing.T) { 135 mm := newMockMultichainManager() 136 for i := 1; i < ledgerSize; i++ { 137 l := mm.chains[systemChainID].ledger 138 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 139 } 140 141 m := newMockD() 142 defer close(m.recvChan) 143 ds := NewHandlerImpl(mm) 144 145 go ds.Handle(m) 146 147 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekOldest, Stop: seekNewest, Behavior: ab.SeekInfo_BLOCK_UNTIL_READY}) 148 149 count := uint64(0) 150 for { 151 select { 152 case deliverReply := <-m.sendChan: 153 if deliverReply.GetBlock() == nil { 154 if deliverReply.GetStatus() != cb.Status_SUCCESS { 155 t.Fatalf("Received an error on the reply channel") 156 } 157 if count != ledgerSize { 158 t.Fatalf("Expected %d blocks but got %d", ledgerSize, count) 159 } 160 return 161 } 162 if deliverReply.GetBlock().Header.Number != count { 163 t.Fatalf("Expected block %d but got block %d", count, deliverReply.GetBlock().Header.Number) 164 } 165 case <-time.After(time.Second): 166 t.Fatalf("Timed out waiting to get all blocks") 167 } 168 count++ 169 } 170 } 171 172 func TestNewestSeek(t *testing.T) { 173 mm := newMockMultichainManager() 174 for i := 1; i < ledgerSize; i++ { 175 l := mm.chains[systemChainID].ledger 176 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 177 } 178 179 m := newMockD() 180 defer close(m.recvChan) 181 ds := NewHandlerImpl(mm) 182 183 go ds.Handle(m) 184 185 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekNewest, Stop: seekNewest, Behavior: ab.SeekInfo_BLOCK_UNTIL_READY}) 186 187 select { 188 case deliverReply := <-m.sendChan: 189 if deliverReply.GetBlock() == nil { 190 if deliverReply.GetStatus() != cb.Status_SUCCESS { 191 t.Fatalf("Received an error on the reply channel") 192 } 193 return 194 } 195 if deliverReply.GetBlock().Header.Number != uint64(ledgerSize-1) { 196 t.Fatalf("Expected only the most recent block") 197 } 198 case <-time.After(time.Second): 199 t.Fatalf("Timed out waiting to get all blocks") 200 } 201 } 202 203 func TestSpecificSeek(t *testing.T) { 204 mm := newMockMultichainManager() 205 for i := 1; i < ledgerSize; i++ { 206 l := mm.chains[systemChainID].ledger 207 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 208 } 209 210 m := newMockD() 211 defer close(m.recvChan) 212 ds := NewHandlerImpl(mm) 213 specifiedStart := uint64(3) 214 specifiedStop := uint64(7) 215 216 go ds.Handle(m) 217 218 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(specifiedStart), Stop: seekSpecified(specifiedStop), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY}) 219 220 count := uint64(0) 221 for { 222 select { 223 case deliverReply := <-m.sendChan: 224 if deliverReply.GetBlock() == nil { 225 if deliverReply.GetStatus() != cb.Status_SUCCESS { 226 t.Fatalf("Received an error on the reply channel") 227 } 228 return 229 } 230 if expected := specifiedStart + count; deliverReply.GetBlock().Header.Number != expected { 231 t.Fatalf("Expected block %d but got block %d", expected, deliverReply.GetBlock().Header.Number) 232 } 233 case <-time.After(time.Second): 234 t.Fatalf("Timed out waiting to get all blocks") 235 } 236 count++ 237 } 238 } 239 240 func TestUnauthorizedSeek(t *testing.T) { 241 mm := newMockMultichainManager() 242 for i := 1; i < ledgerSize; i++ { 243 l := mm.chains[systemChainID].ledger 244 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 245 } 246 mm.chains[systemChainID].policyManager.Policy.Err = fmt.Errorf("Fail to evaluate policy") 247 248 m := newMockD() 249 defer close(m.recvChan) 250 ds := NewHandlerImpl(mm) 251 252 go ds.Handle(m) 253 254 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(0)), Stop: seekSpecified(uint64(0)), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY}) 255 256 select { 257 case deliverReply := <-m.sendChan: 258 if deliverReply.GetStatus() != cb.Status_FORBIDDEN { 259 t.Fatalf("Received wrong error on the reply channel") 260 } 261 case <-time.After(time.Second): 262 t.Fatalf("Timed out waiting to get all blocks") 263 } 264 } 265 266 func TestBadSeek(t *testing.T) { 267 mm := newMockMultichainManager() 268 for i := 1; i < ledgerSize; i++ { 269 l := mm.chains[systemChainID].ledger 270 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 271 } 272 273 m := newMockD() 274 defer close(m.recvChan) 275 ds := NewHandlerImpl(mm) 276 277 go ds.Handle(m) 278 279 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(3 * ledgerSize)), Stop: seekSpecified(uint64(3 * ledgerSize)), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY}) 280 281 select { 282 case deliverReply := <-m.sendChan: 283 if deliverReply.GetStatus() != cb.Status_NOT_FOUND { 284 t.Fatalf("Received wrong error on the reply channel") 285 } 286 case <-time.After(time.Second): 287 t.Fatalf("Timed out waiting to get all blocks") 288 } 289 } 290 291 func TestFailFastSeek(t *testing.T) { 292 mm := newMockMultichainManager() 293 for i := 1; i < ledgerSize; i++ { 294 l := mm.chains[systemChainID].ledger 295 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 296 } 297 298 m := newMockD() 299 defer close(m.recvChan) 300 ds := NewHandlerImpl(mm) 301 302 go ds.Handle(m) 303 304 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(ledgerSize - 1)), Stop: seekSpecified(ledgerSize), Behavior: ab.SeekInfo_FAIL_IF_NOT_READY}) 305 306 select { 307 case deliverReply := <-m.sendChan: 308 if deliverReply.GetBlock() == nil { 309 t.Fatalf("Expected to receive first block") 310 } 311 case <-time.After(time.Second): 312 t.Fatalf("Timed out waiting to get all blocks") 313 } 314 315 select { 316 case deliverReply := <-m.sendChan: 317 if deliverReply.GetStatus() != cb.Status_NOT_FOUND { 318 t.Fatalf("Expected to receive failure for second block") 319 } 320 case <-time.After(time.Second): 321 t.Fatalf("Timed out waiting to get all blocks") 322 } 323 } 324 325 func TestBlockingSeek(t *testing.T) { 326 mm := newMockMultichainManager() 327 for i := 1; i < ledgerSize; i++ { 328 l := mm.chains[systemChainID].ledger 329 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}})) 330 } 331 332 m := newMockD() 333 defer close(m.recvChan) 334 ds := NewHandlerImpl(mm) 335 336 go ds.Handle(m) 337 338 m.recvChan <- makeSeek(systemChainID, &ab.SeekInfo{Start: seekSpecified(uint64(ledgerSize - 1)), Stop: seekSpecified(ledgerSize), Behavior: ab.SeekInfo_BLOCK_UNTIL_READY}) 339 340 select { 341 case deliverReply := <-m.sendChan: 342 if deliverReply.GetBlock() == nil { 343 t.Fatalf("Expected to receive first block") 344 } 345 case <-time.After(time.Second): 346 t.Fatalf("Timed out waiting to get first block") 347 } 348 349 select { 350 case <-m.sendChan: 351 t.Fatalf("Should not have delivered an error or second block") 352 case <-time.After(50 * time.Millisecond): 353 } 354 355 l := mm.chains[systemChainID].ledger 356 l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", ledgerSize+1))}})) 357 358 select { 359 case deliverReply := <-m.sendChan: 360 if deliverReply.GetBlock() == nil { 361 t.Fatalf("Expected to receive new block") 362 } 363 case <-time.After(time.Second): 364 t.Fatalf("Timed out waiting to get new block") 365 } 366 367 select { 368 case deliverReply := <-m.sendChan: 369 if deliverReply.GetStatus() != cb.Status_SUCCESS { 370 t.Fatalf("Expected delivery to complete") 371 } 372 case <-time.After(time.Second): 373 t.Fatalf("Timed out waiting to get all blocks") 374 } 375 }