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 }