Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 1 | #region Copyright notice and license |
| 2 | |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | // Copyright 2015 gRPC authors. |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 4 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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 |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 8 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 10 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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. |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 16 | |
| 17 | #endregion |
| 18 | |
| 19 | using System; |
Jan Tattermusch | 7ebbc47 | 2015-12-08 22:39:02 -0800 | [diff] [blame] | 20 | using System.Collections.Generic; |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 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 | |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 39 | readonly string host; |
Jan Tattermusch | 7ebbc47 | 2015-12-08 22:39:02 -0800 | [diff] [blame] | 40 | readonly IEnumerable<ChannelOption> channelOptions; |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 41 | |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 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 | |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 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 | |
Jan Tattermusch | 7ebbc47 | 2015-12-08 22:39:02 -0800 | [diff] [blame] | 55 | public MockServiceHelper(string host = null, Marshaller<string> marshaller = null, IEnumerable<ChannelOption> channelOptions = null) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 56 | { |
| 57 | this.host = host ?? "localhost"; |
Jan Tattermusch | 7ebbc47 | 2015-12-08 22:39:02 -0800 | [diff] [blame] | 58 | this.channelOptions = channelOptions; |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 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); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 88 | |
Mehrdad Afshari | e954dff | 2018-02-11 20:11:28 -0800 | [diff] [blame] | 89 | ServiceDefinition = ServerServiceDefinition.CreateBuilder() |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 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)) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 94 | .Build(); |
| 95 | |
| 96 | var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own."); |
| 97 | |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 98 | unaryHandler = new UnaryServerMethod<string, string>((request, context) => |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 99 | { |
| 100 | context.Status = defaultStatus; |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 101 | return Task.FromResult(""); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 102 | }); |
| 103 | |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 104 | clientStreamingHandler = new ClientStreamingServerMethod<string, string>((requestStream, context) => |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 105 | { |
| 106 | context.Status = defaultStatus; |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 107 | return Task.FromResult(""); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 108 | }); |
| 109 | |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 110 | serverStreamingHandler = new ServerStreamingServerMethod<string, string>((request, responseStream, context) => |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 111 | { |
| 112 | context.Status = defaultStatus; |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 113 | return TaskUtils.CompletedTask; |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 114 | }); |
| 115 | |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 116 | duplexStreamingHandler = new DuplexStreamingServerMethod<string, string>((requestStream, responseStream, context) => |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 117 | { |
| 118 | context.Status = defaultStatus; |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 119 | return TaskUtils.CompletedTask; |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 120 | }); |
| 121 | } |
| 122 | |
| 123 | /// <summary> |
| 124 | /// Returns the default server for this service and creates one if not yet created. |
| 125 | /// </summary> |
| 126 | public Server GetServer() |
| 127 | { |
| 128 | if (server == null) |
| 129 | { |
Jan Tattermusch | 09d2f55 | 2017-04-20 11:39:37 +0200 | [diff] [blame] | 130 | // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 |
| 131 | server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 132 | { |
Mehrdad Afshari | e954dff | 2018-02-11 20:11:28 -0800 | [diff] [blame] | 133 | Services = { ServiceDefinition }, |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 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> |
| 143 | public Channel GetChannel() |
| 144 | { |
| 145 | if (channel == null) |
| 146 | { |
Jan Tattermusch | 7ebbc47 | 2015-12-08 22:39:02 -0800 | [diff] [blame] | 147 | channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, channelOptions); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 148 | } |
| 149 | return channel; |
| 150 | } |
| 151 | |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 152 | public CallInvocationDetails<string, string> CreateUnaryCall(CallOptions options = default(CallOptions)) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 153 | { |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 154 | return new CallInvocationDetails<string, string>(channel, unaryMethod, options); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 155 | } |
| 156 | |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 157 | public CallInvocationDetails<string, string> CreateClientStreamingCall(CallOptions options = default(CallOptions)) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 158 | { |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 159 | return new CallInvocationDetails<string, string>(channel, clientStreamingMethod, options); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 160 | } |
| 161 | |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 162 | public CallInvocationDetails<string, string> CreateServerStreamingCall(CallOptions options = default(CallOptions)) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 163 | { |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 164 | return new CallInvocationDetails<string, string>(channel, serverStreamingMethod, options); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 165 | } |
| 166 | |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 167 | public CallInvocationDetails<string, string> CreateDuplexStreamingCall(CallOptions options = default(CallOptions)) |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 168 | { |
Jan Tattermusch | 67c4587 | 2015-08-27 18:12:39 -0700 | [diff] [blame] | 169 | return new CallInvocationDetails<string, string>(channel, duplexStreamingMethod, options); |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | public string Host |
| 173 | { |
| 174 | get |
| 175 | { |
| 176 | return this.host; |
| 177 | } |
| 178 | } |
| 179 | |
Mehrdad Afshari | e954dff | 2018-02-11 20:11:28 -0800 | [diff] [blame] | 180 | public ServerServiceDefinition ServiceDefinition { get; set; } |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 181 | |
| 182 | public UnaryServerMethod<string, string> UnaryHandler |
| 183 | { |
| 184 | get |
| 185 | { |
| 186 | return this.unaryHandler; |
| 187 | } |
Jan Tattermusch | c75c57c | 2015-08-07 22:07:40 -0700 | [diff] [blame] | 188 | |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 189 | set |
| 190 | { |
| 191 | unaryHandler = value; |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | public ClientStreamingServerMethod<string, string> ClientStreamingHandler |
| 196 | { |
| 197 | get |
| 198 | { |
| 199 | return this.clientStreamingHandler; |
| 200 | } |
Jan Tattermusch | c75c57c | 2015-08-07 22:07:40 -0700 | [diff] [blame] | 201 | |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 202 | set |
| 203 | { |
| 204 | clientStreamingHandler = value; |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | public ServerStreamingServerMethod<string, string> ServerStreamingHandler |
| 209 | { |
| 210 | get |
| 211 | { |
| 212 | return this.serverStreamingHandler; |
| 213 | } |
Jan Tattermusch | c75c57c | 2015-08-07 22:07:40 -0700 | [diff] [blame] | 214 | |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 215 | set |
| 216 | { |
| 217 | serverStreamingHandler = value; |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | public DuplexStreamingServerMethod<string, string> DuplexStreamingHandler |
| 222 | { |
| 223 | get |
| 224 | { |
| 225 | return this.duplexStreamingHandler; |
| 226 | } |
Jan Tattermusch | c75c57c | 2015-08-07 22:07:40 -0700 | [diff] [blame] | 227 | |
Jan Tattermusch | 5b0b392 | 2015-08-07 19:07:14 -0700 | [diff] [blame] | 228 | set |
| 229 | { |
| 230 | duplexStreamingHandler = value; |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | } |