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
19package grpc
20
21import (
22	"context"
23	"net"
24	"reflect"
25	"strconv"
26	"strings"
27	"testing"
28	"time"
29
30	"google.golang.org/grpc/internal/transport"
31)
32
33type emptyServiceServer interface{}
34
35type testServer struct{}
36
37func (s) TestStopBeforeServe(t *testing.T) {
38	lis, err := net.Listen("tcp", "localhost:0")
39	if err != nil {
40		t.Fatalf("failed to create listener: %v", err)
41	}
42
43	server := NewServer()
44	server.Stop()
45	err = server.Serve(lis)
46	if err != ErrServerStopped {
47		t.Fatalf("server.Serve() error = %v, want %v", err, ErrServerStopped)
48	}
49
50	// server.Serve is responsible for closing the listener, even if the
51	// server was already stopped.
52	err = lis.Close()
53	if got, want := errorDesc(err), "use of closed"; !strings.Contains(got, want) {
54		t.Errorf("Close() error = %q, want %q", got, want)
55	}
56}
57
58func (s) TestGracefulStop(t *testing.T) {
59
60	lis, err := net.Listen("tcp", "localhost:0")
61	if err != nil {
62		t.Fatalf("failed to create listener: %v", err)
63	}
64
65	server := NewServer()
66	go func() {
67		// make sure Serve() is called
68		time.Sleep(time.Millisecond * 500)
69		server.GracefulStop()
70	}()
71
72	err = server.Serve(lis)
73	if err != nil {
74		t.Fatalf("Serve() returned non-nil error on GracefulStop: %v", err)
75	}
76}
77
78func (s) TestGetServiceInfo(t *testing.T) {
79	testSd := ServiceDesc{
80		ServiceName: "grpc.testing.EmptyService",
81		HandlerType: (*emptyServiceServer)(nil),
82		Methods: []MethodDesc{
83			{
84				MethodName: "EmptyCall",
85				Handler:    nil,
86			},
87		},
88		Streams: []StreamDesc{
89			{
90				StreamName:    "EmptyStream",
91				Handler:       nil,
92				ServerStreams: false,
93				ClientStreams: true,
94			},
95		},
96		Metadata: []int{0, 2, 1, 3},
97	}
98
99	server := NewServer()
100	server.RegisterService(&testSd, &testServer{})
101
102	info := server.GetServiceInfo()
103	want := map[string]ServiceInfo{
104		"grpc.testing.EmptyService": {
105			Methods: []MethodInfo{
106				{
107					Name:           "EmptyCall",
108					IsClientStream: false,
109					IsServerStream: false,
110				},
111				{
112					Name:           "EmptyStream",
113					IsClientStream: true,
114					IsServerStream: false,
115				}},
116			Metadata: []int{0, 2, 1, 3},
117		},
118	}
119
120	if !reflect.DeepEqual(info, want) {
121		t.Errorf("GetServiceInfo() = %+v, want %+v", info, want)
122	}
123}
124
125func (s) TestStreamContext(t *testing.T) {
126	expectedStream := &transport.Stream{}
127	ctx := NewContextWithServerTransportStream(context.Background(), expectedStream)
128	s := ServerTransportStreamFromContext(ctx)
129	stream, ok := s.(*transport.Stream)
130	if !ok || expectedStream != stream {
131		t.Fatalf("GetStreamFromContext(%v) = %v, %t, want: %v, true", ctx, stream, ok, expectedStream)
132	}
133}
134
135func BenchmarkChainUnaryInterceptor(b *testing.B) {
136	for _, n := range []int{1, 3, 5, 10} {
137		n := n
138		b.Run(strconv.Itoa(n), func(b *testing.B) {
139			interceptors := make([]UnaryServerInterceptor, 0, n)
140			for i := 0; i < n; i++ {
141				interceptors = append(interceptors, func(
142					ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler,
143				) (interface{}, error) {
144					return handler(ctx, req)
145				})
146			}
147
148			s := NewServer(ChainUnaryInterceptor(interceptors...))
149			b.ReportAllocs()
150			b.ResetTimer()
151			for i := 0; i < b.N; i++ {
152				if _, err := s.opts.unaryInt(context.Background(), nil, nil,
153					func(ctx context.Context, req interface{}) (interface{}, error) {
154						return nil, nil
155					},
156				); err != nil {
157					b.Fatal(err)
158				}
159			}
160		})
161	}
162}
163
164func BenchmarkChainStreamInterceptor(b *testing.B) {
165	for _, n := range []int{1, 3, 5, 10} {
166		n := n
167		b.Run(strconv.Itoa(n), func(b *testing.B) {
168			interceptors := make([]StreamServerInterceptor, 0, n)
169			for i := 0; i < n; i++ {
170				interceptors = append(interceptors, func(
171					srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler,
172				) error {
173					return handler(srv, ss)
174				})
175			}
176
177			s := NewServer(ChainStreamInterceptor(interceptors...))
178			b.ReportAllocs()
179			b.ResetTimer()
180			for i := 0; i < b.N; i++ {
181				if err := s.opts.streamInt(nil, nil, nil, func(srv interface{}, stream ServerStream) error {
182					return nil
183				}); err != nil {
184					b.Fatal(err)
185				}
186			}
187		})
188	}
189}
190