blob: 32a52eee6bf3b5229a99e7e664d8f4303f4ce11a [file] [log] [blame]
Jan Tattermuscha7fff862015-02-13 11:08:08 -08001#region Copyright notice and license
2
Jan Tattermuschacb842c2016-03-25 16:54:14 -07003// Copyright 2015-2016, Google Inc.
Jan Tattermuscha7fff862015-02-13 11:08:08 -08004// All rights reserved.
Craig Tiller190d3602015-02-18 09:23:38 -08005//
Jan Tattermuscha7fff862015-02-13 11:08:08 -08006// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
Craig Tiller190d3602015-02-18 09:23:38 -08009//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080010// * 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 Tiller190d3602015-02-18 09:23:38 -080019//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080020// 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 Tattermuscheb3e76e2015-02-06 11:43:13 -080034using System;
Jan Tattermuschd233d3a2015-02-06 14:15:00 -080035using System.Collections.Generic;
Jan Tattermusch74f39e12015-09-23 20:14:56 -070036using System.IO;
Jan Tattermusch0ed73152015-12-09 18:21:11 -080037using System.Linq;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080038using System.Text.RegularExpressions;
Jan Tattermusche5c44602015-05-01 11:12:34 -070039using System.Threading;
Jan Tattermuscha5272b62015-04-30 11:56:46 -070040using System.Threading.Tasks;
Jan Tattermusch1ca56b92015-04-27 11:03:06 -070041
Jan Tattermuschb26972f2015-09-03 17:47:14 -070042using CommandLine;
Jan Tattermusch74f39e12015-09-23 20:14:56 -070043using CommandLine.Text;
Jan Tattermusch67c45872015-08-27 18:12:39 -070044using Google.Apis.Auth.OAuth2;
45using Google.Protobuf;
Jan Tattermuschdca6e882015-04-22 16:56:27 -070046using Grpc.Auth;
Jan Tattermusch30868622015-02-19 09:22:33 -080047using Grpc.Core;
Jan Tattermusch66f85782017-02-24 19:44:16 +010048using Grpc.Core.Logging;
Jan Tattermusch30868622015-02-19 09:22:33 -080049using Grpc.Core.Utils;
Jan Tattermusch8644aea2015-08-03 10:21:18 -070050using Grpc.Testing;
Jan Tattermusch64d7c242015-10-08 08:02:27 -070051using Newtonsoft.Json.Linq;
Jan Tattermusch30868622015-02-19 09:22:33 -080052using NUnit.Framework;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080053
Jan Tattermusch8b86b152015-02-19 21:01:05 -080054namespace Grpc.IntegrationTesting
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080055{
Jan Tattermusch503bbac2015-02-26 18:19:47 -080056 public class InteropClient
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080057 {
58 private class ClientOptions
59 {
Paul Marks3a5bba02017-02-07 16:28:09 -080060 [Option("server_host", Default = "localhost")]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070061 public string ServerHost { get; set; }
62
Jan Tattermusch678ec902016-08-08 12:54:16 +080063 [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070064 public string ServerHostOverride { get; set; }
65
66 [Option("server_port", Required = true)]
67 public int ServerPort { get; set; }
68
Jan Tattermusch678ec902016-08-08 12:54:16 +080069 [Option("test_case", Default = "large_unary")]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070070 public string TestCase { get; set; }
71
Jan Tattermusch7828e812015-10-07 17:27:48 -070072 // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
Jan Tattermusch678ec902016-08-08 12:54:16 +080073 [Option("use_tls", Default = false)]
Jan Tattermusch7828e812015-10-07 17:27:48 -070074 public bool? UseTls { get; set; }
Jan Tattermuschb26972f2015-09-03 17:47:14 -070075
Jan Tattermusch7828e812015-10-07 17:27:48 -070076 // Deliberately using nullable bool type to allow --use_test_ca=true syntax (as opposed to --use_test_ca)
Jan Tattermusch678ec902016-08-08 12:54:16 +080077 [Option("use_test_ca", Default = false)]
Jan Tattermusch7828e812015-10-07 17:27:48 -070078 public bool? UseTestCa { get; set; }
Jan Tattermuschb26972f2015-09-03 17:47:14 -070079
80 [Option("default_service_account", Required = false)]
81 public string DefaultServiceAccount { get; set; }
82
83 [Option("oauth_scope", Required = false)]
84 public string OAuthScope { get; set; }
85
86 [Option("service_account_key_file", Required = false)]
87 public string ServiceAccountKeyFile { get; set; }
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080088 }
89
90 ClientOptions options;
91
Jan Tattermusch503bbac2015-02-26 18:19:47 -080092 private InteropClient(ClientOptions options)
Jan Tattermusch392d1e02015-02-09 11:13:51 -080093 {
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080094 this.options = options;
95 }
96
Jan Tattermusch503bbac2015-02-26 18:19:47 -080097 public static void Run(string[] args)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080098 {
Jan Tattermusch66f85782017-02-24 19:44:16 +010099 GrpcEnvironment.SetLogger(new ConsoleLogger());
Jan Tattermusch90cbde82016-08-08 14:33:28 +0800100 var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
101 .WithNotParsed(errors => Environment.Exit(1))
102 .WithParsed(options =>
103 {
104 var interopClient = new InteropClient(options);
105 interopClient.Run().Wait();
106 });
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800107 }
108
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700109 private async Task Run()
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800110 {
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700111 var credentials = await CreateCredentialsAsync();
112
113 List<ChannelOption> channelOptions = null;
114 if (!string.IsNullOrEmpty(options.ServerHostOverride))
115 {
116 channelOptions = new List<ChannelOption>
117 {
118 new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride)
119 };
120 }
121 var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800122 await RunTestCaseAsync(channel, options);
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700123 await channel.ShutdownAsync();
124 }
125
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700126 private async Task<ChannelCredentials> CreateCredentialsAsync()
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700127 {
Jan Tattermuschbeffc772015-10-22 13:28:22 -0700128 var credentials = ChannelCredentials.Insecure;
129 if (options.UseTls.Value)
130 {
131 credentials = options.UseTestCa.Value ? TestCredentials.CreateSslCredentials() : new SslCredentials();
132 }
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700133
134 if (options.TestCase == "jwt_token_creds")
135 {
136 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
137 Assert.IsTrue(googleCredential.IsCreateScopedRequired);
Jan Tattermusch18729a02015-10-08 18:40:00 -0700138 credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700139 }
140
141 if (options.TestCase == "compute_engine_creds")
142 {
143 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
144 Assert.IsFalse(googleCredential.IsCreateScopedRequired);
Jan Tattermusch18729a02015-10-08 18:40:00 -0700145 credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700146 }
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700147 return credentials;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800148 }
149
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800150 private async Task RunTestCaseAsync(Channel channel, ClientOptions options)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800151 {
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800152 var client = new TestService.TestServiceClient(channel);
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700153 switch (options.TestCase)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800154 {
155 case "empty_unary":
156 RunEmptyUnary(client);
157 break;
158 case "large_unary":
159 RunLargeUnary(client);
160 break;
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800161 case "client_streaming":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700162 await RunClientStreamingAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800163 break;
164 case "server_streaming":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700165 await RunServerStreamingAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800166 break;
167 case "ping_pong":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700168 await RunPingPongAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800169 break;
170 case "empty_stream":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700171 await RunEmptyStreamAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800172 break;
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700173 case "compute_engine_creds":
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700174 RunComputeEngineCreds(client, options.DefaultServiceAccount, options.OAuthScope);
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700175 break;
176 case "jwt_token_creds":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700177 RunJwtTokenCreds(client);
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700178 break;
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700179 case "oauth2_auth_token":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700180 await RunOAuth2AuthTokenAsync(client, options.OAuthScope);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700181 break;
182 case "per_rpc_creds":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700183 await RunPerRpcCredsAsync(client, options.OAuthScope);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700184 break;
Jan Tattermusche5c44602015-05-01 11:12:34 -0700185 case "cancel_after_begin":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700186 await RunCancelAfterBeginAsync(client);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700187 break;
188 case "cancel_after_first_response":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700189 await RunCancelAfterFirstResponseAsync(client);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700190 break;
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700191 case "timeout_on_sleeping_server":
192 await RunTimeoutOnSleepingServerAsync(client);
193 break;
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800194 case "custom_metadata":
195 await RunCustomMetadataAsync(client);
196 break;
197 case "status_code_and_message":
198 await RunStatusCodeAndMessageAsync(client);
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800199 break;
Noah Eisen9a171c72016-10-21 16:26:40 -0700200 case "unimplemented_service":
201 RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel));
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800202 break;
Noah Eisenb2a26472016-10-21 16:43:57 -0700203 case "unimplemented_method":
204 RunUnimplementedMethod(client);
205 break;
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700206 case "client_compressed_unary":
207 RunClientCompressedUnary(client);
208 break;
209 case "client_compressed_streaming":
210 await RunClientCompressedStreamingAsync(client);
211 break;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800212 default:
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700213 throw new ArgumentException("Unknown test case " + options.TestCase);
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800214 }
215 }
216
Jan Tattermusch809148d2016-03-22 15:09:41 -0700217 public static void RunEmptyUnary(TestService.TestServiceClient client)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800218 {
219 Console.WriteLine("running empty_unary");
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700220 var response = client.EmptyCall(new Empty());
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800221 Assert.IsNotNull(response);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800222 Console.WriteLine("Passed!");
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800223 }
224
Jan Tattermusch809148d2016-03-22 15:09:41 -0700225 public static void RunLargeUnary(TestService.TestServiceClient client)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800226 {
227 Console.WriteLine("running large_unary");
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700228 var request = new SimpleRequest
229 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700230 ResponseSize = 314159,
231 Payload = CreateZerosPayload(271828)
232 };
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800233 var response = client.UnaryCall(request);
234
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800235 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800236 Console.WriteLine("Passed!");
237 }
238
Jan Tattermusch809148d2016-03-22 15:09:41 -0700239 public static async Task RunClientStreamingAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800240 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700241 Console.WriteLine("running client_streaming");
242
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700243 var bodySizes = new List<int> { 27182, 8, 1828, 45904 }.Select((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700244
245 using (var call = client.StreamingInputCall())
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800246 {
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700247 await call.RequestStream.WriteAllAsync(bodySizes);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800248
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700249 var response = await call.ResponseAsync;
250 Assert.AreEqual(74922, response.AggregatedPayloadSize);
251 }
252 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800253 }
254
Jan Tattermusch809148d2016-03-22 15:09:41 -0700255 public static async Task RunServerStreamingAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800256 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700257 Console.WriteLine("running server_streaming");
258
259 var bodySizes = new List<int> { 31415, 9, 2653, 58979 };
260
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700261 var request = new StreamingOutputCallRequest
262 {
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700263 ResponseParameters = { bodySizes.Select((size) => new ResponseParameters { Size = size }) }
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700264 };
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700265
266 using (var call = client.StreamingOutputCall(request))
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700267 {
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700268 var responseList = await call.ResponseStream.ToListAsync();
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700269 CollectionAssert.AreEqual(bodySizes, responseList.Select((item) => item.Payload.Body.Length));
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700270 }
271 Console.WriteLine("Passed!");
272 }
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800273
Jan Tattermusch809148d2016-03-22 15:09:41 -0700274 public static async Task RunPingPongAsync(TestService.TestServiceClient client)
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700275 {
276 Console.WriteLine("running ping_pong");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800277
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700278 using (var call = client.FullDuplexCall())
279 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700280 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
281 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700282 ResponseParameters = { new ResponseParameters { Size = 31415 } },
283 Payload = CreateZerosPayload(27182)
284 });
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800285
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700286 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700287 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
288
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700289 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
290 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700291 ResponseParameters = { new ResponseParameters { Size = 9 } },
292 Payload = CreateZerosPayload(8)
293 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700294
295 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700296 Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length);
297
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700298 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
299 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700300 ResponseParameters = { new ResponseParameters { Size = 2653 } },
301 Payload = CreateZerosPayload(1828)
302 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700303
304 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700305 Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length);
306
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700307 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
308 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700309 ResponseParameters = { new ResponseParameters { Size = 58979 } },
310 Payload = CreateZerosPayload(45904)
311 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700312
313 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700314 Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length);
315
316 await call.RequestStream.CompleteAsync();
317
318 Assert.IsFalse(await call.ResponseStream.MoveNext());
319 }
320 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800321 }
322
Jan Tattermusch809148d2016-03-22 15:09:41 -0700323 public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800324 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700325 Console.WriteLine("running empty_stream");
326 using (var call = client.FullDuplexCall())
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700327 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700328 await call.RequestStream.CompleteAsync();
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800329
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700330 var responseList = await call.ResponseStream.ToListAsync();
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700331 Assert.AreEqual(0, responseList.Count);
332 }
333 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800334 }
335
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700336 public static void RunComputeEngineCreds(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700337 {
338 Console.WriteLine("running compute_engine_creds");
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700339
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700340 var request = new SimpleRequest
341 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700342 ResponseSize = 314159,
343 Payload = CreateZerosPayload(271828),
344 FillUsername = true,
345 FillOauthScope = true
346 };
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700347
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700348 // not setting credentials here because they were set on channel already
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700349 var response = client.UnaryCall(request);
350
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700351 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700352 Assert.False(string.IsNullOrEmpty(response.OauthScope));
353 Assert.True(oauthScope.Contains(response.OauthScope));
354 Assert.AreEqual(defaultServiceAccount, response.Username);
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700355 Console.WriteLine("Passed!");
356 }
357
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700358 public static void RunJwtTokenCreds(TestService.TestServiceClient client)
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700359 {
360 Console.WriteLine("running jwt_token_creds");
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700361
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700362 var request = new SimpleRequest
363 {
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700364 ResponseSize = 314159,
365 Payload = CreateZerosPayload(271828),
366 FillUsername = true,
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700367 };
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700368
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700369 // not setting credentials here because they were set on channel already
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700370 var response = client.UnaryCall(request);
371
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700372 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700373 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700374 Console.WriteLine("Passed!");
375 }
376
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700377 public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope)
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700378 {
379 Console.WriteLine("running oauth2_auth_token");
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700380 ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700381 string oauth2Token = await credential.GetAccessTokenForRequestAsync();
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700382
Jan Tattermusch18729a02015-10-08 18:40:00 -0700383 var credentials = GoogleGrpcCredentials.FromAccessToken(oauth2Token);
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700384 var request = new SimpleRequest
385 {
386 FillUsername = true,
387 FillOauthScope = true
388 };
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700389
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700390 var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700391
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700392 Assert.False(string.IsNullOrEmpty(response.OauthScope));
393 Assert.True(oauthScope.Contains(response.OauthScope));
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700394 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700395 Console.WriteLine("Passed!");
396 }
397
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700398 public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope)
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700399 {
400 Console.WriteLine("running per_rpc_creds");
Jan Tattermuschcf72a3a2015-10-08 08:44:20 -0700401 ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700402
Jan Tattermusch18729a02015-10-08 18:40:00 -0700403 var credentials = googleCredential.ToCallCredentials();
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700404 var request = new SimpleRequest
405 {
406 FillUsername = true,
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700407 };
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700408
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700409 var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700410
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700411 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700412 Console.WriteLine("Passed!");
413 }
414
Jan Tattermusch809148d2016-03-22 15:09:41 -0700415 public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700416 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700417 Console.WriteLine("running cancel_after_begin");
418
419 var cts = new CancellationTokenSource();
420 using (var call = client.StreamingInputCall(cancellationToken: cts.Token))
Jan Tattermusche5c44602015-05-01 11:12:34 -0700421 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700422 // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
423 await Task.Delay(1000);
424 cts.Cancel();
Jan Tattermusche5c44602015-05-01 11:12:34 -0700425
Jan Tattermusch9f19bd32016-04-08 13:32:30 -0700426 var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
Jan Tattermuschc8d7b842015-08-07 20:52:21 -0700427 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700428 }
429 Console.WriteLine("Passed!");
Jan Tattermusche5c44602015-05-01 11:12:34 -0700430 }
431
Jan Tattermusch809148d2016-03-22 15:09:41 -0700432 public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700433 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700434 Console.WriteLine("running cancel_after_first_response");
435
436 var cts = new CancellationTokenSource();
437 using (var call = client.FullDuplexCall(cancellationToken: cts.Token))
Jan Tattermusche5c44602015-05-01 11:12:34 -0700438 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700439 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
440 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700441 ResponseParameters = { new ResponseParameters { Size = 31415 } },
442 Payload = CreateZerosPayload(27182)
443 });
Jan Tattermusche5c44602015-05-01 11:12:34 -0700444
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700445 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700446 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
447
448 cts.Cancel();
449
Jan Tattermusch71702b12016-05-25 20:48:38 -0700450 try
451 {
452 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
453 await call.ResponseStream.MoveNext();
454 Assert.Fail();
455 }
456 catch (RpcException ex)
457 {
458 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
459 }
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700460 }
461 Console.WriteLine("Passed!");
Jan Tattermusche5c44602015-05-01 11:12:34 -0700462 }
463
Jan Tattermusch809148d2016-03-22 15:09:41 -0700464 public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client)
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700465 {
466 Console.WriteLine("running timeout_on_sleeping_server");
467
468 var deadline = DateTime.UtcNow.AddMilliseconds(1);
469 using (var call = client.FullDuplexCall(deadline: deadline))
470 {
471 try
472 {
Jan Tattermusch0608a002015-08-26 08:50:19 -0700473 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) });
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700474 }
475 catch (InvalidOperationException)
476 {
477 // Deadline was reached before write has started. Eat the exception and continue.
478 }
Jan Tattermuscha46d21d2016-05-10 09:57:51 -0700479 catch (RpcException)
480 {
481 // Deadline was reached before write has started. Eat the exception and continue.
482 }
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700483
Jan Tattermusch1e5d9b92016-05-25 21:38:10 -0700484 try
485 {
486 await call.ResponseStream.MoveNext();
487 Assert.Fail();
488 }
489 catch (RpcException ex)
490 {
491 // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
492 Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
493 }
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700494 }
495 Console.WriteLine("Passed!");
496 }
497
Jan Tattermusch809148d2016-03-22 15:09:41 -0700498 public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client)
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800499 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800500 Console.WriteLine("running custom_metadata");
501 {
502 // step 1: test unary call
503 var request = new SimpleRequest
504 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800505 ResponseSize = 314159,
506 Payload = CreateZerosPayload(271828)
507 };
508
509 var call = client.UnaryCallAsync(request, headers: CreateTestMetadata());
510 await call.ResponseAsync;
511
512 var responseHeaders = await call.ResponseHeadersAsync;
513 var responseTrailers = call.GetTrailers();
514
515 Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
516 CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
517 }
518
519 {
520 // step 2: test full duplex call
521 var request = new StreamingOutputCallRequest
522 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800523 ResponseParameters = { new ResponseParameters { Size = 31415 } },
524 Payload = CreateZerosPayload(27182)
525 };
526
527 var call = client.FullDuplexCall(headers: CreateTestMetadata());
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800528
529 await call.RequestStream.WriteAsync(request);
530 await call.RequestStream.CompleteAsync();
531 await call.ResponseStream.ToListAsync();
532
Noah Eisen2d41ed12016-10-12 17:53:43 -0700533 var responseHeaders = await call.ResponseHeadersAsync;
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800534 var responseTrailers = call.GetTrailers();
535
536 Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
537 CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
538 }
539
540 Console.WriteLine("Passed!");
541 }
542
Jan Tattermusch809148d2016-03-22 15:09:41 -0700543 public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client)
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800544 {
545 Console.WriteLine("running status_code_and_message");
546 var echoStatus = new EchoStatus
547 {
548 Code = 2,
549 Message = "test status message"
550 };
551
552 {
553 // step 1: test unary call
554 var request = new SimpleRequest { ResponseStatus = echoStatus };
555
556 var e = Assert.Throws<RpcException>(() => client.UnaryCall(request));
557 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
558 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
559 }
560
561 {
562 // step 2: test full duplex call
563 var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus };
564
565 var call = client.FullDuplexCall();
566 await call.RequestStream.WriteAsync(request);
567 await call.RequestStream.CompleteAsync();
568
Jan Tattermusch71702b12016-05-25 20:48:38 -0700569 try
570 {
571 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
572 await call.ResponseStream.ToListAsync();
573 Assert.Fail();
574 }
575 catch (RpcException e)
576 {
577 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
578 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
579 }
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800580 }
581
582 Console.WriteLine("Passed!");
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800583 }
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800584
Noah Eisen9a171c72016-10-21 16:26:40 -0700585 public static void RunUnimplementedService(UnimplementedService.UnimplementedServiceClient client)
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800586 {
Noah Eisen9a171c72016-10-21 16:26:40 -0700587 Console.WriteLine("running unimplemented_service");
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800588 var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
589
590 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800591 Console.WriteLine("Passed!");
592 }
593
Noah Eisenb2a26472016-10-21 16:43:57 -0700594 public static void RunUnimplementedMethod(TestService.TestServiceClient client)
595 {
596 Console.WriteLine("running unimplemented_method");
597 var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
598
599 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
600 Console.WriteLine("Passed!");
601 }
602
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700603 public static void RunClientCompressedUnary(TestService.TestServiceClient client)
604 {
605 Console.WriteLine("running client_compressed_unary");
606 var probeRequest = new SimpleRequest
607 {
608 ExpectCompressed = new BoolValue
609 {
610 Value = true // lie about compression
611 },
612 ResponseSize = 314159,
613 Payload = CreateZerosPayload(271828)
614 };
615 var e = Assert.Throws<RpcException>(() => client.UnaryCall(probeRequest, CreateClientCompressionMetadata(false)));
616 Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode);
617
618 var compressedRequest = new SimpleRequest
619 {
620 ExpectCompressed = new BoolValue
621 {
622 Value = true
623 },
624 ResponseSize = 314159,
625 Payload = CreateZerosPayload(271828)
626 };
627 var response1 = client.UnaryCall(compressedRequest, CreateClientCompressionMetadata(true));
628 Assert.AreEqual(314159, response1.Payload.Body.Length);
629
630 var uncompressedRequest = new SimpleRequest
631 {
632 ExpectCompressed = new BoolValue
633 {
634 Value = false
635 },
636 ResponseSize = 314159,
637 Payload = CreateZerosPayload(271828)
638 };
639 var response2 = client.UnaryCall(uncompressedRequest, CreateClientCompressionMetadata(false));
640 Assert.AreEqual(314159, response2.Payload.Body.Length);
641
642 Console.WriteLine("Passed!");
643 }
644
645 public static async Task RunClientCompressedStreamingAsync(TestService.TestServiceClient client)
646 {
647 Console.WriteLine("running client_compressed_streaming");
648 try
649 {
650 var probeCall = client.StreamingInputCall(CreateClientCompressionMetadata(false));
651 await probeCall.RequestStream.WriteAsync(new StreamingInputCallRequest
652 {
653 ExpectCompressed = new BoolValue
654 {
655 Value = true
656 },
657 Payload = CreateZerosPayload(27182)
658 });
659
660 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
661 await probeCall;
662 Assert.Fail();
663 }
664 catch (RpcException e)
665 {
666 Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode);
667 }
668
669 var call = client.StreamingInputCall(CreateClientCompressionMetadata(true));
670 await call.RequestStream.WriteAsync(new StreamingInputCallRequest
671 {
672 ExpectCompressed = new BoolValue
673 {
674 Value = true
675 },
676 Payload = CreateZerosPayload(27182)
677 });
678
679 call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress);
680 await call.RequestStream.WriteAsync(new StreamingInputCallRequest
681 {
682 ExpectCompressed = new BoolValue
683 {
684 Value = false
685 },
686 Payload = CreateZerosPayload(45904)
687 });
688 await call.RequestStream.CompleteAsync();
689
690 var response = await call.ResponseAsync;
691 Assert.AreEqual(73086, response.AggregatedPayloadSize);
692
693 Console.WriteLine("Passed!");
694 }
695
Jan Tattermusch075dde42015-03-11 18:21:00 -0700696 private static Payload CreateZerosPayload(int size)
697 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700698 return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800699 }
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700700
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700701 private static Metadata CreateClientCompressionMetadata(bool compressed)
702 {
703 var algorithmName = compressed ? "gzip" : "identity";
704 return new Metadata
705 {
Jan Tattermusch606e35a2016-06-22 12:26:36 -0700706 { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, algorithmName) }
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700707 };
708 }
709
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700710 // extracts the client_email field from service account file used for auth test cases
711 private static string GetEmailFromServiceAccountFile()
712 {
713 string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
714 Assert.IsNotNull(keyFile);
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700715 var jobject = JObject.Parse(File.ReadAllText(keyFile));
716 string email = jobject.GetValue("client_email").Value<string>();
717 Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
718 return email;
719 }
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800720
721 private static Metadata CreateTestMetadata()
722 {
723 return new Metadata
724 {
725 {"x-grpc-test-echo-initial", "test_initial_metadata_value"},
726 {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}}
727 };
728 }
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800729 }
730}