| Index: third_party/grpc/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
|
| diff --git a/third_party/grpc/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/third_party/grpc/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b0e33e49f77eefabf6a80ada6e0b22e2ab6f2fae
|
| --- /dev/null
|
| +++ b/third_party/grpc/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
|
| @@ -0,0 +1,619 @@
|
| +#region Copyright notice and license
|
| +
|
| +// Copyright 2015, Google Inc.
|
| +// All rights reserved.
|
| +//
|
| +// Redistribution and use in source and binary forms, with or without
|
| +// modification, are permitted provided that the following conditions are
|
| +// met:
|
| +//
|
| +// * Redistributions of source code must retain the above copyright
|
| +// notice, this list of conditions and the following disclaimer.
|
| +// * Redistributions in binary form must reproduce the above
|
| +// copyright notice, this list of conditions and the following disclaimer
|
| +// in the documentation and/or other materials provided with the
|
| +// distribution.
|
| +// * Neither the name of Google Inc. nor the names of its
|
| +// contributors may be used to endorse or promote products derived from
|
| +// this software without specific prior written permission.
|
| +//
|
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +#endregion
|
| +
|
| +using System;
|
| +using System.Collections.Generic;
|
| +using System.IO;
|
| +using System.Linq;
|
| +using System.Text.RegularExpressions;
|
| +using System.Threading;
|
| +using System.Threading.Tasks;
|
| +
|
| +using CommandLine;
|
| +using CommandLine.Text;
|
| +using Google.Apis.Auth.OAuth2;
|
| +using Google.Protobuf;
|
| +using Grpc.Auth;
|
| +using Grpc.Core;
|
| +using Grpc.Core.Utils;
|
| +using Grpc.Testing;
|
| +using Newtonsoft.Json.Linq;
|
| +using NUnit.Framework;
|
| +
|
| +namespace Grpc.IntegrationTesting
|
| +{
|
| + public class InteropClient
|
| + {
|
| + private class ClientOptions
|
| + {
|
| + [Option("server_host", DefaultValue = "127.0.0.1")]
|
| + public string ServerHost { get; set; }
|
| +
|
| + [Option("server_host_override", DefaultValue = TestCredentials.DefaultHostOverride)]
|
| + public string ServerHostOverride { get; set; }
|
| +
|
| + [Option("server_port", Required = true)]
|
| + public int ServerPort { get; set; }
|
| +
|
| + [Option("test_case", DefaultValue = "large_unary")]
|
| + public string TestCase { get; set; }
|
| +
|
| + // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
|
| + [Option("use_tls", DefaultValue = false)]
|
| + public bool? UseTls { get; set; }
|
| +
|
| + // Deliberately using nullable bool type to allow --use_test_ca=true syntax (as opposed to --use_test_ca)
|
| + [Option("use_test_ca", DefaultValue = false)]
|
| + public bool? UseTestCa { get; set; }
|
| +
|
| + [Option("default_service_account", Required = false)]
|
| + public string DefaultServiceAccount { get; set; }
|
| +
|
| + [Option("oauth_scope", Required = false)]
|
| + public string OAuthScope { get; set; }
|
| +
|
| + [Option("service_account_key_file", Required = false)]
|
| + public string ServiceAccountKeyFile { get; set; }
|
| +
|
| + [HelpOption]
|
| + public string GetUsage()
|
| + {
|
| + var help = new HelpText
|
| + {
|
| + Heading = "gRPC C# interop testing client",
|
| + AddDashesToOption = true
|
| + };
|
| + help.AddPreOptionsLine("Usage:");
|
| + help.AddOptions(this);
|
| + return help;
|
| + }
|
| + }
|
| +
|
| + ClientOptions options;
|
| +
|
| + private InteropClient(ClientOptions options)
|
| + {
|
| + this.options = options;
|
| + }
|
| +
|
| + public static void Run(string[] args)
|
| + {
|
| + var options = new ClientOptions();
|
| + if (!Parser.Default.ParseArguments(args, options))
|
| + {
|
| + Environment.Exit(1);
|
| + }
|
| +
|
| + var interopClient = new InteropClient(options);
|
| + interopClient.Run().Wait();
|
| + }
|
| +
|
| + private async Task Run()
|
| + {
|
| + var credentials = await CreateCredentialsAsync();
|
| +
|
| + List<ChannelOption> channelOptions = null;
|
| + if (!string.IsNullOrEmpty(options.ServerHostOverride))
|
| + {
|
| + channelOptions = new List<ChannelOption>
|
| + {
|
| + new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride)
|
| + };
|
| + }
|
| + var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
|
| + await RunTestCaseAsync(channel, options);
|
| + await channel.ShutdownAsync();
|
| + }
|
| +
|
| + private async Task<ChannelCredentials> CreateCredentialsAsync()
|
| + {
|
| + var credentials = ChannelCredentials.Insecure;
|
| + if (options.UseTls.Value)
|
| + {
|
| + credentials = options.UseTestCa.Value ? TestCredentials.CreateSslCredentials() : new SslCredentials();
|
| + }
|
| +
|
| + if (options.TestCase == "jwt_token_creds")
|
| + {
|
| + var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
|
| + Assert.IsTrue(googleCredential.IsCreateScopedRequired);
|
| + credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
|
| + }
|
| +
|
| + if (options.TestCase == "compute_engine_creds")
|
| + {
|
| + var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
|
| + Assert.IsFalse(googleCredential.IsCreateScopedRequired);
|
| + credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
|
| + }
|
| + return credentials;
|
| + }
|
| +
|
| + private async Task RunTestCaseAsync(Channel channel, ClientOptions options)
|
| + {
|
| + var client = new TestService.TestServiceClient(channel);
|
| + switch (options.TestCase)
|
| + {
|
| + case "empty_unary":
|
| + RunEmptyUnary(client);
|
| + break;
|
| + case "large_unary":
|
| + RunLargeUnary(client);
|
| + break;
|
| + case "client_streaming":
|
| + await RunClientStreamingAsync(client);
|
| + break;
|
| + case "server_streaming":
|
| + await RunServerStreamingAsync(client);
|
| + break;
|
| + case "ping_pong":
|
| + await RunPingPongAsync(client);
|
| + break;
|
| + case "empty_stream":
|
| + await RunEmptyStreamAsync(client);
|
| + break;
|
| + case "compute_engine_creds":
|
| + RunComputeEngineCreds(client, options.DefaultServiceAccount, options.OAuthScope);
|
| + break;
|
| + case "jwt_token_creds":
|
| + RunJwtTokenCreds(client);
|
| + break;
|
| + case "oauth2_auth_token":
|
| + await RunOAuth2AuthTokenAsync(client, options.OAuthScope);
|
| + break;
|
| + case "per_rpc_creds":
|
| + await RunPerRpcCredsAsync(client, options.OAuthScope);
|
| + break;
|
| + case "cancel_after_begin":
|
| + await RunCancelAfterBeginAsync(client);
|
| + break;
|
| + case "cancel_after_first_response":
|
| + await RunCancelAfterFirstResponseAsync(client);
|
| + break;
|
| + case "timeout_on_sleeping_server":
|
| + await RunTimeoutOnSleepingServerAsync(client);
|
| + break;
|
| + case "custom_metadata":
|
| + await RunCustomMetadataAsync(client);
|
| + break;
|
| + case "status_code_and_message":
|
| + await RunStatusCodeAndMessageAsync(client);
|
| + break;
|
| + case "unimplemented_method":
|
| + RunUnimplementedMethod(new UnimplementedService.UnimplementedServiceClient(channel));
|
| + break;
|
| + default:
|
| + throw new ArgumentException("Unknown test case " + options.TestCase);
|
| + }
|
| + }
|
| +
|
| + public static void RunEmptyUnary(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running empty_unary");
|
| + var response = client.EmptyCall(new Empty());
|
| + Assert.IsNotNull(response);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static void RunLargeUnary(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running large_unary");
|
| + var request = new SimpleRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseSize = 314159,
|
| + Payload = CreateZerosPayload(271828)
|
| + };
|
| + var response = client.UnaryCall(request);
|
| +
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
|
| + Assert.AreEqual(314159, response.Payload.Body.Length);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunClientStreamingAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running client_streaming");
|
| +
|
| + var bodySizes = new List<int> { 27182, 8, 1828, 45904 }.ConvertAll((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) });
|
| +
|
| + using (var call = client.StreamingInputCall())
|
| + {
|
| + await call.RequestStream.WriteAllAsync(bodySizes);
|
| +
|
| + var response = await call.ResponseAsync;
|
| + Assert.AreEqual(74922, response.AggregatedPayloadSize);
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunServerStreamingAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running server_streaming");
|
| +
|
| + var bodySizes = new List<int> { 31415, 9, 2653, 58979 };
|
| +
|
| + var request = new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { bodySizes.ConvertAll((size) => new ResponseParameters { Size = size }) }
|
| + };
|
| +
|
| + using (var call = client.StreamingOutputCall(request))
|
| + {
|
| + var responseList = await call.ResponseStream.ToListAsync();
|
| + foreach (var res in responseList)
|
| + {
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, res.Payload.Type);
|
| + }
|
| + CollectionAssert.AreEqual(bodySizes, responseList.ConvertAll((item) => item.Payload.Body.Length));
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunPingPongAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running ping_pong");
|
| +
|
| + using (var call = client.FullDuplexCall())
|
| + {
|
| + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { new ResponseParameters { Size = 31415 } },
|
| + Payload = CreateZerosPayload(27182)
|
| + });
|
| +
|
| + Assert.IsTrue(await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
|
| + Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
|
| +
|
| + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { new ResponseParameters { Size = 9 } },
|
| + Payload = CreateZerosPayload(8)
|
| + });
|
| +
|
| + Assert.IsTrue(await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
|
| + Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length);
|
| +
|
| + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { new ResponseParameters { Size = 2653 } },
|
| + Payload = CreateZerosPayload(1828)
|
| + });
|
| +
|
| + Assert.IsTrue(await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
|
| + Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length);
|
| +
|
| + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { new ResponseParameters { Size = 58979 } },
|
| + Payload = CreateZerosPayload(45904)
|
| + });
|
| +
|
| + Assert.IsTrue(await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
|
| + Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length);
|
| +
|
| + await call.RequestStream.CompleteAsync();
|
| +
|
| + Assert.IsFalse(await call.ResponseStream.MoveNext());
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunEmptyStreamAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running empty_stream");
|
| + using (var call = client.FullDuplexCall())
|
| + {
|
| + await call.RequestStream.CompleteAsync();
|
| +
|
| + var responseList = await call.ResponseStream.ToListAsync();
|
| + Assert.AreEqual(0, responseList.Count);
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static void RunComputeEngineCreds(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
|
| + {
|
| + Console.WriteLine("running compute_engine_creds");
|
| +
|
| + var request = new SimpleRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseSize = 314159,
|
| + Payload = CreateZerosPayload(271828),
|
| + FillUsername = true,
|
| + FillOauthScope = true
|
| + };
|
| +
|
| + // not setting credentials here because they were set on channel already
|
| + var response = client.UnaryCall(request);
|
| +
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
|
| + Assert.AreEqual(314159, response.Payload.Body.Length);
|
| + Assert.False(string.IsNullOrEmpty(response.OauthScope));
|
| + Assert.True(oauthScope.Contains(response.OauthScope));
|
| + Assert.AreEqual(defaultServiceAccount, response.Username);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static void RunJwtTokenCreds(TestService.TestServiceClient client)
|
| + {
|
| + Console.WriteLine("running jwt_token_creds");
|
| +
|
| + var request = new SimpleRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseSize = 314159,
|
| + Payload = CreateZerosPayload(271828),
|
| + FillUsername = true,
|
| + };
|
| +
|
| + // not setting credentials here because they were set on channel already
|
| + var response = client.UnaryCall(request);
|
| +
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
|
| + Assert.AreEqual(314159, response.Payload.Body.Length);
|
| + Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope)
|
| + {
|
| + Console.WriteLine("running oauth2_auth_token");
|
| + ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
|
| + string oauth2Token = await credential.GetAccessTokenForRequestAsync();
|
| +
|
| + var credentials = GoogleGrpcCredentials.FromAccessToken(oauth2Token);
|
| + var request = new SimpleRequest
|
| + {
|
| + FillUsername = true,
|
| + FillOauthScope = true
|
| + };
|
| +
|
| + var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
|
| +
|
| + Assert.False(string.IsNullOrEmpty(response.OauthScope));
|
| + Assert.True(oauthScope.Contains(response.OauthScope));
|
| + Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope)
|
| + {
|
| + Console.WriteLine("running per_rpc_creds");
|
| + ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
|
| +
|
| + var credentials = googleCredential.ToCallCredentials();
|
| + var request = new SimpleRequest
|
| + {
|
| + FillUsername = true,
|
| + };
|
| +
|
| + var response = client.UnaryCall(request, new CallOptions(credentials: credentials));
|
| +
|
| + Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunCancelAfterBeginAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running cancel_after_begin");
|
| +
|
| + var cts = new CancellationTokenSource();
|
| + using (var call = client.StreamingInputCall(cancellationToken: cts.Token))
|
| + {
|
| + // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
|
| + await Task.Delay(1000);
|
| + cts.Cancel();
|
| +
|
| + var ex = Assert.Throws<RpcException>(async () => await call.ResponseAsync);
|
| + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunCancelAfterFirstResponseAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running cancel_after_first_response");
|
| +
|
| + var cts = new CancellationTokenSource();
|
| + using (var call = client.FullDuplexCall(cancellationToken: cts.Token))
|
| + {
|
| + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { new ResponseParameters { Size = 31415 } },
|
| + Payload = CreateZerosPayload(27182)
|
| + });
|
| +
|
| + Assert.IsTrue(await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type);
|
| + Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length);
|
| +
|
| + cts.Cancel();
|
| +
|
| + var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunTimeoutOnSleepingServerAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running timeout_on_sleeping_server");
|
| +
|
| + var deadline = DateTime.UtcNow.AddMilliseconds(1);
|
| + using (var call = client.FullDuplexCall(deadline: deadline))
|
| + {
|
| + try
|
| + {
|
| + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) });
|
| + }
|
| + catch (InvalidOperationException)
|
| + {
|
| + // Deadline was reached before write has started. Eat the exception and continue.
|
| + }
|
| +
|
| + var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
|
| + Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode);
|
| + }
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running custom_metadata");
|
| + {
|
| + // step 1: test unary call
|
| + var request = new SimpleRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseSize = 314159,
|
| + Payload = CreateZerosPayload(271828)
|
| + };
|
| +
|
| + var call = client.UnaryCallAsync(request, headers: CreateTestMetadata());
|
| + await call.ResponseAsync;
|
| +
|
| + var responseHeaders = await call.ResponseHeadersAsync;
|
| + var responseTrailers = call.GetTrailers();
|
| +
|
| + Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
|
| + CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
|
| + }
|
| +
|
| + {
|
| + // step 2: test full duplex call
|
| + var request = new StreamingOutputCallRequest
|
| + {
|
| + ResponseType = PayloadType.COMPRESSABLE,
|
| + ResponseParameters = { new ResponseParameters { Size = 31415 } },
|
| + Payload = CreateZerosPayload(27182)
|
| + };
|
| +
|
| + var call = client.FullDuplexCall(headers: CreateTestMetadata());
|
| + var responseHeaders = await call.ResponseHeadersAsync;
|
| +
|
| + await call.RequestStream.WriteAsync(request);
|
| + await call.RequestStream.CompleteAsync();
|
| + await call.ResponseStream.ToListAsync();
|
| +
|
| + var responseTrailers = call.GetTrailers();
|
| +
|
| + Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
|
| + CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
|
| + }
|
| +
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client)
|
| + {
|
| + Console.WriteLine("running status_code_and_message");
|
| + var echoStatus = new EchoStatus
|
| + {
|
| + Code = 2,
|
| + Message = "test status message"
|
| + };
|
| +
|
| + {
|
| + // step 1: test unary call
|
| + var request = new SimpleRequest { ResponseStatus = echoStatus };
|
| +
|
| + var e = Assert.Throws<RpcException>(() => client.UnaryCall(request));
|
| + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
|
| + Assert.AreEqual(echoStatus.Message, e.Status.Detail);
|
| + }
|
| +
|
| + {
|
| + // step 2: test full duplex call
|
| + var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus };
|
| +
|
| + var call = client.FullDuplexCall();
|
| + await call.RequestStream.WriteAsync(request);
|
| + await call.RequestStream.CompleteAsync();
|
| +
|
| + var e = Assert.Throws<RpcException>(async () => await call.ResponseStream.ToListAsync());
|
| + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
|
| + Assert.AreEqual(echoStatus.Message, e.Status.Detail);
|
| + }
|
| +
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client)
|
| + {
|
| + Console.WriteLine("running unimplemented_method");
|
| + var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
|
| +
|
| + Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
|
| + Assert.AreEqual("", e.Status.Detail);
|
| + Console.WriteLine("Passed!");
|
| + }
|
| +
|
| + private static Payload CreateZerosPayload(int size)
|
| + {
|
| + return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
|
| + }
|
| +
|
| + // extracts the client_email field from service account file used for auth test cases
|
| + private static string GetEmailFromServiceAccountFile()
|
| + {
|
| + string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
|
| + Assert.IsNotNull(keyFile);
|
| +
|
| + var jobject = JObject.Parse(File.ReadAllText(keyFile));
|
| + string email = jobject.GetValue("client_email").Value<string>();
|
| + Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
|
| + return email;
|
| + }
|
| +
|
| + private static Metadata CreateTestMetadata()
|
| + {
|
| + return new Metadata
|
| + {
|
| + {"x-grpc-test-echo-initial", "test_initial_metadata_value"},
|
| + {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}}
|
| + };
|
| + }
|
| + }
|
| +}
|
|
|