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  }