blob: e83a8a7274a52b6ba812b424ea138a95ab5d6976 [file] [log] [blame]
Jan Tattermuscha7fff862015-02-13 11:08:08 -08001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015-2016 gRPC authors.
Craig Tiller190d3602015-02-18 09:23:38 -08004//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005// 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
Craig Tiller190d3602015-02-18 09:23:38 -08008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Craig Tiller190d3602015-02-18 09:23:38 -080010//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011// 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 Tattermuscha7fff862015-02-13 11:08:08 -080016
17#endregion
18
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080019using System;
Jan Tattermuschd233d3a2015-02-06 14:15:00 -080020using System.Collections.Generic;
Jan Tattermusch74f39e12015-09-23 20:14:56 -070021using System.IO;
Jan Tattermusch0ed73152015-12-09 18:21:11 -080022using System.Linq;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080023using System.Text.RegularExpressions;
Jan Tattermusche5c44602015-05-01 11:12:34 -070024using System.Threading;
Jan Tattermuscha5272b62015-04-30 11:56:46 -070025using System.Threading.Tasks;
Jan Tattermusch1ca56b92015-04-27 11:03:06 -070026
Jan Tattermuschb26972f2015-09-03 17:47:14 -070027using CommandLine;
Jan Tattermusch74f39e12015-09-23 20:14:56 -070028using CommandLine.Text;
Jan Tattermusch67c45872015-08-27 18:12:39 -070029using Google.Apis.Auth.OAuth2;
30using Google.Protobuf;
Jan Tattermuschdca6e882015-04-22 16:56:27 -070031using Grpc.Auth;
Jan Tattermusch30868622015-02-19 09:22:33 -080032using Grpc.Core;
Jan Tattermusch66f85782017-02-24 19:44:16 +010033using Grpc.Core.Logging;
Jan Tattermusch30868622015-02-19 09:22:33 -080034using Grpc.Core.Utils;
Jan Tattermusch8644aea2015-08-03 10:21:18 -070035using Grpc.Testing;
Jan Tattermusch64d7c242015-10-08 08:02:27 -070036using Newtonsoft.Json.Linq;
Jan Tattermusch30868622015-02-19 09:22:33 -080037using NUnit.Framework;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080038
Jan Tattermusch8b86b152015-02-19 21:01:05 -080039namespace Grpc.IntegrationTesting
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080040{
Jan Tattermusch503bbac2015-02-26 18:19:47 -080041 public class InteropClient
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080042 {
43 private class ClientOptions
44 {
Paul Marks3a5bba02017-02-07 16:28:09 -080045 [Option("server_host", Default = "localhost")]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070046 public string ServerHost { get; set; }
47
Jan Tattermusch678ec902016-08-08 12:54:16 +080048 [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070049 public string ServerHostOverride { get; set; }
50
51 [Option("server_port", Required = true)]
52 public int ServerPort { get; set; }
53
Jan Tattermusch678ec902016-08-08 12:54:16 +080054 [Option("test_case", Default = "large_unary")]
Jan Tattermuschb26972f2015-09-03 17:47:14 -070055 public string TestCase { get; set; }
56
Jan Tattermusch7828e812015-10-07 17:27:48 -070057 // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
Jan Tattermusch678ec902016-08-08 12:54:16 +080058 [Option("use_tls", Default = false)]
Jan Tattermusch7828e812015-10-07 17:27:48 -070059 public bool? UseTls { get; set; }
Jan Tattermuschb26972f2015-09-03 17:47:14 -070060
Jan Tattermusch7828e812015-10-07 17:27:48 -070061 // 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 +080062 [Option("use_test_ca", Default = false)]
Jan Tattermusch7828e812015-10-07 17:27:48 -070063 public bool? UseTestCa { get; set; }
Jan Tattermuschb26972f2015-09-03 17:47:14 -070064
65 [Option("default_service_account", Required = false)]
66 public string DefaultServiceAccount { get; set; }
67
68 [Option("oauth_scope", Required = false)]
69 public string OAuthScope { get; set; }
70
71 [Option("service_account_key_file", Required = false)]
72 public string ServiceAccountKeyFile { get; set; }
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080073 }
74
75 ClientOptions options;
76
Jan Tattermusch503bbac2015-02-26 18:19:47 -080077 private InteropClient(ClientOptions options)
Jan Tattermusch392d1e02015-02-09 11:13:51 -080078 {
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080079 this.options = options;
80 }
81
Jan Tattermusch503bbac2015-02-26 18:19:47 -080082 public static void Run(string[] args)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080083 {
Jan Tattermusch66f85782017-02-24 19:44:16 +010084 GrpcEnvironment.SetLogger(new ConsoleLogger());
Jan Tattermusch90cbde82016-08-08 14:33:28 +080085 var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
86 .WithNotParsed(errors => Environment.Exit(1))
87 .WithParsed(options =>
88 {
89 var interopClient = new InteropClient(options);
90 interopClient.Run().Wait();
91 });
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080092 }
93
Jan Tattermusch0c140a82015-08-02 00:54:02 -070094 private async Task Run()
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -080095 {
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -070096 var credentials = await CreateCredentialsAsync();
97
98 List<ChannelOption> channelOptions = null;
99 if (!string.IsNullOrEmpty(options.ServerHostOverride))
100 {
101 channelOptions = new List<ChannelOption>
102 {
103 new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride)
104 };
105 }
106 var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800107 await RunTestCaseAsync(channel, options);
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700108 await channel.ShutdownAsync();
109 }
110
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700111 private async Task<ChannelCredentials> CreateCredentialsAsync()
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700112 {
Jan Tattermuschbeffc772015-10-22 13:28:22 -0700113 var credentials = ChannelCredentials.Insecure;
114 if (options.UseTls.Value)
115 {
116 credentials = options.UseTestCa.Value ? TestCredentials.CreateSslCredentials() : new SslCredentials();
117 }
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700118
119 if (options.TestCase == "jwt_token_creds")
120 {
121 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
122 Assert.IsTrue(googleCredential.IsCreateScopedRequired);
Jan Tattermusch18729a02015-10-08 18:40:00 -0700123 credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700124 }
125
126 if (options.TestCase == "compute_engine_creds")
127 {
128 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
129 Assert.IsFalse(googleCredential.IsCreateScopedRequired);
Jan Tattermusch18729a02015-10-08 18:40:00 -0700130 credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700131 }
Jan Tattermusch9e5e7e92015-09-24 10:34:05 -0700132 return credentials;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800133 }
134
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800135 private async Task RunTestCaseAsync(Channel channel, ClientOptions options)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800136 {
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800137 var client = new TestService.TestServiceClient(channel);
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700138 switch (options.TestCase)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800139 {
140 case "empty_unary":
141 RunEmptyUnary(client);
142 break;
143 case "large_unary":
144 RunLargeUnary(client);
145 break;
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800146 case "client_streaming":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700147 await RunClientStreamingAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800148 break;
149 case "server_streaming":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700150 await RunServerStreamingAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800151 break;
152 case "ping_pong":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700153 await RunPingPongAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800154 break;
155 case "empty_stream":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700156 await RunEmptyStreamAsync(client);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800157 break;
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700158 case "compute_engine_creds":
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700159 RunComputeEngineCreds(client, options.DefaultServiceAccount, options.OAuthScope);
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700160 break;
161 case "jwt_token_creds":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700162 RunJwtTokenCreds(client);
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700163 break;
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700164 case "oauth2_auth_token":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700165 await RunOAuth2AuthTokenAsync(client, options.OAuthScope);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700166 break;
167 case "per_rpc_creds":
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700168 await RunPerRpcCredsAsync(client, options.OAuthScope);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700169 break;
Jan Tattermusche5c44602015-05-01 11:12:34 -0700170 case "cancel_after_begin":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700171 await RunCancelAfterBeginAsync(client);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700172 break;
173 case "cancel_after_first_response":
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700174 await RunCancelAfterFirstResponseAsync(client);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700175 break;
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700176 case "timeout_on_sleeping_server":
177 await RunTimeoutOnSleepingServerAsync(client);
178 break;
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800179 case "custom_metadata":
180 await RunCustomMetadataAsync(client);
181 break;
182 case "status_code_and_message":
183 await RunStatusCodeAndMessageAsync(client);
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800184 break;
Noah Eisen9a171c72016-10-21 16:26:40 -0700185 case "unimplemented_service":
186 RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel));
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800187 break;
Noah Eisenb2a26472016-10-21 16:43:57 -0700188 case "unimplemented_method":
189 RunUnimplementedMethod(client);
190 break;
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700191 case "client_compressed_unary":
192 RunClientCompressedUnary(client);
193 break;
194 case "client_compressed_streaming":
195 await RunClientCompressedStreamingAsync(client);
196 break;
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800197 default:
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700198 throw new ArgumentException("Unknown test case " + options.TestCase);
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800199 }
200 }
201
Jan Tattermusch809148d2016-03-22 15:09:41 -0700202 public static void RunEmptyUnary(TestService.TestServiceClient client)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800203 {
204 Console.WriteLine("running empty_unary");
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700205 var response = client.EmptyCall(new Empty());
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800206 Assert.IsNotNull(response);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800207 Console.WriteLine("Passed!");
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800208 }
209
Jan Tattermusch809148d2016-03-22 15:09:41 -0700210 public static void RunLargeUnary(TestService.TestServiceClient client)
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800211 {
212 Console.WriteLine("running large_unary");
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700213 var request = new SimpleRequest
214 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700215 ResponseSize = 314159,
216 Payload = CreateZerosPayload(271828)
217 };
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800218 var response = client.UnaryCall(request);
219
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800220 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800221 Console.WriteLine("Passed!");
222 }
223
Jan Tattermusch809148d2016-03-22 15:09:41 -0700224 public static async Task RunClientStreamingAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800225 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700226 Console.WriteLine("running client_streaming");
227
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700228 var bodySizes = new List<int> { 27182, 8, 1828, 45904 }.Select((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700229
230 using (var call = client.StreamingInputCall())
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800231 {
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700232 await call.RequestStream.WriteAllAsync(bodySizes);
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800233
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700234 var response = await call.ResponseAsync;
235 Assert.AreEqual(74922, response.AggregatedPayloadSize);
236 }
237 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800238 }
239
Jan Tattermusch809148d2016-03-22 15:09:41 -0700240 public static async Task RunServerStreamingAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800241 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700242 Console.WriteLine("running server_streaming");
243
244 var bodySizes = new List<int> { 31415, 9, 2653, 58979 };
245
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700246 var request = new StreamingOutputCallRequest
247 {
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700248 ResponseParameters = { bodySizes.Select((size) => new ResponseParameters { Size = size }) }
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700249 };
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700250
251 using (var call = client.StreamingOutputCall(request))
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700252 {
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700253 var responseList = await call.ResponseStream.ToListAsync();
Jan Tattermusch317b8ac2016-06-16 09:36:11 -0700254 CollectionAssert.AreEqual(bodySizes, responseList.Select((item) => item.Payload.Body.Length));
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700255 }
256 Console.WriteLine("Passed!");
257 }
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800258
Jan Tattermusch809148d2016-03-22 15:09:41 -0700259 public static async Task RunPingPongAsync(TestService.TestServiceClient client)
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700260 {
261 Console.WriteLine("running ping_pong");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800262
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700263 using (var call = client.FullDuplexCall())
264 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700265 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
266 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700267 ResponseParameters = { new ResponseParameters { Size = 31415 } },
268 Payload = CreateZerosPayload(27182)
269 });
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800270
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700271 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700272 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
273
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700274 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
275 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700276 ResponseParameters = { new ResponseParameters { Size = 9 } },
277 Payload = CreateZerosPayload(8)
278 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700279
280 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700281 Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length);
282
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700283 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
284 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700285 ResponseParameters = { new ResponseParameters { Size = 2653 } },
286 Payload = CreateZerosPayload(1828)
287 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700288
289 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700290 Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length);
291
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700292 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
293 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700294 ResponseParameters = { new ResponseParameters { Size = 58979 } },
295 Payload = CreateZerosPayload(45904)
296 });
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700297
298 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700299 Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length);
300
301 await call.RequestStream.CompleteAsync();
302
303 Assert.IsFalse(await call.ResponseStream.MoveNext());
304 }
305 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800306 }
307
Jan Tattermusch809148d2016-03-22 15:09:41 -0700308 public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client)
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800309 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700310 Console.WriteLine("running empty_stream");
311 using (var call = client.FullDuplexCall())
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700312 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700313 await call.RequestStream.CompleteAsync();
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800314
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700315 var responseList = await call.ResponseStream.ToListAsync();
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700316 Assert.AreEqual(0, responseList.Count);
317 }
318 Console.WriteLine("Passed!");
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800319 }
320
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700321 public static void RunComputeEngineCreds(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700322 {
323 Console.WriteLine("running compute_engine_creds");
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700324
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700325 var request = new SimpleRequest
326 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700327 ResponseSize = 314159,
328 Payload = CreateZerosPayload(271828),
329 FillUsername = true,
330 FillOauthScope = true
331 };
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700332
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700333 // not setting credentials here because they were set on channel already
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700334 var response = client.UnaryCall(request);
335
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700336 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700337 Assert.False(string.IsNullOrEmpty(response.OauthScope));
338 Assert.True(oauthScope.Contains(response.OauthScope));
339 Assert.AreEqual(defaultServiceAccount, response.Username);
Jan Tattermusch0bbfa382015-04-27 16:11:59 -0700340 Console.WriteLine("Passed!");
341 }
342
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700343 public static void RunJwtTokenCreds(TestService.TestServiceClient client)
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700344 {
345 Console.WriteLine("running jwt_token_creds");
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700346
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700347 var request = new SimpleRequest
348 {
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700349 ResponseSize = 314159,
350 Payload = CreateZerosPayload(271828),
351 FillUsername = true,
Jan Tattermusch46e85b02015-08-13 10:31:05 -0700352 };
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700353
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700354 // not setting credentials here because they were set on channel already
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700355 var response = client.UnaryCall(request);
356
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700357 Assert.AreEqual(314159, response.Payload.Body.Length);
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700358 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700359 Console.WriteLine("Passed!");
360 }
361
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700362 public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope)
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700363 {
364 Console.WriteLine("running oauth2_auth_token");
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700365 ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
Jan Tattermusch0c140a82015-08-02 00:54:02 -0700366 string oauth2Token = await credential.GetAccessTokenForRequestAsync();
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700367
Jan Tattermusch18729a02015-10-08 18:40:00 -0700368 var credentials = GoogleGrpcCredentials.FromAccessToken(oauth2Token);
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700369 var request = new SimpleRequest
370 {
371 FillUsername = true,
372 FillOauthScope = true
373 };
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700374
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700375 var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700376
Jan Tattermuschb26972f2015-09-03 17:47:14 -0700377 Assert.False(string.IsNullOrEmpty(response.OauthScope));
378 Assert.True(oauthScope.Contains(response.OauthScope));
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700379 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700380 Console.WriteLine("Passed!");
381 }
382
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700383 public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope)
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700384 {
385 Console.WriteLine("running per_rpc_creds");
Jan Tattermuschcf72a3a2015-10-08 08:44:20 -0700386 ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700387
Jan Tattermusch18729a02015-10-08 18:40:00 -0700388 var credentials = googleCredential.ToCallCredentials();
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700389 var request = new SimpleRequest
390 {
391 FillUsername = true,
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700392 };
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700393
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700394 var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700395
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700396 Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Jan Tattermusch7b4a31f2015-07-20 17:08:13 -0700397 Console.WriteLine("Passed!");
398 }
399
Jan Tattermusch809148d2016-03-22 15:09:41 -0700400 public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700401 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700402 Console.WriteLine("running cancel_after_begin");
403
404 var cts = new CancellationTokenSource();
405 using (var call = client.StreamingInputCall(cancellationToken: cts.Token))
Jan Tattermusche5c44602015-05-01 11:12:34 -0700406 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700407 // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
408 await Task.Delay(1000);
409 cts.Cancel();
Jan Tattermusche5c44602015-05-01 11:12:34 -0700410
Jan Tattermusch9f19bd32016-04-08 13:32:30 -0700411 var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseAsync);
Jan Tattermuschc8d7b842015-08-07 20:52:21 -0700412 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700413 }
414 Console.WriteLine("Passed!");
Jan Tattermusche5c44602015-05-01 11:12:34 -0700415 }
416
Jan Tattermusch809148d2016-03-22 15:09:41 -0700417 public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700418 {
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700419 Console.WriteLine("running cancel_after_first_response");
420
421 var cts = new CancellationTokenSource();
422 using (var call = client.FullDuplexCall(cancellationToken: cts.Token))
Jan Tattermusche5c44602015-05-01 11:12:34 -0700423 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700424 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
425 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700426 ResponseParameters = { new ResponseParameters { Size = 31415 } },
427 Payload = CreateZerosPayload(27182)
428 });
Jan Tattermusche5c44602015-05-01 11:12:34 -0700429
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700430 Assert.IsTrue(await call.ResponseStream.MoveNext());
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700431 Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
432
433 cts.Cancel();
434
Jan Tattermusch71702b12016-05-25 20:48:38 -0700435 try
436 {
437 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
438 await call.ResponseStream.MoveNext();
439 Assert.Fail();
440 }
441 catch (RpcException ex)
442 {
443 Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
444 }
Jan Tattermuschb98e1dd2015-07-24 21:30:14 -0700445 }
446 Console.WriteLine("Passed!");
Jan Tattermusche5c44602015-05-01 11:12:34 -0700447 }
448
Jan Tattermusch809148d2016-03-22 15:09:41 -0700449 public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client)
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700450 {
451 Console.WriteLine("running timeout_on_sleeping_server");
452
453 var deadline = DateTime.UtcNow.AddMilliseconds(1);
454 using (var call = client.FullDuplexCall(deadline: deadline))
455 {
456 try
457 {
Jan Tattermusch0608a002015-08-26 08:50:19 -0700458 await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) });
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700459 }
460 catch (InvalidOperationException)
461 {
462 // Deadline was reached before write has started. Eat the exception and continue.
463 }
Jan Tattermuscha46d21d2016-05-10 09:57:51 -0700464 catch (RpcException)
465 {
466 // Deadline was reached before write has started. Eat the exception and continue.
467 }
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700468
Jan Tattermusch1e5d9b92016-05-25 21:38:10 -0700469 try
470 {
471 await call.ResponseStream.MoveNext();
472 Assert.Fail();
473 }
474 catch (RpcException ex)
475 {
476 // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
477 Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
478 }
Jan Tattermusche4134dd2015-08-12 14:54:40 -0700479 }
480 Console.WriteLine("Passed!");
481 }
482
Jan Tattermusch809148d2016-03-22 15:09:41 -0700483 public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client)
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800484 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800485 Console.WriteLine("running custom_metadata");
486 {
487 // step 1: test unary call
488 var request = new SimpleRequest
489 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800490 ResponseSize = 314159,
491 Payload = CreateZerosPayload(271828)
492 };
493
494 var call = client.UnaryCallAsync(request, headers: CreateTestMetadata());
495 await call.ResponseAsync;
496
497 var responseHeaders = await call.ResponseHeadersAsync;
498 var responseTrailers = call.GetTrailers();
499
500 Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
501 CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
502 }
503
504 {
505 // step 2: test full duplex call
506 var request = new StreamingOutputCallRequest
507 {
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800508 ResponseParameters = { new ResponseParameters { Size = 31415 } },
509 Payload = CreateZerosPayload(27182)
510 };
511
512 var call = client.FullDuplexCall(headers: CreateTestMetadata());
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800513
514 await call.RequestStream.WriteAsync(request);
515 await call.RequestStream.CompleteAsync();
516 await call.ResponseStream.ToListAsync();
517
Noah Eisen2d41ed12016-10-12 17:53:43 -0700518 var responseHeaders = await call.ResponseHeadersAsync;
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800519 var responseTrailers = call.GetTrailers();
520
521 Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
522 CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
523 }
524
525 Console.WriteLine("Passed!");
526 }
527
Jan Tattermusch809148d2016-03-22 15:09:41 -0700528 public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client)
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800529 {
530 Console.WriteLine("running status_code_and_message");
531 var echoStatus = new EchoStatus
532 {
533 Code = 2,
534 Message = "test status message"
535 };
536
537 {
538 // step 1: test unary call
539 var request = new SimpleRequest { ResponseStatus = echoStatus };
540
541 var e = Assert.Throws<RpcException>(() => client.UnaryCall(request));
542 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
543 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
544 }
545
546 {
547 // step 2: test full duplex call
548 var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus };
549
550 var call = client.FullDuplexCall();
551 await call.RequestStream.WriteAsync(request);
552 await call.RequestStream.CompleteAsync();
553
Jan Tattermusch71702b12016-05-25 20:48:38 -0700554 try
555 {
556 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
557 await call.ResponseStream.ToListAsync();
558 Assert.Fail();
559 }
560 catch (RpcException e)
561 {
562 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
563 Assert.AreEqual(echoStatus.Message, e.Status.Detail);
564 }
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800565 }
566
567 Console.WriteLine("Passed!");
Jan Tattermusch50faa8f2015-02-21 17:51:52 -0800568 }
Jan Tattermuschd233d3a2015-02-06 14:15:00 -0800569
Noah Eisen9a171c72016-10-21 16:26:40 -0700570 public static void RunUnimplementedService(UnimplementedService.UnimplementedServiceClient client)
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800571 {
Noah Eisen9a171c72016-10-21 16:26:40 -0700572 Console.WriteLine("running unimplemented_service");
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800573 var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
574
575 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
Jan Tattermuschfa20ebc2015-12-09 18:38:10 -0800576 Console.WriteLine("Passed!");
577 }
578
Noah Eisenb2a26472016-10-21 16:43:57 -0700579 public static void RunUnimplementedMethod(TestService.TestServiceClient client)
580 {
581 Console.WriteLine("running unimplemented_method");
582 var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
583
584 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
585 Console.WriteLine("Passed!");
586 }
587
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700588 public static void RunClientCompressedUnary(TestService.TestServiceClient client)
589 {
590 Console.WriteLine("running client_compressed_unary");
591 var probeRequest = new SimpleRequest
592 {
593 ExpectCompressed = new BoolValue
594 {
595 Value = true // lie about compression
596 },
597 ResponseSize = 314159,
598 Payload = CreateZerosPayload(271828)
599 };
600 var e = Assert.Throws<RpcException>(() => client.UnaryCall(probeRequest, CreateClientCompressionMetadata(false)));
601 Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode);
602
603 var compressedRequest = new SimpleRequest
604 {
605 ExpectCompressed = new BoolValue
606 {
607 Value = true
608 },
609 ResponseSize = 314159,
610 Payload = CreateZerosPayload(271828)
611 };
612 var response1 = client.UnaryCall(compressedRequest, CreateClientCompressionMetadata(true));
613 Assert.AreEqual(314159, response1.Payload.Body.Length);
614
615 var uncompressedRequest = new SimpleRequest
616 {
617 ExpectCompressed = new BoolValue
618 {
619 Value = false
620 },
621 ResponseSize = 314159,
622 Payload = CreateZerosPayload(271828)
623 };
624 var response2 = client.UnaryCall(uncompressedRequest, CreateClientCompressionMetadata(false));
625 Assert.AreEqual(314159, response2.Payload.Body.Length);
626
627 Console.WriteLine("Passed!");
628 }
629
630 public static async Task RunClientCompressedStreamingAsync(TestService.TestServiceClient client)
631 {
632 Console.WriteLine("running client_compressed_streaming");
633 try
634 {
635 var probeCall = client.StreamingInputCall(CreateClientCompressionMetadata(false));
636 await probeCall.RequestStream.WriteAsync(new StreamingInputCallRequest
637 {
638 ExpectCompressed = new BoolValue
639 {
640 Value = true
641 },
642 Payload = CreateZerosPayload(27182)
643 });
644
645 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
646 await probeCall;
647 Assert.Fail();
648 }
649 catch (RpcException e)
650 {
651 Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode);
652 }
653
654 var call = client.StreamingInputCall(CreateClientCompressionMetadata(true));
655 await call.RequestStream.WriteAsync(new StreamingInputCallRequest
656 {
657 ExpectCompressed = new BoolValue
658 {
659 Value = true
660 },
661 Payload = CreateZerosPayload(27182)
662 });
663
664 call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress);
665 await call.RequestStream.WriteAsync(new StreamingInputCallRequest
666 {
667 ExpectCompressed = new BoolValue
668 {
669 Value = false
670 },
671 Payload = CreateZerosPayload(45904)
672 });
673 await call.RequestStream.CompleteAsync();
674
675 var response = await call.ResponseAsync;
676 Assert.AreEqual(73086, response.AggregatedPayloadSize);
677
678 Console.WriteLine("Passed!");
679 }
680
Jan Tattermusch075dde42015-03-11 18:21:00 -0700681 private static Payload CreateZerosPayload(int size)
682 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -0700683 return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800684 }
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700685
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700686 private static Metadata CreateClientCompressionMetadata(bool compressed)
687 {
688 var algorithmName = compressed ? "gzip" : "identity";
689 return new Metadata
690 {
Jan Tattermusch606e35a2016-06-22 12:26:36 -0700691 { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, algorithmName) }
Jan Tattermuscha7daf1e2016-06-21 19:11:49 -0700692 };
693 }
694
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700695 // extracts the client_email field from service account file used for auth test cases
696 private static string GetEmailFromServiceAccountFile()
697 {
698 string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
699 Assert.IsNotNull(keyFile);
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700700 var jobject = JObject.Parse(File.ReadAllText(keyFile));
701 string email = jobject.GetValue("client_email").Value<string>();
702 Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
703 return email;
704 }
Jan Tattermusch0ed73152015-12-09 18:21:11 -0800705
706 private static Metadata CreateTestMetadata()
707 {
708 return new Metadata
709 {
710 {"x-grpc-test-echo-initial", "test_initial_metadata_value"},
711 {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}}
712 };
713 }
Jan Tattermuscheb3e76e2015-02-06 11:43:13 -0800714 }
715}