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  }