Jan Tattermusch | a7fff86 | 2015-02-13 11:08:08 -0800 | [diff] [blame] | 1 | #region Copyright notice and license |
| 2 | |
Jan Tattermusch | af77b3d | 2015-02-13 11:22:21 -0800 | [diff] [blame] | 3 | // Copyright 2015, Google Inc. |
Jan Tattermusch | a7fff86 | 2015-02-13 11:08:08 -0800 | [diff] [blame] | 4 | // All rights reserved. |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 5 | // |
Jan Tattermusch | a7fff86 | 2015-02-13 11:08:08 -0800 | [diff] [blame] | 6 | // Redistribution and use in source and binary forms, with or without |
| 7 | // modification, are permitted provided that the following conditions are |
| 8 | // met: |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 9 | // |
Jan Tattermusch | a7fff86 | 2015-02-13 11:08:08 -0800 | [diff] [blame] | 10 | // * Redistributions of source code must retain the above copyright |
| 11 | // notice, this list of conditions and the following disclaimer. |
| 12 | // * Redistributions in binary form must reproduce the above |
| 13 | // copyright notice, this list of conditions and the following disclaimer |
| 14 | // in the documentation and/or other materials provided with the |
| 15 | // distribution. |
| 16 | // * Neither the name of Google Inc. nor the names of its |
| 17 | // contributors may be used to endorse or promote products derived from |
| 18 | // this software without specific prior written permission. |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 19 | // |
Jan Tattermusch | a7fff86 | 2015-02-13 11:08:08 -0800 | [diff] [blame] | 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | |
| 32 | #endregion |
| 33 | |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 34 | using System; |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 35 | using System.Collections.Generic; |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 36 | using System.Text.RegularExpressions; |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 37 | using Google.ProtocolBuffers; |
Jan Tattermusch | 3086862 | 2015-02-19 09:22:33 -0800 | [diff] [blame] | 38 | using Grpc.Core; |
| 39 | using Grpc.Core.Utils; |
| 40 | using NUnit.Framework; |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 41 | using grpc.testing; |
| 42 | |
Jan Tattermusch | 3086862 | 2015-02-19 09:22:33 -0800 | [diff] [blame] | 43 | namespace Grpc.Interop |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 44 | { |
Jan Tattermusch | 392d1e0 | 2015-02-09 11:13:51 -0800 | [diff] [blame] | 45 | class Client |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 46 | { |
| 47 | private class ClientOptions |
| 48 | { |
| 49 | public bool help; |
| 50 | public string serverHost; |
| 51 | public string serverHostOverride; |
| 52 | public int? serverPort; |
| 53 | public string testCase; |
| 54 | public bool useTls; |
| 55 | public bool useTestCa; |
| 56 | } |
| 57 | |
| 58 | ClientOptions options; |
| 59 | |
Jan Tattermusch | 392d1e0 | 2015-02-09 11:13:51 -0800 | [diff] [blame] | 60 | private Client(ClientOptions options) |
| 61 | { |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 62 | this.options = options; |
| 63 | } |
| 64 | |
| 65 | public static void Main(string[] args) |
| 66 | { |
| 67 | Console.WriteLine("gRPC C# interop testing client"); |
| 68 | ClientOptions options = ParseArguments(args); |
| 69 | |
| 70 | if (options.serverHost == null || !options.serverPort.HasValue || options.testCase == null) |
| 71 | { |
| 72 | Console.WriteLine("Missing required argument."); |
| 73 | Console.WriteLine(); |
| 74 | options.help = true; |
| 75 | } |
| 76 | |
| 77 | if (options.help) |
| 78 | { |
| 79 | Console.WriteLine("Usage:"); |
| 80 | Console.WriteLine(" --server_host=HOSTNAME"); |
| 81 | Console.WriteLine(" --server_host_override=HOSTNAME"); |
| 82 | Console.WriteLine(" --server_port=PORT"); |
| 83 | Console.WriteLine(" --test_case=TESTCASE"); |
| 84 | Console.WriteLine(" --use_tls=BOOLEAN"); |
| 85 | Console.WriteLine(" --use_test_ca=BOOLEAN"); |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 86 | Console.WriteLine(); |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 87 | Environment.Exit(1); |
| 88 | } |
| 89 | |
Jan Tattermusch | 392d1e0 | 2015-02-09 11:13:51 -0800 | [diff] [blame] | 90 | var interopClient = new Client(options); |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 91 | interopClient.Run(); |
| 92 | } |
| 93 | |
| 94 | private void Run() |
| 95 | { |
Jan Tattermusch | 23821ce | 2015-02-13 10:46:02 -0800 | [diff] [blame] | 96 | GrpcEnvironment.Initialize(); |
| 97 | |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 98 | string addr = string.Format("{0}:{1}", options.serverHost, options.serverPort); |
| 99 | using (Channel channel = new Channel(addr)) |
| 100 | { |
| 101 | TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel); |
| 102 | |
| 103 | RunTestCase(options.testCase, client); |
| 104 | } |
| 105 | |
| 106 | GrpcEnvironment.Shutdown(); |
| 107 | } |
| 108 | |
| 109 | private void RunTestCase(string testCase, TestServiceGrpc.ITestServiceClient client) |
| 110 | { |
| 111 | switch (testCase) |
| 112 | { |
| 113 | case "empty_unary": |
| 114 | RunEmptyUnary(client); |
| 115 | break; |
| 116 | case "large_unary": |
| 117 | RunLargeUnary(client); |
| 118 | break; |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 119 | case "client_streaming": |
| 120 | RunClientStreaming(client); |
| 121 | break; |
| 122 | case "server_streaming": |
| 123 | RunServerStreaming(client); |
| 124 | break; |
| 125 | case "ping_pong": |
| 126 | RunPingPong(client); |
| 127 | break; |
| 128 | case "empty_stream": |
| 129 | RunEmptyStream(client); |
| 130 | break; |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 131 | default: |
| 132 | throw new ArgumentException("Unknown test case " + testCase); |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | private void RunEmptyUnary(TestServiceGrpc.ITestServiceClient client) |
| 137 | { |
| 138 | Console.WriteLine("running empty_unary"); |
| 139 | var response = client.EmptyCall(Empty.DefaultInstance); |
| 140 | Assert.IsNotNull(response); |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 141 | Console.WriteLine("Passed!"); |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | private void RunLargeUnary(TestServiceGrpc.ITestServiceClient client) |
| 145 | { |
| 146 | Console.WriteLine("running large_unary"); |
| 147 | var request = SimpleRequest.CreateBuilder() |
| 148 | .SetResponseType(PayloadType.COMPRESSABLE) |
| 149 | .SetResponseSize(314159) |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 150 | .SetPayload(CreateZerosPayload(271828)) |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 151 | .Build(); |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 152 | |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 153 | var response = client.UnaryCall(request); |
| 154 | |
| 155 | Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); |
| 156 | Assert.AreEqual(314159, response.Payload.Body.Length); |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 157 | Console.WriteLine("Passed!"); |
| 158 | } |
| 159 | |
| 160 | private void RunClientStreaming(TestServiceGrpc.ITestServiceClient client) |
| 161 | { |
| 162 | Console.WriteLine("running client_streaming"); |
| 163 | |
| 164 | var bodySizes = new List<int>{27182, 8, 1828, 45904}; |
| 165 | |
| 166 | var context = client.StreamingInputCall(); |
| 167 | foreach (var size in bodySizes) |
| 168 | { |
| 169 | context.Inputs.OnNext( |
| 170 | StreamingInputCallRequest.CreateBuilder().SetPayload(CreateZerosPayload(size)).Build()); |
| 171 | } |
| 172 | context.Inputs.OnCompleted(); |
| 173 | |
| 174 | var response = context.Task.Result; |
| 175 | Assert.AreEqual(74922, response.AggregatedPayloadSize); |
| 176 | Console.WriteLine("Passed!"); |
| 177 | } |
| 178 | |
| 179 | private void RunServerStreaming(TestServiceGrpc.ITestServiceClient client) |
| 180 | { |
| 181 | Console.WriteLine("running server_streaming"); |
| 182 | |
| 183 | var bodySizes = new List<int>{31415, 9, 2653, 58979}; |
| 184 | |
| 185 | var request = StreamingOutputCallRequest.CreateBuilder() |
| 186 | .SetResponseType(PayloadType.COMPRESSABLE) |
| 187 | .AddRangeResponseParameters(bodySizes.ConvertAll( |
| 188 | (size) => ResponseParameters.CreateBuilder().SetSize(size).Build())) |
| 189 | .Build(); |
| 190 | |
| 191 | var recorder = new RecordingObserver<StreamingOutputCallResponse>(); |
| 192 | client.StreamingOutputCall(request, recorder); |
| 193 | |
| 194 | var responseList = recorder.ToList().Result; |
| 195 | |
| 196 | foreach (var res in responseList) |
| 197 | { |
| 198 | Assert.AreEqual(PayloadType.COMPRESSABLE, res.Payload.Type); |
| 199 | } |
| 200 | CollectionAssert.AreEqual(bodySizes, responseList.ConvertAll((item) => item.Payload.Body.Length)); |
| 201 | Console.WriteLine("Passed!"); |
| 202 | } |
| 203 | |
| 204 | private void RunPingPong(TestServiceGrpc.ITestServiceClient client) |
| 205 | { |
| 206 | Console.WriteLine("running ping_pong"); |
| 207 | |
| 208 | var recorder = new RecordingQueue<StreamingOutputCallResponse>(); |
| 209 | var inputs = client.FullDuplexCall(recorder); |
| 210 | |
| 211 | StreamingOutputCallResponse response; |
| 212 | |
| 213 | inputs.OnNext(StreamingOutputCallRequest.CreateBuilder() |
| 214 | .SetResponseType(PayloadType.COMPRESSABLE) |
| 215 | .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(31415)) |
| 216 | .SetPayload(CreateZerosPayload(27182)).Build()); |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 217 | |
| 218 | response = recorder.Queue.Take(); |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 219 | Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); |
| 220 | Assert.AreEqual(31415, response.Payload.Body.Length); |
| 221 | |
| 222 | inputs.OnNext(StreamingOutputCallRequest.CreateBuilder() |
| 223 | .SetResponseType(PayloadType.COMPRESSABLE) |
| 224 | .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(9)) |
| 225 | .SetPayload(CreateZerosPayload(8)).Build()); |
| 226 | |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 227 | response = recorder.Queue.Take(); |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 228 | Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); |
| 229 | Assert.AreEqual(9, response.Payload.Body.Length); |
| 230 | |
| 231 | inputs.OnNext(StreamingOutputCallRequest.CreateBuilder() |
| 232 | .SetResponseType(PayloadType.COMPRESSABLE) |
| 233 | .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(2635)) |
| 234 | .SetPayload(CreateZerosPayload(1828)).Build()); |
| 235 | |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 236 | response = recorder.Queue.Take(); |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 237 | Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); |
| 238 | Assert.AreEqual(2653, response.Payload.Body.Length); |
| 239 | |
| 240 | |
| 241 | inputs.OnNext(StreamingOutputCallRequest.CreateBuilder() |
| 242 | .SetResponseType(PayloadType.COMPRESSABLE) |
| 243 | .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(58979)) |
| 244 | .SetPayload(CreateZerosPayload(45904)).Build()); |
| 245 | |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 246 | response = recorder.Queue.Take(); |
Jan Tattermusch | d233d3a | 2015-02-06 14:15:00 -0800 | [diff] [blame] | 247 | Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); |
| 248 | Assert.AreEqual(58979, response.Payload.Body.Length); |
| 249 | |
| 250 | recorder.Finished.Wait(); |
| 251 | Assert.AreEqual(0, recorder.Queue.Count); |
| 252 | |
| 253 | Console.WriteLine("Passed!"); |
| 254 | } |
| 255 | |
| 256 | private void RunEmptyStream(TestServiceGrpc.ITestServiceClient client) |
| 257 | { |
| 258 | Console.WriteLine("running empty_stream"); |
| 259 | |
| 260 | var recorder = new RecordingObserver<StreamingOutputCallResponse>(); |
| 261 | var inputs = client.FullDuplexCall(recorder); |
| 262 | inputs.OnCompleted(); |
| 263 | |
| 264 | var responseList = recorder.ToList().Result; |
| 265 | Assert.AreEqual(0, responseList.Count); |
| 266 | |
| 267 | Console.WriteLine("Passed!"); |
| 268 | } |
| 269 | |
| 270 | |
| 271 | private Payload CreateZerosPayload(int size) { |
| 272 | return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build(); |
Jan Tattermusch | eb3e76e | 2015-02-06 11:43:13 -0800 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | private static ClientOptions ParseArguments(string[] args) |
| 276 | { |
| 277 | var options = new ClientOptions(); |
| 278 | foreach(string arg in args) |
| 279 | { |
| 280 | ParseArgument(arg, options); |
| 281 | if (options.help) |
| 282 | { |
| 283 | break; |
| 284 | } |
| 285 | } |
| 286 | return options; |
| 287 | } |
| 288 | |
| 289 | private static void ParseArgument(string arg, ClientOptions options) |
| 290 | { |
| 291 | Match match; |
| 292 | match = Regex.Match(arg, "--server_host=(.*)"); |
| 293 | if (match.Success) |
| 294 | { |
| 295 | options.serverHost = match.Groups[1].Value.Trim(); |
| 296 | return; |
| 297 | } |
| 298 | |
| 299 | match = Regex.Match(arg, "--server_host_override=(.*)"); |
| 300 | if (match.Success) |
| 301 | { |
| 302 | options.serverHostOverride = match.Groups[1].Value.Trim(); |
| 303 | return; |
| 304 | } |
| 305 | |
| 306 | match = Regex.Match(arg, "--server_port=(.*)"); |
| 307 | if (match.Success) |
| 308 | { |
| 309 | options.serverPort = int.Parse(match.Groups[1].Value.Trim()); |
| 310 | return; |
| 311 | } |
| 312 | |
| 313 | match = Regex.Match(arg, "--test_case=(.*)"); |
| 314 | if (match.Success) |
| 315 | { |
| 316 | options.testCase = match.Groups[1].Value.Trim(); |
| 317 | return; |
| 318 | } |
| 319 | |
| 320 | match = Regex.Match(arg, "--use_tls=(.*)"); |
| 321 | if (match.Success) |
| 322 | { |
| 323 | options.useTls = bool.Parse(match.Groups[1].Value.Trim()); |
| 324 | return; |
| 325 | } |
| 326 | |
| 327 | match = Regex.Match(arg, "--use_test_ca=(.*)"); |
| 328 | if (match.Success) |
| 329 | { |
| 330 | options.useTestCa = bool.Parse(match.Groups[1].Value.Trim()); |
| 331 | return; |
| 332 | } |
| 333 | |
| 334 | Console.WriteLine(string.Format("Unrecognized argument \"{0}\"", arg)); |
| 335 | options.help = true; |
| 336 | } |
| 337 | } |
| 338 | } |