github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/deliverservice/deliveryclient_test.go (about) 1 /* 2 Copyright IBM Corp. 2017 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 deliverclient 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "runtime" 24 "sync" 25 "sync/atomic" 26 "testing" 27 "time" 28 29 "github.com/hyperledger/fabric/core/deliverservice/blocksprovider" 30 "github.com/hyperledger/fabric/core/deliverservice/mocks" 31 "github.com/hyperledger/fabric/gossip/api" 32 "github.com/hyperledger/fabric/gossip/common" 33 "github.com/hyperledger/fabric/msp/mgmt/testtools" 34 "github.com/hyperledger/fabric/protos/orderer" 35 "github.com/stretchr/testify/assert" 36 "google.golang.org/grpc" 37 ) 38 39 func init() { 40 msptesttools.LoadMSPSetupForTesting() 41 } 42 43 const ( 44 goRoutineTestWaitTimeout = time.Second * 15 45 ) 46 47 var ( 48 lock = sync.Mutex{} 49 ) 50 51 type mockBlocksDelivererFactory struct { 52 mockCreate func() (blocksprovider.BlocksDeliverer, error) 53 } 54 55 func (mock *mockBlocksDelivererFactory) Create() (blocksprovider.BlocksDeliverer, error) { 56 return mock.mockCreate() 57 } 58 59 type mockMCS struct { 60 } 61 62 func (*mockMCS) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType { 63 return common.PKIidType("pkiID") 64 } 65 66 func (*mockMCS) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error { 67 return nil 68 } 69 70 func (*mockMCS) Sign(msg []byte) ([]byte, error) { 71 return msg, nil 72 } 73 74 func (*mockMCS) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error { 75 return nil 76 } 77 78 func (*mockMCS) VerifyByChannel(chainID common.ChainID, peerIdentity api.PeerIdentityType, signature, message []byte) error { 79 return nil 80 } 81 82 func (*mockMCS) ValidateIdentity(peerIdentity api.PeerIdentityType) error { 83 return nil 84 } 85 86 func TestNewDeliverService(t *testing.T) { 87 defer ensureNoGoroutineLeak(t)() 88 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64, 1)} 89 factory := &struct{ mockBlocksDelivererFactory }{} 90 91 blocksDeliverer := &mocks.MockBlocksDeliverer{} 92 blocksDeliverer.MockRecv = mocks.MockRecv 93 94 factory.mockCreate = func() (blocksprovider.BlocksDeliverer, error) { 95 return blocksDeliverer, nil 96 } 97 abcf := func(*grpc.ClientConn) orderer.AtomicBroadcastClient { 98 return &mocks.MockAtomicBroadcastClient{blocksDeliverer} 99 } 100 101 connFactory := func(_ string) func(string) (*grpc.ClientConn, error) { 102 return func(endpoint string) (*grpc.ClientConn, error) { 103 lock.Lock() 104 defer lock.Unlock() 105 return newConnection(), nil 106 } 107 } 108 service, err := NewDeliverService(&Config{ 109 Endpoints: []string{"a"}, 110 Gossip: gossipServiceAdapter, 111 CryptoSvc: &mockMCS{}, 112 ABCFactory: abcf, 113 ConnFactory: connFactory, 114 }) 115 assert.NoError(t, err) 116 assert.NoError(t, service.StartDeliverForChannel("TEST_CHAINID", &mocks.MockLedgerInfo{0})) 117 118 // Lets start deliver twice 119 assert.Error(t, service.StartDeliverForChannel("TEST_CHAINID", &mocks.MockLedgerInfo{0}), "can't start delivery") 120 // Lets stop deliver that not started 121 assert.Error(t, service.StopDeliverForChannel("TEST_CHAINID2"), "can't stop delivery") 122 123 // Let it try to simulate a few recv -> gossip rounds 124 time.Sleep(time.Second) 125 assert.NoError(t, service.StopDeliverForChannel("TEST_CHAINID")) 126 time.Sleep(time.Duration(10) * time.Millisecond) 127 // Make sure to stop all blocks providers 128 service.Stop() 129 time.Sleep(time.Duration(500) * time.Millisecond) 130 assert.Equal(t, 0, connNumber) 131 assertBlockDissemination(0, gossipServiceAdapter.GossipBlockDisseminations, t) 132 assert.Equal(t, atomic.LoadInt32(&blocksDeliverer.RecvCnt), atomic.LoadInt32(&gossipServiceAdapter.AddPayloadsCnt)) 133 assert.Error(t, service.StartDeliverForChannel("TEST_CHAINID", &mocks.MockLedgerInfo{0}), "Delivery service is stopping") 134 assert.Error(t, service.StopDeliverForChannel("TEST_CHAINID"), "Delivery service is stopping") 135 } 136 137 func TestDeliverServiceRestart(t *testing.T) { 138 defer ensureNoGoroutineLeak(t)() 139 // Scenario: bring up ordering service instance, then shut it down, and then resurrect it. 140 // Client is expected to reconnect to it, and to ask for a block sequence that is the next block 141 // after the last block it got from the previous incarnation of the ordering service. 142 143 os := mocks.NewOrderer(5611, t) 144 145 time.Sleep(time.Second) 146 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 147 148 service, err := NewDeliverService(&Config{ 149 Endpoints: []string{"localhost:5611"}, 150 Gossip: gossipServiceAdapter, 151 CryptoSvc: &mockMCS{}, 152 ABCFactory: DefaultABCFactory, 153 ConnFactory: DefaultConnectionFactory, 154 }) 155 assert.NoError(t, err) 156 157 li := &mocks.MockLedgerInfo{Height: uint64(100)} 158 os.SetNextExpectedSeek(uint64(100)) 159 160 err = service.StartDeliverForChannel("TEST_CHAINID", li) 161 assert.NoError(t, err, "can't start delivery") 162 // Check that delivery client requests blocks in order 163 go os.SendBlock(uint64(100)) 164 assertBlockDissemination(100, gossipServiceAdapter.GossipBlockDisseminations, t) 165 go os.SendBlock(uint64(101)) 166 assertBlockDissemination(101, gossipServiceAdapter.GossipBlockDisseminations, t) 167 go os.SendBlock(uint64(102)) 168 assertBlockDissemination(102, gossipServiceAdapter.GossipBlockDisseminations, t) 169 os.Shutdown() 170 time.Sleep(time.Second * 3) 171 os = mocks.NewOrderer(5611, t) 172 li.Height = 103 173 os.SetNextExpectedSeek(uint64(103)) 174 go os.SendBlock(uint64(103)) 175 assertBlockDissemination(103, gossipServiceAdapter.GossipBlockDisseminations, t) 176 service.Stop() 177 os.Shutdown() 178 } 179 180 func TestDeliverServiceFailover(t *testing.T) { 181 defer ensureNoGoroutineLeak(t)() 182 // Scenario: bring up 2 ordering service instances, 183 // and shut down the instance that the client has connected to. 184 // Client is expected to connect to the other instance, and to ask for a block sequence that is the next block 185 // after the last block it got from the ordering service that was shut down. 186 // Then, shut down the other node, and bring back the first (that was shut down first). 187 188 os1 := mocks.NewOrderer(5612, t) 189 os2 := mocks.NewOrderer(5613, t) 190 191 time.Sleep(time.Second) 192 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 193 194 service, err := NewDeliverService(&Config{ 195 Endpoints: []string{"localhost:5612", "localhost:5613"}, 196 Gossip: gossipServiceAdapter, 197 CryptoSvc: &mockMCS{}, 198 ABCFactory: DefaultABCFactory, 199 ConnFactory: DefaultConnectionFactory, 200 }) 201 assert.NoError(t, err) 202 li := &mocks.MockLedgerInfo{Height: uint64(100)} 203 os1.SetNextExpectedSeek(uint64(100)) 204 os2.SetNextExpectedSeek(uint64(100)) 205 206 err = service.StartDeliverForChannel("TEST_CHAINID", li) 207 assert.NoError(t, err, "can't start delivery") 208 // We need to discover to which instance the client connected to 209 go os1.SendBlock(uint64(100)) 210 instance2fail := os1 211 reincarnatedNodePort := 5612 212 instance2failSecond := os2 213 select { 214 case seq := <-gossipServiceAdapter.GossipBlockDisseminations: 215 assert.Equal(t, uint64(100), seq) 216 case <-time.After(time.Second * 2): 217 // Shutdown first instance and replace it, in order to make an instance 218 // with an empty sending channel 219 os1.Shutdown() 220 time.Sleep(time.Second) 221 os1 = mocks.NewOrderer(5612, t) 222 instance2fail = os2 223 instance2failSecond = os1 224 reincarnatedNodePort = 5613 225 // Ensure we really are connected to the second instance, 226 // by making it send a block 227 go os2.SendBlock(uint64(100)) 228 assertBlockDissemination(100, gossipServiceAdapter.GossipBlockDisseminations, t) 229 } 230 231 atomic.StoreUint64(&li.Height, uint64(101)) 232 os1.SetNextExpectedSeek(uint64(101)) 233 os2.SetNextExpectedSeek(uint64(101)) 234 // Fail the orderer node the client is connected to 235 instance2fail.Shutdown() 236 time.Sleep(time.Second) 237 // Ensure the client asks blocks from the other ordering service node 238 go instance2failSecond.SendBlock(uint64(101)) 239 assertBlockDissemination(101, gossipServiceAdapter.GossipBlockDisseminations, t) 240 atomic.StoreUint64(&li.Height, uint64(102)) 241 // Now shut down the 2nd node 242 instance2failSecond.Shutdown() 243 time.Sleep(time.Second * 1) 244 // Bring up the first one 245 os := mocks.NewOrderer(reincarnatedNodePort, t) 246 os.SetNextExpectedSeek(102) 247 go os.SendBlock(uint64(102)) 248 assertBlockDissemination(102, gossipServiceAdapter.GossipBlockDisseminations, t) 249 os.Shutdown() 250 service.Stop() 251 } 252 253 func TestDeliverServiceServiceUnavailable(t *testing.T) { 254 orgMaxRetryDelay := blocksprovider.MaxRetryDelay 255 blocksprovider.MaxRetryDelay = time.Millisecond * 200 256 defer func() { blocksprovider.MaxRetryDelay = orgMaxRetryDelay }() 257 defer ensureNoGoroutineLeak(t)() 258 // Scenario: bring up 2 ordering service instances, 259 // Make the instance the client connects to fail after a delivery of a block and send SERVICE_UNAVAILABLE 260 // whenever subsequent seeks are sent to it. 261 // The client is expected to connect to the other instance, and to ask for a block sequence that is the next block 262 // after the last block it got from the first ordering service node. 263 264 os1 := mocks.NewOrderer(5615, t) 265 os2 := mocks.NewOrderer(5616, t) 266 267 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 268 269 service, err := NewDeliverService(&Config{ 270 Endpoints: []string{"localhost:5615", "localhost:5616"}, 271 Gossip: gossipServiceAdapter, 272 CryptoSvc: &mockMCS{}, 273 ABCFactory: DefaultABCFactory, 274 ConnFactory: DefaultConnectionFactory, 275 }) 276 assert.NoError(t, err) 277 li := &mocks.MockLedgerInfo{Height: 100} 278 os1.SetNextExpectedSeek(li.Height) 279 os2.SetNextExpectedSeek(li.Height) 280 281 err = service.StartDeliverForChannel("TEST_CHAINID", li) 282 assert.NoError(t, err, "can't start delivery") 283 284 waitForConnectionToSomeOSN := func() (*mocks.Orderer, *mocks.Orderer) { 285 for { 286 if os1.ConnCount() > 0 { 287 return os1, os2 288 } 289 if os2.ConnCount() > 0 { 290 return os2, os1 291 } 292 time.Sleep(time.Millisecond * 100) 293 } 294 } 295 296 activeInstance, backupInstance := waitForConnectionToSomeOSN() 297 assert.NotNil(t, activeInstance) 298 assert.NotNil(t, backupInstance) 299 // Check that delivery client get connected to active 300 assert.Equal(t, activeInstance.ConnCount(), 1) 301 // and not connected to backup instances 302 assert.Equal(t, backupInstance.ConnCount(), 0) 303 304 // Send first block 305 go activeInstance.SendBlock(li.Height) 306 307 assertBlockDissemination(li.Height, gossipServiceAdapter.GossipBlockDisseminations, t) 308 li.Height++ 309 310 // Backup instance should expect a seek of 101 since we got 100 311 backupInstance.SetNextExpectedSeek(li.Height) 312 // Have backup instance prepare to send a block 313 backupInstance.SendBlock(li.Height) 314 315 // Fail instance delivery client connected to 316 activeInstance.Fail() 317 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 318 defer cancel() 319 320 wg := sync.WaitGroup{} 321 wg.Add(1) 322 323 go func(ctx context.Context) { 324 defer wg.Done() 325 for { 326 select { 327 case <-time.After(time.Millisecond * 100): 328 if backupInstance.ConnCount() > 0 { 329 return 330 } 331 case <-ctx.Done(): 332 return 333 } 334 } 335 }(ctx) 336 337 wg.Wait() 338 assert.NoError(t, ctx.Err(), "Delivery client has not failed over to alive ordering service") 339 // Check that delivery client was indeed connected 340 assert.Equal(t, backupInstance.ConnCount(), 1) 341 // Ensure the client asks blocks from the other ordering service node 342 assertBlockDissemination(li.Height, gossipServiceAdapter.GossipBlockDisseminations, t) 343 344 // Cleanup 345 os1.Shutdown() 346 os2.Shutdown() 347 service.Stop() 348 } 349 350 func TestDeliverServiceShutdown(t *testing.T) { 351 defer ensureNoGoroutineLeak(t)() 352 // Scenario: Launch an ordering service node and let the client pull some blocks. 353 // Then, shut down the client, and check that it is no longer fetching blocks. 354 os := mocks.NewOrderer(5614, t) 355 356 time.Sleep(time.Second) 357 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 358 359 service, err := NewDeliverService(&Config{ 360 Endpoints: []string{"localhost:5614"}, 361 Gossip: gossipServiceAdapter, 362 CryptoSvc: &mockMCS{}, 363 ABCFactory: DefaultABCFactory, 364 ConnFactory: DefaultConnectionFactory, 365 }) 366 assert.NoError(t, err) 367 368 li := &mocks.MockLedgerInfo{Height: uint64(100)} 369 os.SetNextExpectedSeek(uint64(100)) 370 err = service.StartDeliverForChannel("TEST_CHAINID", li) 371 assert.NoError(t, err, "can't start delivery") 372 373 // Check that delivery service requests blocks in order 374 go os.SendBlock(uint64(100)) 375 assertBlockDissemination(100, gossipServiceAdapter.GossipBlockDisseminations, t) 376 go os.SendBlock(uint64(101)) 377 assertBlockDissemination(101, gossipServiceAdapter.GossipBlockDisseminations, t) 378 atomic.StoreUint64(&li.Height, uint64(102)) 379 os.SetNextExpectedSeek(uint64(102)) 380 // Now stop the delivery service and make sure we don't disseminate a block 381 service.Stop() 382 go os.SendBlock(uint64(102)) 383 select { 384 case <-gossipServiceAdapter.GossipBlockDisseminations: 385 assert.Fail(t, "Disseminated a block after shutting down the delivery service") 386 case <-time.After(time.Second * 2): 387 } 388 os.Shutdown() 389 time.Sleep(time.Second) 390 } 391 392 func TestDeliverServiceBadConfig(t *testing.T) { 393 // Empty endpoints 394 service, err := NewDeliverService(&Config{ 395 Endpoints: []string{}, 396 Gossip: &mocks.MockGossipServiceAdapter{}, 397 CryptoSvc: &mockMCS{}, 398 ABCFactory: DefaultABCFactory, 399 ConnFactory: DefaultConnectionFactory, 400 }) 401 assert.Error(t, err) 402 assert.Nil(t, service) 403 404 // Nil gossip adapter 405 service, err = NewDeliverService(&Config{ 406 Endpoints: []string{"a"}, 407 Gossip: nil, 408 CryptoSvc: &mockMCS{}, 409 ABCFactory: DefaultABCFactory, 410 ConnFactory: DefaultConnectionFactory, 411 }) 412 assert.Error(t, err) 413 assert.Nil(t, service) 414 415 // Nil crypto service 416 service, err = NewDeliverService(&Config{ 417 Endpoints: []string{"a"}, 418 Gossip: &mocks.MockGossipServiceAdapter{}, 419 CryptoSvc: nil, 420 ABCFactory: DefaultABCFactory, 421 ConnFactory: DefaultConnectionFactory, 422 }) 423 assert.Error(t, err) 424 assert.Nil(t, service) 425 426 // Nil ABCFactory 427 service, err = NewDeliverService(&Config{ 428 Endpoints: []string{"a"}, 429 Gossip: &mocks.MockGossipServiceAdapter{}, 430 CryptoSvc: &mockMCS{}, 431 ABCFactory: nil, 432 ConnFactory: DefaultConnectionFactory, 433 }) 434 assert.Error(t, err) 435 assert.Nil(t, service) 436 437 // Nil connFactory 438 service, err = NewDeliverService(&Config{ 439 Endpoints: []string{"a"}, 440 Gossip: &mocks.MockGossipServiceAdapter{}, 441 CryptoSvc: &mockMCS{}, 442 ABCFactory: DefaultABCFactory, 443 }) 444 assert.Error(t, err) 445 assert.Nil(t, service) 446 } 447 448 func TestRetryPolicyOverflow(t *testing.T) { 449 connFactory := func(channelID string) func(endpoint string) (*grpc.ClientConn, error) { 450 return func(_ string) (*grpc.ClientConn, error) { 451 return nil, errors.New("") 452 } 453 } 454 client := (&deliverServiceImpl{conf: &Config{ConnFactory: connFactory}}).newClient("TEST", &mocks.MockLedgerInfo{Height: uint64(100)}) 455 assert.NotNil(t, client.shouldRetry) 456 for i := 0; i < 100; i++ { 457 retryTime, _ := client.shouldRetry(i, time.Second) 458 assert.True(t, retryTime <= time.Hour && retryTime > 0) 459 } 460 } 461 462 func assertBlockDissemination(expectedSeq uint64, ch chan uint64, t *testing.T) { 463 select { 464 case seq := <-ch: 465 assert.Equal(t, expectedSeq, seq) 466 case <-time.After(time.Second * 5): 467 assert.FailNow(t, fmt.Sprintf("Didn't gossip a new block with seq num %d within a timely manner", expectedSeq)) 468 t.Fatal() 469 } 470 } 471 472 func ensureNoGoroutineLeak(t *testing.T) func() { 473 goroutineCountAtStart := runtime.NumGoroutine() 474 return func() { 475 start := time.Now() 476 timeLimit := start.Add(goRoutineTestWaitTimeout) 477 for time.Now().Before(timeLimit) { 478 time.Sleep(time.Millisecond * 500) 479 if goroutineCountAtStart >= runtime.NumGoroutine() { 480 return 481 } 482 } 483 assert.Fail(t, "Some goroutine(s) didn't finish: %s", getStackTrace()) 484 } 485 } 486 487 func getStackTrace() string { 488 buf := make([]byte, 1<<16) 489 runtime.Stack(buf, true) 490 return string(buf) 491 }