vitess.io/vitess@v0.16.2/go/vt/vtadmin/grpcserver/server_test.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 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 grpcserver 18 19 import ( 20 "context" 21 "net" 22 "testing" 23 "time" 24 25 "google.golang.org/grpc/credentials/insecure" 26 27 "github.com/stretchr/testify/assert" 28 "golang.org/x/net/nettest" 29 "google.golang.org/grpc" 30 31 healthpb "google.golang.org/grpc/health/grpc_health_v1" 32 ) 33 34 func TestServer(t *testing.T) { 35 lis, err := nettest.NewLocalListener("tcp") 36 listenFunc = func(network, address string) (net.Listener, error) { 37 return lis, err 38 } 39 40 defer lis.Close() 41 42 s := New("testservice", Options{ 43 EnableTracing: true, 44 AllowReflection: true, 45 CMuxReadTimeout: time.Second, 46 }) 47 48 go func() { err := s.ListenAndServe(); assert.NoError(t, err) }() 49 50 readyCh := make(chan bool) 51 52 go func() { 53 for !s.isServing() { 54 } 55 readyCh <- true 56 }() 57 58 serveStart := time.Now() 59 select { 60 case <-readyCh: 61 case serveStop := <-time.After(time.Millisecond * 500): 62 t.Errorf("server did not start within %s", serveStop.Sub(serveStart)) 63 return 64 } 65 close(readyCh) 66 67 conn, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) 68 assert.NoError(t, err) 69 70 defer conn.Close() 71 72 healthclient := healthpb.NewHealthClient(conn) 73 resp, err := healthclient.Check(context.Background(), &healthpb.HealthCheckRequest{Service: "grpc.health.v1.Health"}) 74 assert.NoError(t, err) 75 assert.NotNil(t, resp) 76 } 77 78 func TestLameduck(t *testing.T) { 79 lis, err := nettest.NewLocalListener("tcp") 80 listenFunc = func(network, address string) (net.Listener, error) { 81 return lis, err 82 } 83 84 ldd := time.Millisecond * 50 85 86 s := New("testservice", Options{LameDuckDuration: ldd}) 87 88 go func() { err := s.ListenAndServe(); assert.NoError(t, err) }() 89 90 readyCh := make(chan bool) 91 92 go func() { 93 for !s.isServing() { 94 } 95 readyCh <- true 96 }() 97 98 serveStart := time.Now() 99 select { 100 case <-readyCh: 101 case serveStop := <-time.After(time.Millisecond * 500): 102 t.Errorf("server did not start within %s", serveStop.Sub(serveStart)) 103 return 104 } 105 106 stoppedCh := make(chan bool) 107 108 go func() { 109 for s.isServing() { 110 } 111 stoppedCh <- true 112 }() 113 114 shutdownStart := time.Now() 115 116 lis.Close() 117 118 select { 119 case <-stoppedCh: 120 case <-time.After(ldd): 121 } 122 123 shutdownDuration := time.Since(shutdownStart) 124 assert.LessOrEqual(t, int64(ldd), int64(shutdownDuration), 125 "should have taken at least %s to shutdown, took only %s", ldd, shutdownDuration) 126 } 127 128 func TestError(t *testing.T) { 129 listenFunc = func(network, address string) (net.Listener, error) { return nil, assert.AnError } 130 s := New("testservice", Options{}) 131 errCh := make(chan error) 132 133 // This has to happen in a goroutine. In normal operation, this function 134 // blocks until externally signalled, and we don't want to hold up the 135 // tests. 136 go func() { 137 errCh <- s.ListenAndServe() 138 }() 139 140 start := time.Now() 141 select { 142 case err := <-errCh: 143 assert.Error(t, err) 144 case ti := <-time.After(time.Millisecond * 10): 145 assert.Fail(t, "timed out waiting for error after %s", ti.Sub(start)) 146 } 147 }