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  }