...

Source file src/google.golang.org/grpc/server_test.go

Documentation: google.golang.org/grpc

     1  /*
     2   *
     3   * Copyright 2016 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package grpc
    20  
    21  import (
    22  	"context"
    23  	"net"
    24  	"reflect"
    25  	"strconv"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/google/go-cmp/cmp"
    31  	"google.golang.org/grpc/internal/transport"
    32  	"google.golang.org/grpc/status"
    33  )
    34  
    35  type emptyServiceServer any
    36  
    37  type testServer struct{}
    38  
    39  func errorDesc(err error) string {
    40  	if s, ok := status.FromError(err); ok {
    41  		return s.Message()
    42  	}
    43  	return err.Error()
    44  }
    45  
    46  func (s) TestStopBeforeServe(t *testing.T) {
    47  	lis, err := net.Listen("tcp", "localhost:0")
    48  	if err != nil {
    49  		t.Fatalf("failed to create listener: %v", err)
    50  	}
    51  
    52  	server := NewServer()
    53  	server.Stop()
    54  	err = server.Serve(lis)
    55  	if err != ErrServerStopped {
    56  		t.Fatalf("server.Serve() error = %v, want %v", err, ErrServerStopped)
    57  	}
    58  
    59  	// server.Serve is responsible for closing the listener, even if the
    60  	// server was already stopped.
    61  	err = lis.Close()
    62  	if got, want := errorDesc(err), "use of closed"; !strings.Contains(got, want) {
    63  		t.Errorf("Close() error = %q, want %q", got, want)
    64  	}
    65  }
    66  
    67  func (s) TestGracefulStop(t *testing.T) {
    68  
    69  	lis, err := net.Listen("tcp", "localhost:0")
    70  	if err != nil {
    71  		t.Fatalf("failed to create listener: %v", err)
    72  	}
    73  
    74  	server := NewServer()
    75  	go func() {
    76  		// make sure Serve() is called
    77  		time.Sleep(time.Millisecond * 500)
    78  		server.GracefulStop()
    79  	}()
    80  
    81  	err = server.Serve(lis)
    82  	if err != nil {
    83  		t.Fatalf("Serve() returned non-nil error on GracefulStop: %v", err)
    84  	}
    85  }
    86  
    87  func (s) TestGetServiceInfo(t *testing.T) {
    88  	testSd := ServiceDesc{
    89  		ServiceName: "grpc.testing.EmptyService",
    90  		HandlerType: (*emptyServiceServer)(nil),
    91  		Methods: []MethodDesc{
    92  			{
    93  				MethodName: "EmptyCall",
    94  				Handler:    nil,
    95  			},
    96  		},
    97  		Streams: []StreamDesc{
    98  			{
    99  				StreamName:    "EmptyStream",
   100  				Handler:       nil,
   101  				ServerStreams: false,
   102  				ClientStreams: true,
   103  			},
   104  		},
   105  		Metadata: []int{0, 2, 1, 3},
   106  	}
   107  
   108  	server := NewServer()
   109  	server.RegisterService(&testSd, &testServer{})
   110  
   111  	info := server.GetServiceInfo()
   112  	want := map[string]ServiceInfo{
   113  		"grpc.testing.EmptyService": {
   114  			Methods: []MethodInfo{
   115  				{
   116  					Name:           "EmptyCall",
   117  					IsClientStream: false,
   118  					IsServerStream: false,
   119  				},
   120  				{
   121  					Name:           "EmptyStream",
   122  					IsClientStream: true,
   123  					IsServerStream: false,
   124  				}},
   125  			Metadata: []int{0, 2, 1, 3},
   126  		},
   127  	}
   128  
   129  	if !reflect.DeepEqual(info, want) {
   130  		t.Errorf("GetServiceInfo() = %+v, want %+v", info, want)
   131  	}
   132  }
   133  
   134  func (s) TestRetryChainedInterceptor(t *testing.T) {
   135  	var records []int
   136  	i1 := func(ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler) (resp any, err error) {
   137  		records = append(records, 1)
   138  		// call handler twice to simulate a retry here.
   139  		handler(ctx, req)
   140  		return handler(ctx, req)
   141  	}
   142  	i2 := func(ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler) (resp any, err error) {
   143  		records = append(records, 2)
   144  		return handler(ctx, req)
   145  	}
   146  	i3 := func(ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler) (resp any, err error) {
   147  		records = append(records, 3)
   148  		return handler(ctx, req)
   149  	}
   150  
   151  	ii := chainUnaryInterceptors([]UnaryServerInterceptor{i1, i2, i3})
   152  
   153  	handler := func(ctx context.Context, req any) (any, error) {
   154  		return nil, nil
   155  	}
   156  	ii(context.Background(), nil, nil, handler)
   157  	if !cmp.Equal(records, []int{1, 2, 3, 2, 3}) {
   158  		t.Fatalf("retry failed on chained interceptors: %v", records)
   159  	}
   160  }
   161  
   162  func (s) TestStreamContext(t *testing.T) {
   163  	expectedStream := &transport.Stream{}
   164  	ctx := NewContextWithServerTransportStream(context.Background(), expectedStream)
   165  	s := ServerTransportStreamFromContext(ctx)
   166  	stream, ok := s.(*transport.Stream)
   167  	if !ok || expectedStream != stream {
   168  		t.Fatalf("GetStreamFromContext(%v) = %v, %t, want: %v, true", ctx, stream, ok, expectedStream)
   169  	}
   170  }
   171  
   172  func BenchmarkChainUnaryInterceptor(b *testing.B) {
   173  	for _, n := range []int{1, 3, 5, 10} {
   174  		n := n
   175  		b.Run(strconv.Itoa(n), func(b *testing.B) {
   176  			interceptors := make([]UnaryServerInterceptor, 0, n)
   177  			for i := 0; i < n; i++ {
   178  				interceptors = append(interceptors, func(
   179  					ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler,
   180  				) (any, error) {
   181  					return handler(ctx, req)
   182  				})
   183  			}
   184  
   185  			s := NewServer(ChainUnaryInterceptor(interceptors...))
   186  			b.ReportAllocs()
   187  			b.ResetTimer()
   188  			for i := 0; i < b.N; i++ {
   189  				if _, err := s.opts.unaryInt(context.Background(), nil, nil,
   190  					func(ctx context.Context, req any) (any, error) {
   191  						return nil, nil
   192  					},
   193  				); err != nil {
   194  					b.Fatal(err)
   195  				}
   196  			}
   197  		})
   198  	}
   199  }
   200  
   201  func BenchmarkChainStreamInterceptor(b *testing.B) {
   202  	for _, n := range []int{1, 3, 5, 10} {
   203  		n := n
   204  		b.Run(strconv.Itoa(n), func(b *testing.B) {
   205  			interceptors := make([]StreamServerInterceptor, 0, n)
   206  			for i := 0; i < n; i++ {
   207  				interceptors = append(interceptors, func(
   208  					srv any, ss ServerStream, info *StreamServerInfo, handler StreamHandler,
   209  				) error {
   210  					return handler(srv, ss)
   211  				})
   212  			}
   213  
   214  			s := NewServer(ChainStreamInterceptor(interceptors...))
   215  			b.ReportAllocs()
   216  			b.ResetTimer()
   217  			for i := 0; i < b.N; i++ {
   218  				if err := s.opts.streamInt(nil, nil, nil, func(srv any, stream ServerStream) error {
   219  					return nil
   220  				}); err != nil {
   221  					b.Fatal(err)
   222  				}
   223  			}
   224  		})
   225  	}
   226  }
   227  

View as plain text