| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 | 
							- #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.TestServiceClientBase client)
 
-         {
 
-             Console.WriteLine("running empty_unary");
 
-             var response = client.EmptyCall(new Empty());
 
-             Assert.IsNotNull(response);
 
-             Console.WriteLine("Passed!");
 
-         }
 
-         public static void RunLargeUnary(TestService.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.TestServiceClientBase 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.UnimplementedServiceClientBase 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}}
 
-             };
 
-         }
 
-     }
 
- }
 
 
  |