github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/core/comm/producer_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 comm
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  	"google.golang.org/grpc"
    25  )
    26  
    27  type connMock struct {
    28  	*grpc.ClientConn
    29  	endpoint string
    30  }
    31  
    32  func TestEmptyEndpoints(t *testing.T) {
    33  	noopFactory := func(endpoint string) (*grpc.ClientConn, error) {
    34  		return nil, nil
    35  	}
    36  	assert.Nil(t, NewConnectionProducer(noopFactory, []string{}))
    37  }
    38  
    39  func TestConnFailures(t *testing.T) {
    40  	conn2Endpoint := make(map[string]string)
    41  	shouldConnFail := map[string]bool{
    42  		"a": true,
    43  		"b": false,
    44  		"c": false,
    45  	}
    46  	connFactory := func(endpoint string) (*grpc.ClientConn, error) {
    47  		conn := &grpc.ClientConn{}
    48  		conn2Endpoint[fmt.Sprintf("%p", conn)] = endpoint
    49  		if !shouldConnFail[endpoint] {
    50  			return conn, nil
    51  		}
    52  		return nil, fmt.Errorf("Failed connecting to %s", endpoint)
    53  	}
    54  	// Create a producer with some endpoints, and have the first one fail and all others not fail
    55  	producer := NewConnectionProducer(connFactory, []string{"a", "b", "c"})
    56  	conn, _, err := producer.NewConnection()
    57  	assert.NoError(t, err)
    58  	// We should not return 'a' because connecting to 'a' fails
    59  	assert.NotEqual(t, "a", conn2Endpoint[fmt.Sprintf("%p", conn)])
    60  	// Now, revive 'a'
    61  	shouldConnFail["a"] = false
    62  	// Try obtaining a connection 1000 times in order to ensure selection is shuffled
    63  	selected := make(map[string]struct{})
    64  	for i := 0; i < 1000; i++ {
    65  		conn, _, err := producer.NewConnection()
    66  		assert.NoError(t, err)
    67  		selected[conn2Endpoint[fmt.Sprintf("%p", conn)]] = struct{}{}
    68  	}
    69  	// The probability of a, b or c not to be selected is really small
    70  	_, isAselected := selected["a"]
    71  	_, isBselected := selected["b"]
    72  	_, isCselected := selected["c"]
    73  	assert.True(t, isBselected)
    74  	assert.True(t, isCselected)
    75  	assert.True(t, isAselected)
    76  
    77  	// Now, make every host fail
    78  	shouldConnFail["a"] = true
    79  	shouldConnFail["b"] = true
    80  	shouldConnFail["c"] = true
    81  	conn, _, err = producer.NewConnection()
    82  	assert.Nil(t, conn)
    83  	assert.Error(t, err)
    84  }
    85  
    86  func TestUpdateEndpoints(t *testing.T) {
    87  	conn2Endpoint := make(map[string]string)
    88  	connFactory := func(endpoint string) (*grpc.ClientConn, error) {
    89  		conn := &grpc.ClientConn{}
    90  		conn2Endpoint[fmt.Sprintf("%p", conn)] = endpoint
    91  		return conn, nil
    92  	}
    93  	// Create a producer with a single endpoint
    94  	producer := NewConnectionProducer(connFactory, []string{"a"})
    95  	conn, a, err := producer.NewConnection()
    96  	assert.NoError(t, err)
    97  	assert.Equal(t, "a", conn2Endpoint[fmt.Sprintf("%p", conn)])
    98  	assert.Equal(t, "a", a)
    99  	// Now update the endpoint and check that when we create a new connection,
   100  	// we don't connect to the previous endpoint
   101  	producer.UpdateEndpoints([]string{"b"})
   102  	conn, b, err := producer.NewConnection()
   103  	assert.NoError(t, err)
   104  	assert.NotEqual(t, "a", conn2Endpoint[fmt.Sprintf("%p", conn)])
   105  	assert.Equal(t, "b", conn2Endpoint[fmt.Sprintf("%p", conn)])
   106  	assert.Equal(t, "b", b)
   107  	// Next, ensure an empty update is ignored
   108  	producer.UpdateEndpoints([]string{})
   109  	conn, _, err = producer.NewConnection()
   110  	assert.Equal(t, "b", conn2Endpoint[fmt.Sprintf("%p", conn)])
   111  }