1
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
60
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
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
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