• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2015 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 #endregion
18 
19 using System;
20 using System.Collections.Generic;
21 using System.Diagnostics;
22 using System.Linq;
23 using System.Threading;
24 using System.Threading.Tasks;
25 using Grpc.Core;
26 using Grpc.Core.Internal;
27 using Grpc.Core.Utils;
28 using NUnit.Framework;
29 
30 namespace Grpc.Core.Tests
31 {
32     /// <summary>
33     /// Allows setting up a mock service in the client-server tests easily.
34     /// </summary>
35     public class MockServiceHelper
36     {
37         public const string ServiceName = "tests.Test";
38 
39         readonly string host;
40         readonly IEnumerable<ChannelOption> channelOptions;
41 
42         readonly Method<string, string> unaryMethod;
43         readonly Method<string, string> clientStreamingMethod;
44         readonly Method<string, string> serverStreamingMethod;
45         readonly Method<string, string> duplexStreamingMethod;
46 
47         UnaryServerMethod<string, string> unaryHandler;
48         ClientStreamingServerMethod<string, string> clientStreamingHandler;
49         ServerStreamingServerMethod<string, string> serverStreamingHandler;
50         DuplexStreamingServerMethod<string, string> duplexStreamingHandler;
51 
52         Server server;
53         Channel channel;
54 
MockServiceHelper(string host = null, Marshaller<string> marshaller = null, IEnumerable<ChannelOption> channelOptions = null)55         public MockServiceHelper(string host = null, Marshaller<string> marshaller = null, IEnumerable<ChannelOption> channelOptions = null)
56         {
57             this.host = host ?? "localhost";
58             this.channelOptions = channelOptions;
59             marshaller = marshaller ?? Marshallers.StringMarshaller;
60 
61             unaryMethod = new Method<string, string>(
62                 MethodType.Unary,
63                 ServiceName,
64                 "Unary",
65                 marshaller,
66                 marshaller);
67 
68             clientStreamingMethod = new Method<string, string>(
69                 MethodType.ClientStreaming,
70                 ServiceName,
71                 "ClientStreaming",
72                 marshaller,
73                 marshaller);
74 
75             serverStreamingMethod = new Method<string, string>(
76                 MethodType.ServerStreaming,
77                 ServiceName,
78                 "ServerStreaming",
79                 marshaller,
80                 marshaller);
81 
82             duplexStreamingMethod = new Method<string, string>(
83                 MethodType.DuplexStreaming,
84                 ServiceName,
85                 "DuplexStreaming",
86                 marshaller,
87                 marshaller);
88 
89             ServiceDefinition = ServerServiceDefinition.CreateBuilder()
90                 .AddMethod(unaryMethod, (request, context) => unaryHandler(request, context))
91                 .AddMethod(clientStreamingMethod, (requestStream, context) => clientStreamingHandler(requestStream, context))
92                 .AddMethod(serverStreamingMethod, (request, responseStream, context) => serverStreamingHandler(request, responseStream, context))
93                 .AddMethod(duplexStreamingMethod, (requestStream, responseStream, context) => duplexStreamingHandler(requestStream, responseStream, context))
94                 .Build();
95 
96             var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own.");
97 
98             unaryHandler = new UnaryServerMethod<string, string>((request, context) =>
99             {
100                 context.Status = defaultStatus;
101                 return Task.FromResult("");
102             });
103 
104             clientStreamingHandler = new ClientStreamingServerMethod<string, string>((requestStream, context) =>
105             {
106                 context.Status = defaultStatus;
107                 return Task.FromResult("");
108             });
109 
110             serverStreamingHandler = new ServerStreamingServerMethod<string, string>((request, responseStream, context) =>
111             {
112                 context.Status = defaultStatus;
113                 return TaskUtils.CompletedTask;
114             });
115 
116             duplexStreamingHandler = new DuplexStreamingServerMethod<string, string>((requestStream, responseStream, context) =>
117             {
118                 context.Status = defaultStatus;
119                 return TaskUtils.CompletedTask;
120             });
121         }
122 
123         /// <summary>
124         /// Returns the default server for this service and creates one if not yet created.
125         /// </summary>
GetServer()126         public Server GetServer()
127         {
128             if (server == null)
129             {
130                 // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
131                 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
132                 {
133                     Services = { ServiceDefinition },
134                     Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
135                 };
136             }
137             return server;
138         }
139 
140         /// <summary>
141         /// Returns the default channel for this service and creates one if not yet created.
142         /// </summary>
GetChannel()143         public Channel GetChannel()
144         {
145             if (channel == null)
146             {
147                 channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, channelOptions);
148             }
149             return channel;
150         }
151 
CreateUnaryCall(CallOptions options = default(CallOptions))152         public CallInvocationDetails<string, string> CreateUnaryCall(CallOptions options = default(CallOptions))
153         {
154             return new CallInvocationDetails<string, string>(channel, unaryMethod, options);
155         }
156 
CreateClientStreamingCall(CallOptions options = default(CallOptions))157         public CallInvocationDetails<string, string> CreateClientStreamingCall(CallOptions options = default(CallOptions))
158         {
159             return new CallInvocationDetails<string, string>(channel, clientStreamingMethod, options);
160         }
161 
CreateServerStreamingCall(CallOptions options = default(CallOptions))162         public CallInvocationDetails<string, string> CreateServerStreamingCall(CallOptions options = default(CallOptions))
163         {
164             return new CallInvocationDetails<string, string>(channel, serverStreamingMethod, options);
165         }
166 
CreateDuplexStreamingCall(CallOptions options = default(CallOptions))167         public CallInvocationDetails<string, string> CreateDuplexStreamingCall(CallOptions options = default(CallOptions))
168         {
169             return new CallInvocationDetails<string, string>(channel, duplexStreamingMethod, options);
170         }
171 
172         public string Host
173         {
174             get
175             {
176                 return this.host;
177             }
178         }
179 
180         public ServerServiceDefinition ServiceDefinition { get; set; }
181 
182         public UnaryServerMethod<string, string> UnaryHandler
183         {
184             get
185             {
186                 return this.unaryHandler;
187             }
188 
189             set
190             {
191                 unaryHandler = value;
192             }
193         }
194 
195         public ClientStreamingServerMethod<string, string> ClientStreamingHandler
196         {
197             get
198             {
199                 return this.clientStreamingHandler;
200             }
201 
202             set
203             {
204                 clientStreamingHandler = value;
205             }
206         }
207 
208         public ServerStreamingServerMethod<string, string> ServerStreamingHandler
209         {
210             get
211             {
212                 return this.serverStreamingHandler;
213             }
214 
215             set
216             {
217                 serverStreamingHandler = value;
218             }
219         }
220 
221         public DuplexStreamingServerMethod<string, string> DuplexStreamingHandler
222         {
223             get
224             {
225                 return this.duplexStreamingHandler;
226             }
227 
228             set
229             {
230                 duplexStreamingHandler = value;
231             }
232         }
233     }
234 }
235