blob: 68a8f4879b46b6690b28862bcd3627990394751e [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;
48using Grpc.Core.Utils;
Jan Tattermusch8644aea2015-08-03 10:21:18 -070049using Grpc.Testing;
Jan Tattermusch64d7c242015-10-08 08:02:27 -070050using Newtonsoft.Json.Linq;
Jan Tattermusch30868622015-02-19 09:22:33 -080051using NUnit.Framework;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080052
Jan Tattermusch8b86b152015-02-19 21:01:05 -080053namespace Grpc.IntegrationTesting
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080054{
Jan Tattermusch503bbac2015-02-26 18:19:47 -080055 public class InteropClient
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080056 {
57 private class ClientOptions
58 {
Paul Marks3a5bba02017-02-07 16:28:09 -080059 [Option("server_host", Default = "localhost")]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070060 public string ServerHost { get; set; }
61
Jan Tattermusch678ec902016-08-08 12:54:16 +080062 [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070063 public string ServerHostOverride { get; set; }
64
65 [Option("server_port", Required = true)]
66 public int ServerPort { get; set; }
67
Jan Tattermusch678ec902016-08-08 12:54:16 +080068 [Option("test_case", Default = "large_unary")]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070069 public string TestCase { get; set; }
70
Jan Tattermusch7828e812015-10-07 17:27:48 -070071 // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
Jan Tattermusch678ec902016-08-08 12:54:16 +080072 [Option("use_tls", Default = false)]
Jan Tattermusch7828e812015-10-07 17:27:48 -070073 public bool? UseTls { get; set; }
Jan Tattermuschb26972f2015-09-03 17:47:14 -070074
Jan Tattermusch7828e812015-10-07 17:27:48 -070075 // 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 +080076 [Option("use_test_ca", Default = false)]
Jan Tattermusch7828e812015-10-07 17:27:48 -070077 public bool? UseTestCa { get; set; }
Jan Tattermuschb26972f2015-09-03 17:47:14 -070078
79 [Option("default_service_account", Required = false)]
80 public string DefaultServiceAccount { get; set; }
81
82 [Option("oauth_scope", Required = false)]
83 public string OAuthScope { get; set; }
84
85 [Option("service_account_key_file", Required = false)]
86 public string ServiceAccountKeyFile { get; set; }
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080087 }
88
89 ClientOptions options;
90
Jan Tattermusch503bbac2015-02-26 18:19:47 -080091 private InteropClient(ClientOptions options)
Jan Tattermusch392d1e02015-02-09 11:13:51 -080092 {
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080093 this.options = options;
94 }
95
Jan Tattermusch503bbac2015-02-26 18:19:47 -080096 public static void Run(string[] args)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080097 {
Jan Tattermusch90cbde82016-08-08 14:33:28 +080098 var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
99 .WithNotParsed(errors => Environment.Exit(1))
100 .WithParsed(options =>
101 {
102 var interopClient = new InteropClient(options);
103 interopClient.Run().Wait();
104 });
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800105 }
106
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700107 private async Task Run()
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800108 {
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700109 var credentials = await CreateCredentialsAsync();
110
111 List<ChannelOption> channelOptions = null;
112 if (!string.IsNullOrEmpty(options.ServerHostOverride))
113 {
114 channelOptions = new List<ChannelOption>
115 {
116 new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride)
117 };
118 }
119 var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800120 await RunTestCaseAsync(channel, options);
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700121 await channel.ShutdownAsync();
122 }
123
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700124 private async Task<ChannelCredentials> CreateCredentialsAsync()
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700125 {
Jan Tattermuschbeffc772015-10-22 13:28:22 -0700126 var credentials = ChannelCredentials.Insecure;
127 if (options.UseTls.Value)
128 {
129 credentials = options.UseTestCa.Value ? TestCredentials.CreateSslCredentials() : new SslCredentials();
130 }
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700131
132 if (options.TestCase == "jwt_token_creds")
133 {
134 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
135 Assert.IsTrue(googleCredential.IsCreateScopedRequired);
Jan Tattermusch18729a02015-10-08 18:40:00 -0700136 credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700137 }
138
139 if (options.TestCase == "compute_engine_creds")
140 {
141 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
142 Assert.IsFalse(googleCredential.IsCreateScopedRequired);
Jan Tattermusch18729a02015-10-08 18:40:00 -0700143 credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700144 }
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700145 return credentials;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800146 }
147
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800148 private async Task RunTestCaseAsync(Channel channel, ClientOptions options)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800149 {
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800150 var client = new TestService.TestServiceClient(channel);
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700151 switch (options.TestCase)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800152 {
153 case "empty_unary":
154 RunEmptyUnary(client);
155 break;
156 case "large_unary":
157 RunLargeUnary(client);
158 break;
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800159 case "client_streaming":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700160 await RunClientStreamingAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800161 break;
162 case "server_streaming":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700163 await RunServerStreamingAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800164 break;
165 case "ping_pong":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700166 await RunPingPongAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800167 break;
168 case "empty_stream":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700169 await RunEmptyStreamAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800170 break;
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700171 case "compute_engine_creds":
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700172 RunComputeEngineCreds(client, options.DefaultServiceAccount, options.OAuthScope);
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700173 break;
174 case "jwt_token_creds":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700175 RunJwtTokenCreds(client);
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700176 break;
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700177 case "oauth2_auth_token":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700178 await RunOAuth2AuthTokenAsync(client, options.OAuthScope);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700179 break;
180 case "per_rpc_creds":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700181 await RunPerRpcCredsAsync(client, options.OAuthScope);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700182 break;
Jan Tattermusche5c44602015-05-01 11:12:34 -0700183 case "cancel_after_begin":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700184 await RunCancelAfterBeginAsync(client);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700185 break;
186 case "cancel_after_first_response":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700187 await RunCancelAfterFirstResponseAsync(client);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700188 break;
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700189 case "timeout_on_sleeping_server":
190 await RunTimeoutOnSleepingServerAsync(client);
191 break;
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800192 case "custom_metadata":
193 await RunCustomMetadataAsync(client);
194 break;
195 case "status_code_and_message":
196 await RunStatusCodeAndMessageAsync(client);
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800197 break;
Noah Eisen9a171c72016-10-21 16:26:40 -0700198 case "unimplemented_service":
199 RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel));
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800200 break;
Noah Eisenb2a26472016-10-21 16:43:57 -0700201 case "unimplemented_method":
202 RunUnimplementedMethod(client);
203 break;
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700204 case "client_compressed_unary":
205 RunClientCompressedUnary(client);
206 break;
207 case "client_compressed_streaming":
208 await RunClientCompressedStreamingAsync(client);
209 break;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800210 default:
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700211 throw new ArgumentException("Unknown test case " + options.TestCase);
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800212 }
213 }
214
Jan Tattermusch809148d2016-03-22 15:09:41 -0700215 public static void RunEmptyUnary(TestService.TestServiceClient client)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800216 {
217 Console.WriteLine("running empty_unary");
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700218 var response = client.EmptyCall(new Empty());
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800219 Assert.IsNotNull(response);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800220 Console.WriteLine("Passed!");
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800221 }
222
Jan Tattermusch809148d2016-03-22 15:09:41 -0700223 public static void RunLargeUnary(TestService.TestServiceClient client)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800224 {
225 Console.WriteLine("running large_unary");
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700226 var request = new SimpleRequest
227 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700228 ResponseSize = 314159,
229 Payload = CreateZerosPayload(271828)
230 };
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800231 var response = client.UnaryCall(request);
232
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800233 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800234 Console.WriteLine("Passed!");
235 }
236
Jan Tattermusch809148d2016-03-22 15:09:41 -0700237 public static async Task RunClientStreamingAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800238 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700239 Console.WriteLine("running client_streaming");
240
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700241 var bodySizes = new List<int> { 27182, 8, 1828, 45904 }.Select((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700242
243 using (var call = client.StreamingInputCall())
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800244 {
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700245 await call.RequestStream.WriteAllAsync(bodySizes);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800246
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700247 var response = await call.ResponseAsync;
248 Assert.AreEqual(74922, response.AggregatedPayloadSize);
249 }
250 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800251 }
252
Jan Tattermusch809148d2016-03-22 15:09:41 -0700253 public static async Task RunServerStreamingAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800254 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700255 Console.WriteLine("running server_streaming");
256
257 var bodySizes = new List<int> { 31415, 9, 2653, 58979 };
258
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700259 var request = new StreamingOutputCallRequest
260 {
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700261 ResponseParameters = { bodySizes.Select((size) => new ResponseParameters { Size = size }) }
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700262 };
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700263
264 using (var call = client.StreamingOutputCall(request))
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700265 {
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700266 var responseList = await call.ResponseStream.ToListAsync();
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700267 CollectionAssert.AreEqual(bodySizes, responseList.Select((item) => item.Payload.Body.Length));
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700268 }
269 Console.WriteLine("Passed!");
270 }
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800271
Jan Tattermusch809148d2016-03-22 15:09:41 -0700272 public static async Task RunPingPongAsync(TestService.TestServiceClient client)
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700273 {
274 Console.WriteLine("running ping_pong");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800275
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700276 using (var call = client.FullDuplexCall())
277 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700278 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
279 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700280 ResponseParameters = { new ResponseParameters { Size = 31415 } },
281 Payload = CreateZerosPayload(27182)
282 });
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800283
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700284 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700285 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
286
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700287 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
288 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700289 ResponseParameters = { new ResponseParameters { Size = 9 } },
290 Payload = CreateZerosPayload(8)
291 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700292
293 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700294 Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length);
295
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700296 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
297 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700298 ResponseParameters = { new ResponseParameters { Size = 2653 } },
299 Payload = CreateZerosPayload(1828)
300 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700301
302 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700303 Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length);
304
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700305 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
306 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700307 ResponseParameters = { new ResponseParameters { Size = 58979 } },
308 Payload = CreateZerosPayload(45904)
309 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700310
311 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700312 Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length);
313
314 await call.RequestStream.CompleteAsync();
315
316 Assert.IsFalse(await call.ResponseStream.MoveNext());
317 }
318 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800319 }
320
Jan Tattermusch809148d2016-03-22 15:09:41 -0700321 public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800322 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700323 Console.WriteLine("running empty_stream");
324 using (var call = client.FullDuplexCall())
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700325 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700326 await call.RequestStream.CompleteAsync();
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800327
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700328 var responseList = await call.ResponseStream.ToListAsync();
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700329 Assert.AreEqual(0, responseList.Count);
330 }
331 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800332 }
333
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700334 public static void RunComputeEngineCreds(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700335 {
336 Console.WriteLine("running compute_engine_creds");
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700337
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700338 var request = new SimpleRequest
339 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700340 ResponseSize = 314159,
341 Payload = CreateZerosPayload(271828),
342 FillUsername = true,
343 FillOauthScope = true
344 };
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700345
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700346 // not setting credentials here because they were set on channel already
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700347 var response = client.UnaryCall(request);
348
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700349 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700350 Assert.False(string.IsNullOrEmpty(response.OauthScope));
351 Assert.True(oauthScope.Contains(response.OauthScope));
352 Assert.AreEqual(defaultServiceAccount, response.Username);
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700353 Console.WriteLine("Passed!");
354 }
355
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700356 public static void RunJwtTokenCreds(TestService.TestServiceClient client)
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700357 {
358 Console.WriteLine("running jwt_token_creds");
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700359
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700360 var request = new SimpleRequest
361 {
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700362 ResponseSize = 314159,
363 Payload = CreateZerosPayload(271828),
364 FillUsername = true,
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700365 };
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700366
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700367 // not setting credentials here because they were set on channel already
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700368 var response = client.UnaryCall(request);
369
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700370 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700371 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700372 Console.WriteLine("Passed!");
373 }
374
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700375 public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope)
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700376 {
377 Console.WriteLine("running oauth2_auth_token");
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700378 ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700379 string oauth2Token = await credential.GetAccessTokenForRequestAsync();
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700380
Jan Tattermusch18729a02015-10-08 18:40:00 -0700381 var credentials = GoogleGrpcCredentials.FromAccessToken(oauth2Token);
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700382 var request = new SimpleRequest
383 {
384 FillUsername = true,
385 FillOauthScope = true
386 };
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700387
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700388 var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700389
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700390 Assert.False(string.IsNullOrEmpty(response.OauthScope));
391 Assert.True(oauthScope.Contains(response.OauthScope));
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700392 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700393 Console.WriteLine("Passed!");
394 }
395
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700396 public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope)
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700397 {
398 Console.WriteLine("running per_rpc_creds");
Jan Tattermuschcf72a3a2015-10-08 08:44:20 -0700399 ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700400
Jan Tattermusch18729a02015-10-08 18:40:00 -0700401 var credentials = googleCredential.ToCallCredentials();
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700402 var request = new SimpleRequest
403 {
404 FillUsername = true,
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700405 };
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700406
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700407 var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700408
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700409 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700410 Console.WriteLine("Passed!");
411 }
412
Jan Tattermusch809148d2016-03-22 15:09:41 -0700413 public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700414 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700415 Console.WriteLine("running cancel_after_begin");
416
417 var cts = new CancellationTokenSource();
418 using (var call = client.StreamingInputCall(cancellationToken: cts.Token))
Jan Tattermusche5c44602015-05-01 11:12:34 -0700419 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700420 // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
421 await Task.Delay(1000);
422 cts.Cancel();
Jan Tattermusche5c44602015-05-01 11:12:34 -0700423
Jan Tattermusch9f19bd32016-04-08 13:32:30 -0700424 var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
Jan Tattermuschc8d7b842015-08-07 20:52:21 -0700425 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700426 }
427 Console.WriteLine("Passed!");
Jan Tattermusche5c44602015-05-01 11:12:34 -0700428 }
429
Jan Tattermusch809148d2016-03-22 15:09:41 -0700430 public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700431 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700432 Console.WriteLine("running cancel_after_first_response");
433
434 var cts = new CancellationTokenSource();
435 using (var call = client.FullDuplexCall(cancellationToken: cts.Token))
Jan Tattermusche5c44602015-05-01 11:12:34 -0700436 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700437 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
438 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700439 ResponseParameters = { new ResponseParameters { Size = 31415 } },
440 Payload = CreateZerosPayload(27182)
441 });
Jan Tattermusche5c44602015-05-01 11:12:34 -0700442
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700443 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700444 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
445
446 cts.Cancel();
447
Jan Tattermusch71702b12016-05-25 20:48:38 -0700448 try
449 {
450 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
451 await call.ResponseStream.MoveNext();
452 Assert.Fail();
453 }
454 catch (RpcException ex)
455 {
456 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
457 }
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700458 }
459 Console.WriteLine("Passed!");
Jan Tattermusche5c44602015-05-01 11:12:34 -0700460 }
461
Jan Tattermusch809148d2016-03-22 15:09:41 -0700462 public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client)
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700463 {
464 Console.WriteLine("running timeout_on_sleeping_server");
465
466 var deadline = DateTime.UtcNow.AddMilliseconds(1);
467 using (var call = client.FullDuplexCall(deadline: deadline))
468 {
469 try
470 {
Jan Tattermusch0608a002015-08-26 08:50:19 -0700471 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) });
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700472 }
473 catch (InvalidOperationException)
474 {
475 // Deadline was reached before write has started. Eat the exception and continue.
476 }
Jan Tattermuscha46d21d2016-05-10 09:57:51 -0700477 catch (RpcException)
478 {
479 // Deadline was reached before write has started. Eat the exception and continue.
480 }
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700481
Jan Tattermusch1e5d9b92016-05-25 21:38:10 -0700482 try
483 {
484 await call.ResponseStream.MoveNext();
485 Assert.Fail();
486 }
487 catch (RpcException ex)
488 {
489 // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
490 Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
491 }
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700492 }
493 Console.WriteLine("Passed!");
494 }
495
Jan Tattermusch809148d2016-03-22 15:09:41 -0700496 public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client)
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800497 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800498 Console.WriteLine("running custom_metadata");
499 {
500 // step 1: test unary call
501 var request = new SimpleRequest
502 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800503 ResponseSize = 314159,
504 Payload = CreateZerosPayload(271828)
505 };
506
507 var call = client.UnaryCallAsync(request, headers: CreateTestMetadata());
508 await call.ResponseAsync;
509
510 var responseHeaders = await call.ResponseHeadersAsync;
511 var responseTrailers = call.GetTrailers();
512
513 Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
514 CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
515 }
516
517 {
518 // step 2: test full duplex call
519 var request = new StreamingOutputCallRequest
520 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800521 ResponseParameters = { new ResponseParameters { Size = 31415 } },
522 Payload = CreateZerosPayload(27182)
523 };
524
525 var call = client.FullDuplexCall(headers: CreateTestMetadata());
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800526
527 await call.RequestStream.WriteAsync(request);
528 await call.RequestStream.CompleteAsync();
529 await call.ResponseStream.ToListAsync();
530
Noah Eisen2d41ed12016-10-12 17:53:43 -0700531 var responseHeaders = await call.ResponseHeadersAsync;
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800532 var responseTrailers = call.GetTrailers();
533
534 Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
535 CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
536 }
537
538 Console.WriteLine("Passed!");
539 }
540
Jan Tattermusch809148d2016-03-22 15:09:41 -0700541 public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client)
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800542 {
543 Console.WriteLine("running status_code_and_message");
544 var echoStatus = new EchoStatus
545 {
546 Code = 2,
547 Message = "test status message"
548 };
549
550 {
551 // step 1: test unary call
552 var request = new SimpleRequest { ResponseStatus = echoStatus };
553
554 var e = Assert.Throws<RpcException>(() => client.UnaryCall(request));
555 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
556 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
557 }
558
559 {
560 // step 2: test full duplex call
561 var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus };
562
563 var call = client.FullDuplexCall();
564 await call.RequestStream.WriteAsync(request);
565 await call.RequestStream.CompleteAsync();
566
Jan Tattermusch71702b12016-05-25 20:48:38 -0700567 try
568 {
569 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
570 await call.ResponseStream.ToListAsync();
571 Assert.Fail();
572 }
573 catch (RpcException e)
574 {
575 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
576 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
577 }
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800578 }
579
580 Console.WriteLine("Passed!");
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800581 }
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800582
Noah Eisen9a171c72016-10-21 16:26:40 -0700583 public static void RunUnimplementedService(UnimplementedService.UnimplementedServiceClient client)
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800584 {
Noah Eisen9a171c72016-10-21 16:26:40 -0700585 Console.WriteLine("running unimplemented_service");
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800586 var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
587
588 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800589 Console.WriteLine("Passed!");
590 }
591
Noah Eisenb2a26472016-10-21 16:43:57 -0700592 public static void RunUnimplementedMethod(TestService.TestServiceClient client)
593 {
594 Console.WriteLine("running unimplemented_method");
595 var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
596
597 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
598 Console.WriteLine("Passed!");
599 }
600
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700601 public static void RunClientCompressedUnary(TestService.TestServiceClient client)
602 {
603 Console.WriteLine("running client_compressed_unary");
604 var probeRequest = new SimpleRequest
605 {
606 ExpectCompressed = new BoolValue
607 {
608 Value = true // lie about compression
609 },
610 ResponseSize = 314159,
611 Payload = CreateZerosPayload(271828)
612 };
613 var e = Assert.Throws<RpcException>(() => client.UnaryCall(probeRequest, CreateClientCompressionMetadata(false)));
614 Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode);
615
616 var compressedRequest = new SimpleRequest
617 {
618 ExpectCompressed = new BoolValue
619 {
620 Value = true
621 },
622 ResponseSize = 314159,
623 Payload = CreateZerosPayload(271828)
624 };
625 var response1 = client.UnaryCall(compressedRequest, CreateClientCompressionMetadata(true));
626 Assert.AreEqual(314159, response1.Payload.Body.Length);
627
628 var uncompressedRequest = new SimpleRequest
629 {
630 ExpectCompressed = new BoolValue
631 {
632 Value = false
633 },
634 ResponseSize = 314159,
635 Payload = CreateZerosPayload(271828)
636 };
637 var response2 = client.UnaryCall(uncompressedRequest, CreateClientCompressionMetadata(false));
638 Assert.AreEqual(314159, response2.Payload.Body.Length);
639
640 Console.WriteLine("Passed!");
641 }
642
643 public static async Task RunClientCompressedStreamingAsync(TestService.TestServiceClient client)
644 {
645 Console.WriteLine("running client_compressed_streaming");
646 try
647 {
648 var probeCall = client.StreamingInputCall(CreateClientCompressionMetadata(false));
649 await probeCall.RequestStream.WriteAsync(new StreamingInputCallRequest
650 {
651 ExpectCompressed = new BoolValue
652 {
653 Value = true
654 },
655 Payload = CreateZerosPayload(27182)
656 });
657
658 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
659 await probeCall;
660 Assert.Fail();
661 }
662 catch (RpcException e)
663 {
664 Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode);
665 }
666
667 var call = client.StreamingInputCall(CreateClientCompressionMetadata(true));
668 await call.RequestStream.WriteAsync(new StreamingInputCallRequest
669 {
670 ExpectCompressed = new BoolValue
671 {
672 Value = true
673 },
674 Payload = CreateZerosPayload(27182)
675 });
676
677 call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress);
678 await call.RequestStream.WriteAsync(new StreamingInputCallRequest
679 {
680 ExpectCompressed = new BoolValue
681 {
682 Value = false
683 },
684 Payload = CreateZerosPayload(45904)
685 });
686 await call.RequestStream.CompleteAsync();
687
688 var response = await call.ResponseAsync;
689 Assert.AreEqual(73086, response.AggregatedPayloadSize);
690
691 Console.WriteLine("Passed!");
692 }
693
Jan Tattermusch075dde42015-03-11 18:21:00 -0700694 private static Payload CreateZerosPayload(int size)
695 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700696 return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800697 }
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700698
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700699 private static Metadata CreateClientCompressionMetadata(bool compressed)
700 {
701 var algorithmName = compressed ? "gzip" : "identity";
702 return new Metadata
703 {
Jan Tattermusch606e35a2016-06-22 12:26:36 -0700704 { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, algorithmName) }
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700705 };
706 }
707
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700708 // extracts the client_email field from service account file used for auth test cases
709 private static string GetEmailFromServiceAccountFile()
710 {
711 string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
712 Assert.IsNotNull(keyFile);
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700713 var jobject = JObject.Parse(File.ReadAllText(keyFile));
714 string email = jobject.GetValue("client_email").Value<string>();
715 Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
716 return email;
717 }
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800718
719 private static Metadata CreateTestMetadata()
720 {
721 return new Metadata
722 {
723 {"x-grpc-test-echo-initial", "test_initial_metadata_value"},
724 {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}}
725 };
726 }
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800727 }
728}