github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 "runtime" 21 "sync" 22 "sync/atomic" 23 "testing" 24 "time" 25 26 "github.com/hyperledger/fabric/core/deliverservice/blocksprovider" 27 "github.com/hyperledger/fabric/core/deliverservice/mocks" 28 "github.com/hyperledger/fabric/gossip/api" 29 "github.com/hyperledger/fabric/gossip/common" 30 "github.com/hyperledger/fabric/msp/mgmt/testtools" 31 "github.com/hyperledger/fabric/protos/orderer" 32 "github.com/stretchr/testify/assert" 33 "google.golang.org/grpc" 34 ) 35 36 func init() { 37 msptesttools.LoadMSPSetupForTesting() 38 } 39 40 const ( 41 goRoutineTestWaitTimeout = time.Second * 10 42 ) 43 44 var ( 45 lock = sync.Mutex{} 46 ) 47 48 type mockBlocksDelivererFactory struct { 49 mockCreate func() (blocksprovider.BlocksDeliverer, error) 50 } 51 52 func (mock *mockBlocksDelivererFactory) Create() (blocksprovider.BlocksDeliverer, error) { 53 return mock.mockCreate() 54 } 55 56 type mockMCS struct { 57 } 58 59 func (*mockMCS) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType { 60 return common.PKIidType("pkiID") 61 } 62 63 func (*mockMCS) VerifyBlock(chainID common.ChainID, signedBlock []byte) error { 64 return nil 65 } 66 67 func (*mockMCS) Sign(msg []byte) ([]byte, error) { 68 return msg, nil 69 } 70 71 func (*mockMCS) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error { 72 return nil 73 } 74 75 func (*mockMCS) VerifyByChannel(chainID common.ChainID, peerIdentity api.PeerIdentityType, signature, message []byte) error { 76 return nil 77 } 78 79 func (*mockMCS) ValidateIdentity(peerIdentity api.PeerIdentityType) error { 80 return nil 81 } 82 83 func TestNewDeliverService(t *testing.T) { 84 defer ensureNoGoroutineLeak(t)() 85 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64, 1)} 86 factory := &struct{ mockBlocksDelivererFactory }{} 87 88 blocksDeliverer := &mocks.MockBlocksDeliverer{} 89 blocksDeliverer.MockRecv = mocks.MockRecv 90 91 factory.mockCreate = func() (blocksprovider.BlocksDeliverer, error) { 92 return blocksDeliverer, nil 93 } 94 abcf := func(*grpc.ClientConn) orderer.AtomicBroadcastClient { 95 return &mocks.MockAtomicBroadcastClient{blocksDeliverer} 96 } 97 98 connFactory := func(endpoint string) (*grpc.ClientConn, error) { 99 lock.Lock() 100 defer lock.Unlock() 101 return newConnection(), nil 102 } 103 service, err := NewDeliverService(&Config{ 104 Endpoints: []string{"a"}, 105 Gossip: gossipServiceAdapter, 106 CryptoSvc: &mockMCS{}, 107 ABCFactory: abcf, 108 ConnFactory: connFactory, 109 }) 110 assert.NoError(t, err) 111 assert.NoError(t, service.StartDeliverForChannel("TEST_CHAINID", &mocks.MockLedgerInfo{0})) 112 113 // Lets start deliver twice 114 assert.Error(t, service.StartDeliverForChannel("TEST_CHAINID", &mocks.MockLedgerInfo{0}), "can't start delivery") 115 // Lets stop deliver that not started 116 assert.Error(t, service.StopDeliverForChannel("TEST_CHAINID2"), "can't stop delivery") 117 118 // Let it try to simulate a few recv -> gossip rounds 119 time.Sleep(time.Second) 120 assert.NoError(t, service.StopDeliverForChannel("TEST_CHAINID")) 121 time.Sleep(time.Duration(10) * time.Millisecond) 122 // Make sure to stop all blocks providers 123 service.Stop() 124 time.Sleep(time.Duration(500) * time.Millisecond) 125 assert.Equal(t, 0, connNumber) 126 assertBlockDissemination(0, gossipServiceAdapter.GossipBlockDisseminations, t) 127 assert.Equal(t, atomic.LoadInt32(&blocksDeliverer.RecvCnt), atomic.LoadInt32(&gossipServiceAdapter.AddPayloadsCnt)) 128 assert.Error(t, service.StartDeliverForChannel("TEST_CHAINID", &mocks.MockLedgerInfo{0}), "Delivery service is stopping") 129 assert.Error(t, service.StopDeliverForChannel("TEST_CHAINID"), "Delivery service is stopping") 130 } 131 132 func TestDeliverServiceRestart(t *testing.T) { 133 defer ensureNoGoroutineLeak(t)() 134 // Scenario: bring up ordering service instance, then shut it down, and then resurrect it. 135 // Client is expected to reconnect to it, and to ask for a block sequence that is the next block 136 // after the last block it got from the previous incarnation of the ordering service. 137 138 os := mocks.NewOrderer(5611, t) 139 140 time.Sleep(time.Second) 141 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 142 143 service, err := NewDeliverService(&Config{ 144 Endpoints: []string{"localhost:5611"}, 145 Gossip: gossipServiceAdapter, 146 CryptoSvc: &mockMCS{}, 147 ABCFactory: DefaultABCFactory, 148 ConnFactory: DefaultConnectionFactory, 149 }) 150 assert.NoError(t, err) 151 152 li := &mocks.MockLedgerInfo{Height: uint64(100)} 153 os.SetNextExpectedSeek(uint64(100)) 154 155 err = service.StartDeliverForChannel("TEST_CHAINID", li) 156 assert.NoError(t, err, "can't start delivery") 157 // Check that delivery client requests blocks in order 158 go os.SendBlock(uint64(100)) 159 assertBlockDissemination(100, gossipServiceAdapter.GossipBlockDisseminations, t) 160 go os.SendBlock(uint64(101)) 161 assertBlockDissemination(101, gossipServiceAdapter.GossipBlockDisseminations, t) 162 go os.SendBlock(uint64(102)) 163 assertBlockDissemination(102, gossipServiceAdapter.GossipBlockDisseminations, t) 164 os.Shutdown() 165 time.Sleep(time.Second * 3) 166 os = mocks.NewOrderer(5611, t) 167 li.Height = 103 168 os.SetNextExpectedSeek(uint64(103)) 169 go os.SendBlock(uint64(103)) 170 assertBlockDissemination(103, gossipServiceAdapter.GossipBlockDisseminations, t) 171 service.Stop() 172 os.Shutdown() 173 } 174 175 func TestDeliverServiceFailover(t *testing.T) { 176 defer ensureNoGoroutineLeak(t)() 177 // Scenario: bring up 2 ordering service instances, 178 // and shut down the instance that the client has connected to. 179 // Client is expected to connect to the other instance, and to ask for a block sequence that is the next block 180 // after the last block it got from the ordering service that was shut down. 181 // Then, shut down the other node, and bring back the first (that was shut down first). 182 183 os1 := mocks.NewOrderer(5612, t) 184 os2 := mocks.NewOrderer(5613, t) 185 186 time.Sleep(time.Second) 187 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 188 189 service, err := NewDeliverService(&Config{ 190 Endpoints: []string{"localhost:5612", "localhost:5613"}, 191 Gossip: gossipServiceAdapter, 192 CryptoSvc: &mockMCS{}, 193 ABCFactory: DefaultABCFactory, 194 ConnFactory: DefaultConnectionFactory, 195 }) 196 assert.NoError(t, err) 197 li := &mocks.MockLedgerInfo{Height: uint64(100)} 198 os1.SetNextExpectedSeek(uint64(100)) 199 os2.SetNextExpectedSeek(uint64(100)) 200 201 err = service.StartDeliverForChannel("TEST_CHAINID", li) 202 assert.NoError(t, err, "can't start delivery") 203 // We need to discover to which instance the client connected to 204 go os1.SendBlock(uint64(100)) 205 instance2fail := os1 206 reincarnatedNodePort := 5612 207 instance2failSecond := os2 208 select { 209 case seq := <-gossipServiceAdapter.GossipBlockDisseminations: 210 assert.Equal(t, uint64(100), seq) 211 case <-time.After(time.Second * 2): 212 // Shutdown first instance and replace it, in order to make an instance 213 // with an empty sending channel 214 os1.Shutdown() 215 time.Sleep(time.Second) 216 os1 = mocks.NewOrderer(5612, t) 217 instance2fail = os2 218 instance2failSecond = os1 219 reincarnatedNodePort = 5613 220 // Ensure we really are connected to the second instance, 221 // by making it send a block 222 go os2.SendBlock(uint64(100)) 223 assertBlockDissemination(100, gossipServiceAdapter.GossipBlockDisseminations, t) 224 } 225 226 atomic.StoreUint64(&li.Height, uint64(101)) 227 os1.SetNextExpectedSeek(uint64(101)) 228 os2.SetNextExpectedSeek(uint64(101)) 229 // Fail the orderer node the client is connected to 230 instance2fail.Shutdown() 231 time.Sleep(time.Second) 232 // Ensure the client asks blocks from the other ordering service node 233 go instance2failSecond.SendBlock(uint64(101)) 234 assertBlockDissemination(101, gossipServiceAdapter.GossipBlockDisseminations, t) 235 atomic.StoreUint64(&li.Height, uint64(102)) 236 // Now shut down the 2nd node 237 instance2failSecond.Shutdown() 238 time.Sleep(time.Second * 1) 239 // Bring up the first one 240 os := mocks.NewOrderer(reincarnatedNodePort, t) 241 os.SetNextExpectedSeek(102) 242 go os.SendBlock(uint64(102)) 243 assertBlockDissemination(102, gossipServiceAdapter.GossipBlockDisseminations, t) 244 os.Shutdown() 245 service.Stop() 246 } 247 248 func TestDeliverServiceShutdown(t *testing.T) { 249 defer ensureNoGoroutineLeak(t)() 250 // Scenario: Launch an ordering service node and let the client pull some blocks. 251 // Then, shut down the client, and check that it is no longer fetching blocks. 252 os := mocks.NewOrderer(5614, t) 253 254 time.Sleep(time.Second) 255 gossipServiceAdapter := &mocks.MockGossipServiceAdapter{GossipBlockDisseminations: make(chan uint64)} 256 257 service, err := NewDeliverService(&Config{ 258 Endpoints: []string{"localhost:5614"}, 259 Gossip: gossipServiceAdapter, 260 CryptoSvc: &mockMCS{}, 261 ABCFactory: DefaultABCFactory, 262 ConnFactory: DefaultConnectionFactory, 263 }) 264 assert.NoError(t, err) 265 266 li := &mocks.MockLedgerInfo{Height: uint64(100)} 267 os.SetNextExpectedSeek(uint64(100)) 268 err = service.StartDeliverForChannel("TEST_CHAINID", li) 269 assert.NoError(t, err, "can't start delivery") 270 271 // Check that delivery service requests blocks in order 272 go os.SendBlock(uint64(100)) 273 assertBlockDissemination(100, gossipServiceAdapter.GossipBlockDisseminations, t) 274 go os.SendBlock(uint64(101)) 275 assertBlockDissemination(101, gossipServiceAdapter.GossipBlockDisseminations, t) 276 atomic.StoreUint64(&li.Height, uint64(102)) 277 os.SetNextExpectedSeek(uint64(102)) 278 // Now stop the delivery service and make sure we don't disseminate a block 279 service.Stop() 280 go os.SendBlock(uint64(102)) 281 select { 282 case <-gossipServiceAdapter.GossipBlockDisseminations: 283 assert.Fail(t, "Disseminated a block after shutting down the delivery service") 284 case <-time.After(time.Second * 2): 285 } 286 os.Shutdown() 287 time.Sleep(time.Second) 288 } 289 290 func TestDeliverServiceBadConfig(t *testing.T) { 291 // Empty endpoints 292 service, err := NewDeliverService(&Config{ 293 Endpoints: []string{}, 294 Gossip: &mocks.MockGossipServiceAdapter{}, 295 CryptoSvc: &mockMCS{}, 296 ABCFactory: DefaultABCFactory, 297 ConnFactory: DefaultConnectionFactory, 298 }) 299 assert.Error(t, err) 300 assert.Nil(t, service) 301 302 // Nil gossip adapter 303 service, err = NewDeliverService(&Config{ 304 Endpoints: []string{"a"}, 305 Gossip: nil, 306 CryptoSvc: &mockMCS{}, 307 ABCFactory: DefaultABCFactory, 308 ConnFactory: DefaultConnectionFactory, 309 }) 310 assert.Error(t, err) 311 assert.Nil(t, service) 312 313 // Nil crypto service 314 service, err = NewDeliverService(&Config{ 315 Endpoints: []string{"a"}, 316 Gossip: &mocks.MockGossipServiceAdapter{}, 317 CryptoSvc: nil, 318 ABCFactory: DefaultABCFactory, 319 ConnFactory: DefaultConnectionFactory, 320 }) 321 assert.Error(t, err) 322 assert.Nil(t, service) 323 324 // Nil ABCFactory 325 service, err = NewDeliverService(&Config{ 326 Endpoints: []string{"a"}, 327 Gossip: &mocks.MockGossipServiceAdapter{}, 328 CryptoSvc: &mockMCS{}, 329 ABCFactory: nil, 330 ConnFactory: DefaultConnectionFactory, 331 }) 332 assert.Error(t, err) 333 assert.Nil(t, service) 334 335 // Nil connFactory 336 service, err = NewDeliverService(&Config{ 337 Endpoints: []string{"a"}, 338 Gossip: &mocks.MockGossipServiceAdapter{}, 339 CryptoSvc: &mockMCS{}, 340 ABCFactory: DefaultABCFactory, 341 }) 342 assert.Error(t, err) 343 assert.Nil(t, service) 344 } 345 346 func assertBlockDissemination(expectedSeq uint64, ch chan uint64, t *testing.T) { 347 select { 348 case seq := <-ch: 349 assert.Equal(t, expectedSeq, seq) 350 case <-time.After(time.Second * 5): 351 assert.Fail(t, "Didn't gossip a new block within a timely manner") 352 } 353 } 354 355 func ensureNoGoroutineLeak(t *testing.T) func() { 356 //goroutineCountAtStart := runtime.NumGoroutine() 357 return func() { 358 // Temporarily disabled, see FAB-3257 for progress 359 /* start := time.Now() 360 timeLimit := start.Add(goRoutineTestWaitTimeout) 361 for time.Now().Before(timeLimit) { 362 time.Sleep(time.Millisecond * 500) 363 if goroutineCountAtStart == runtime.NumGoroutine() { 364 fmt.Println(getStackTrace()) 365 return 366 } 367 } 368 assert.Equal(t, goroutineCountAtStart, runtime.NumGoroutine(), "Some goroutine(s) didn't finish: %s", getStackTrace())*/ 369 } 370 } 371 372 func getStackTrace() string { 373 buf := make([]byte, 1<<16) 374 runtime.Stack(buf, true) 375 return string(buf) 376 }