github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/integration/clientv3/naming/resolver_test.go (about) 1 // Copyright 2016 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package naming_test 16 17 import ( 18 "bytes" 19 "context" 20 "testing" 21 "time" 22 23 "github.com/lfch/etcd-io/client/v3/naming/endpoints" 24 "github.com/lfch/etcd-io/client/v3/naming/resolver" 25 "github.com/lfch/etcd-io/pkg/v3/grpc_testing" 26 integration2 "github.com/lfch/etcd-io/tests/v3/framework/integration" 27 "google.golang.org/grpc" 28 testpb "google.golang.org/grpc/test/grpc_testing" 29 ) 30 31 // This test mimics scenario described in grpc_naming.md doc. 32 33 func TestEtcdGrpcResolver(t *testing.T) { 34 integration2.BeforeTest(t) 35 36 s1PayloadBody := []byte{'1'} 37 s1 := grpc_testing.NewDummyStubServer(s1PayloadBody) 38 if err := s1.Start(nil); err != nil { 39 t.Fatal("failed to start dummy grpc server (s1)", err) 40 } 41 defer s1.Stop() 42 43 s2PayloadBody := []byte{'2'} 44 s2 := grpc_testing.NewDummyStubServer(s2PayloadBody) 45 if err := s2.Start(nil); err != nil { 46 t.Fatal("failed to start dummy grpc server (s2)", err) 47 } 48 defer s2.Stop() 49 50 clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) 51 defer clus.Terminate(t) 52 53 em, err := endpoints.NewManager(clus.Client(0), "foo") 54 if err != nil { 55 t.Fatal("failed to create EndpointManager", err) 56 } 57 58 e1 := endpoints.Endpoint{Addr: s1.Addr()} 59 e2 := endpoints.Endpoint{Addr: s2.Addr()} 60 61 err = em.AddEndpoint(context.TODO(), "foo/e1", e1) 62 if err != nil { 63 t.Fatal("failed to add foo", err) 64 } 65 66 b, err := resolver.NewBuilder(clus.Client(1)) 67 if err != nil { 68 t.Fatal("failed to new resolver builder", err) 69 } 70 71 conn, err := grpc.Dial("etcd:///foo", grpc.WithInsecure(), grpc.WithResolvers(b)) 72 if err != nil { 73 t.Fatal("failed to connect to foo", err) 74 } 75 defer conn.Close() 76 77 c := testpb.NewTestServiceClient(conn) 78 resp, err := c.UnaryCall(context.TODO(), &testpb.SimpleRequest{}, grpc.WaitForReady(true)) 79 if err != nil { 80 t.Fatal("failed to invoke rpc to foo (e1)", err) 81 } 82 if resp.GetPayload() == nil || !bytes.Equal(resp.GetPayload().GetBody(), s1PayloadBody) { 83 t.Fatalf("unexpected response from foo (e1): %s", resp.GetPayload().GetBody()) 84 } 85 86 em.DeleteEndpoint(context.TODO(), "foo/e1") 87 em.AddEndpoint(context.TODO(), "foo/e2", e2) 88 89 // We use a loop with deadline of 30s to avoid test getting flake 90 // as it's asynchronous for gRPC Client to update underlying connections. 91 maxRetries := 300 92 retryPeriod := 100 * time.Millisecond 93 retries := 0 94 for { 95 time.Sleep(retryPeriod) 96 retries++ 97 98 resp, err = c.UnaryCall(context.TODO(), &testpb.SimpleRequest{}) 99 if err != nil { 100 if retries < maxRetries { 101 continue 102 } 103 t.Fatal("failed to invoke rpc to foo (e2)", err) 104 } 105 if resp.GetPayload() == nil || !bytes.Equal(resp.GetPayload().GetBody(), s2PayloadBody) { 106 if retries < maxRetries { 107 continue 108 } 109 t.Fatalf("unexpected response from foo (e2): %s", resp.GetPayload().GetBody()) 110 } 111 break 112 } 113 }