go.etcd.io/etcd@v3.3.27+incompatible/proxy/grpcproxy/cluster_test.go (about) 1 // Copyright 2017 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 grpcproxy 16 17 import ( 18 "context" 19 "net" 20 "testing" 21 "time" 22 23 "github.com/coreos/etcd/clientv3" 24 pb "github.com/coreos/etcd/etcdserver/etcdserverpb" 25 "github.com/coreos/etcd/integration" 26 "github.com/coreos/etcd/pkg/testutil" 27 28 "google.golang.org/grpc" 29 ) 30 31 func TestClusterProxyMemberList(t *testing.T) { 32 defer testutil.AfterTest(t) 33 34 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) 35 defer clus.Terminate(t) 36 37 cts := newClusterProxyServer([]string{clus.Members[0].GRPCAddr()}, t) 38 defer cts.close(t) 39 40 cfg := clientv3.Config{ 41 Endpoints: []string{cts.caddr}, 42 DialTimeout: 5 * time.Second, 43 } 44 client, err := clientv3.New(cfg) 45 if err != nil { 46 t.Fatalf("err %v, want nil", err) 47 } 48 defer client.Close() 49 50 // wait some time for register-loop to write keys 51 time.Sleep(time.Second) 52 53 var mresp *clientv3.MemberListResponse 54 mresp, err = client.Cluster.MemberList(context.Background()) 55 if err != nil { 56 t.Fatalf("err %v, want nil", err) 57 } 58 59 if len(mresp.Members) != 1 { 60 t.Fatalf("len(mresp.Members) expected 1, got %d (%+v)", len(mresp.Members), mresp.Members) 61 } 62 if len(mresp.Members[0].ClientURLs) != 1 { 63 t.Fatalf("len(mresp.Members[0].ClientURLs) expected 1, got %d (%+v)", len(mresp.Members[0].ClientURLs), mresp.Members[0].ClientURLs[0]) 64 } 65 if mresp.Members[0].ClientURLs[0] != cts.caddr { 66 t.Fatalf("mresp.Members[0].ClientURLs[0] expected %q, got %q", cts.caddr, mresp.Members[0].ClientURLs[0]) 67 } 68 } 69 70 type clusterproxyTestServer struct { 71 cp pb.ClusterServer 72 c *clientv3.Client 73 server *grpc.Server 74 l net.Listener 75 donec <-chan struct{} 76 caddr string 77 } 78 79 func (cts *clusterproxyTestServer) close(t *testing.T) { 80 cts.server.Stop() 81 cts.l.Close() 82 cts.c.Close() 83 select { 84 case <-cts.donec: 85 return 86 case <-time.After(5 * time.Second): 87 t.Fatalf("register-loop took too long to return") 88 } 89 } 90 91 func newClusterProxyServer(endpoints []string, t *testing.T) *clusterproxyTestServer { 92 cfg := clientv3.Config{ 93 Endpoints: endpoints, 94 DialTimeout: 5 * time.Second, 95 } 96 client, err := clientv3.New(cfg) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 cts := &clusterproxyTestServer{ 102 c: client, 103 } 104 cts.l, err = net.Listen("tcp", "127.0.0.1:0") 105 if err != nil { 106 t.Fatal(err) 107 } 108 var opts []grpc.ServerOption 109 cts.server = grpc.NewServer(opts...) 110 servec := make(chan struct{}) 111 go func() { 112 <-servec 113 cts.server.Serve(cts.l) 114 }() 115 116 Register(client, "test-prefix", cts.l.Addr().String(), 7) 117 cts.cp, cts.donec = NewClusterProxy(client, cts.l.Addr().String(), "test-prefix") 118 cts.caddr = cts.l.Addr().String() 119 pb.RegisterClusterServer(cts.server, cts.cp) 120 close(servec) 121 122 // wait some time for free port 0 to be resolved 123 time.Sleep(500 * time.Millisecond) 124 125 return cts 126 }