|  | @@ -37,6 +37,7 @@ using System.Text.RegularExpressions;
 | 
	
		
			
				|  |  |  using System.Threading;
 | 
	
		
			
				|  |  |  using System.Threading.Tasks;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +using CommandLine;
 | 
	
		
			
				|  |  |  using Google.Apis.Auth.OAuth2;
 | 
	
		
			
				|  |  |  using Google.Protobuf;
 | 
	
		
			
				|  |  |  using Grpc.Auth;
 | 
	
	
		
			
				|  | @@ -44,25 +45,54 @@ using Grpc.Core;
 | 
	
		
			
				|  |  |  using Grpc.Core.Utils;
 | 
	
		
			
				|  |  |  using Grpc.Testing;
 | 
	
		
			
				|  |  |  using NUnit.Framework;
 | 
	
		
			
				|  |  | +using CommandLine.Text;
 | 
	
		
			
				|  |  | +using System.IO;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      public class InteropClient
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        private const string ServiceAccountUser = "155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk@developer.gserviceaccount.com";
 | 
	
		
			
				|  |  | -        private const string ComputeEngineUser = "155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel@developer.gserviceaccount.com";
 | 
	
		
			
				|  |  | -        private const string AuthScope = "https://www.googleapis.com/auth/xapi.zoo";
 | 
	
		
			
				|  |  | -        private const string AuthScopeResponse = "xapi.zoo";
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          private class ClientOptions
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            public bool help;
 | 
	
		
			
				|  |  | -            public string serverHost = "127.0.0.1";
 | 
	
		
			
				|  |  | -            public string serverHostOverride = TestCredentials.DefaultHostOverride;
 | 
	
		
			
				|  |  | -            public int? serverPort;
 | 
	
		
			
				|  |  | -            public string testCase = "large_unary";
 | 
	
		
			
				|  |  | -            public bool useTls;
 | 
	
		
			
				|  |  | -            public bool useTestCa;
 | 
	
		
			
				|  |  | +            [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; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            [Option("use_tls")]
 | 
	
		
			
				|  |  | +            public bool UseTls { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            [Option("use_test_ca")]
 | 
	
		
			
				|  |  | +            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;
 | 
	
	
		
			
				|  | @@ -74,26 +104,9 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          public static void Run(string[] args)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            Console.WriteLine("gRPC C# interop testing client");
 | 
	
		
			
				|  |  | -            ClientOptions options = ParseArguments(args);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (options.serverHost == null || !options.serverPort.HasValue || options.testCase == null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Console.WriteLine("Missing required argument.");
 | 
	
		
			
				|  |  | -                Console.WriteLine();
 | 
	
		
			
				|  |  | -                options.help = true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (options.help)
 | 
	
		
			
				|  |  | +            var options = new ClientOptions();
 | 
	
		
			
				|  |  | +            if (!Parser.Default.ParseArguments(args, options))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                Console.WriteLine("Usage:");
 | 
	
		
			
				|  |  | -                Console.WriteLine("  --server_host=HOSTNAME");
 | 
	
		
			
				|  |  | -                Console.WriteLine("  --server_host_override=HOSTNAME");
 | 
	
		
			
				|  |  | -                Console.WriteLine("  --server_port=PORT");
 | 
	
		
			
				|  |  | -                Console.WriteLine("  --test_case=TESTCASE");
 | 
	
		
			
				|  |  | -                Console.WriteLine("  --use_tls=BOOLEAN");
 | 
	
		
			
				|  |  | -                Console.WriteLine("  --use_test_ca=BOOLEAN");
 | 
	
		
			
				|  |  | -                Console.WriteLine();
 | 
	
		
			
				|  |  |                  Environment.Exit(1);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -103,30 +116,27 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private async Task Run()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            Credentials credentials = null;
 | 
	
		
			
				|  |  | -            if (options.useTls)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                credentials = TestCredentials.CreateTestClientCredentials(options.useTestCa);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +            var credentials = options.UseTls ? TestCredentials.CreateTestClientCredentials(options.UseTestCa) : Credentials.Insecure;
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  |              List<ChannelOption> channelOptions = null;
 | 
	
		
			
				|  |  | -            if (!string.IsNullOrEmpty(options.serverHostOverride))
 | 
	
		
			
				|  |  | +            if (!string.IsNullOrEmpty(options.ServerHostOverride))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  channelOptions = new List<ChannelOption>
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    new ChannelOption(ChannelOptions.SslTargetNameOverride, options.serverHostOverride)
 | 
	
		
			
				|  |  | +                    new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride)
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            var channel = new Channel(options.serverHost, options.serverPort.Value, credentials, channelOptions);
 | 
	
		
			
				|  |  | +            Console.WriteLine(options.ServerHost);
 | 
	
		
			
				|  |  | +            Console.WriteLine(options.ServerPort);
 | 
	
		
			
				|  |  | +            var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
 | 
	
		
			
				|  |  |              TestService.TestServiceClient client = new TestService.TestServiceClient(channel);
 | 
	
		
			
				|  |  | -            await RunTestCaseAsync(options.testCase, client);
 | 
	
		
			
				|  |  | +            await RunTestCaseAsync(client, options);
 | 
	
		
			
				|  |  |              channel.ShutdownAsync().Wait();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private async Task RunTestCaseAsync(string testCase, TestService.TestServiceClient client)
 | 
	
		
			
				|  |  | +        private async Task RunTestCaseAsync(TestService.TestServiceClient client, ClientOptions options)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            switch (testCase)
 | 
	
		
			
				|  |  | +            switch (options.TestCase)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  case "empty_unary":
 | 
	
		
			
				|  |  |                      RunEmptyUnary(client);
 | 
	
	
		
			
				|  | @@ -146,20 +156,17 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |                  case "empty_stream":
 | 
	
		
			
				|  |  |                      await RunEmptyStreamAsync(client);
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  | -                case "service_account_creds":
 | 
	
		
			
				|  |  | -                    await RunServiceAccountCredsAsync(client);
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  |                  case "compute_engine_creds":
 | 
	
		
			
				|  |  | -                    await RunComputeEngineCredsAsync(client);
 | 
	
		
			
				|  |  | +                    await RunComputeEngineCredsAsync(client, options.DefaultServiceAccount, options.OAuthScope);
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  case "jwt_token_creds":
 | 
	
		
			
				|  |  | -                    await RunJwtTokenCredsAsync(client);
 | 
	
		
			
				|  |  | +                    await RunJwtTokenCredsAsync(client, options.DefaultServiceAccount);
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  case "oauth2_auth_token":
 | 
	
		
			
				|  |  | -                    await RunOAuth2AuthTokenAsync(client);
 | 
	
		
			
				|  |  | +                    await RunOAuth2AuthTokenAsync(client, options.DefaultServiceAccount, options.OAuthScope);
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  case "per_rpc_creds":
 | 
	
		
			
				|  |  | -                    await RunPerRpcCredsAsync(client);
 | 
	
		
			
				|  |  | +                    await RunPerRpcCredsAsync(client, options.DefaultServiceAccount);
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  case "cancel_after_begin":
 | 
	
		
			
				|  |  |                      await RunCancelAfterBeginAsync(client);
 | 
	
	
		
			
				|  | @@ -174,7 +181,7 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |                      RunBenchmarkEmptyUnary(client);
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  default:
 | 
	
		
			
				|  |  | -                    throw new ArgumentException("Unknown test case " + testCase);
 | 
	
		
			
				|  |  | +                    throw new ArgumentException("Unknown test case " + options.TestCase);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -313,32 +320,7 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |              Console.WriteLine("Passed!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public static async Task RunServiceAccountCredsAsync(TestService.TestServiceClient client)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            Console.WriteLine("running service_account_creds");
 | 
	
		
			
				|  |  | -            var credential = await GoogleCredential.GetApplicationDefaultAsync();
 | 
	
		
			
				|  |  | -            credential = credential.CreateScoped(new[] { AuthScope });
 | 
	
		
			
				|  |  | -            client.HeaderInterceptor = AuthInterceptors.FromCredential(credential);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            var request = new SimpleRequest
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                ResponseType = PayloadType.COMPRESSABLE,
 | 
	
		
			
				|  |  | -                ResponseSize = 314159,
 | 
	
		
			
				|  |  | -                Payload = CreateZerosPayload(271828),
 | 
	
		
			
				|  |  | -                FillUsername = true,
 | 
	
		
			
				|  |  | -                FillOauthScope = true
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            var response = client.UnaryCall(request);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(314159, response.Payload.Body.Length);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(AuthScopeResponse, response.OauthScope);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(ServiceAccountUser, response.Username);
 | 
	
		
			
				|  |  | -            Console.WriteLine("Passed!");
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public static async Task RunComputeEngineCredsAsync(TestService.TestServiceClient client)
 | 
	
		
			
				|  |  | +        public static async Task RunComputeEngineCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              Console.WriteLine("running compute_engine_creds");
 | 
	
		
			
				|  |  |              var credential = await GoogleCredential.GetApplicationDefaultAsync();
 | 
	
	
		
			
				|  | @@ -358,16 +340,16 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
 | 
	
		
			
				|  |  |              Assert.AreEqual(314159, response.Payload.Body.Length);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(AuthScopeResponse, response.OauthScope);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(ComputeEngineUser, response.Username);
 | 
	
		
			
				|  |  | +            Assert.False(string.IsNullOrEmpty(response.OauthScope));
 | 
	
		
			
				|  |  | +            Assert.True(oauthScope.Contains(response.OauthScope));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(defaultServiceAccount, response.Username);
 | 
	
		
			
				|  |  |              Console.WriteLine("Passed!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public static async Task RunJwtTokenCredsAsync(TestService.TestServiceClient client)
 | 
	
		
			
				|  |  | +        public static async Task RunJwtTokenCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              Console.WriteLine("running jwt_token_creds");
 | 
	
		
			
				|  |  |              var credential = await GoogleCredential.GetApplicationDefaultAsync();
 | 
	
		
			
				|  |  | -            // check this a credential with scope support, but don't add the scope.
 | 
	
		
			
				|  |  |              Assert.IsTrue(credential.IsCreateScopedRequired);
 | 
	
		
			
				|  |  |              client.HeaderInterceptor = AuthInterceptors.FromCredential(credential);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -377,21 +359,20 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |                  ResponseSize = 314159,
 | 
	
		
			
				|  |  |                  Payload = CreateZerosPayload(271828),
 | 
	
		
			
				|  |  |                  FillUsername = true,
 | 
	
		
			
				|  |  | -                FillOauthScope = true
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var response = client.UnaryCall(request);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
 | 
	
		
			
				|  |  |              Assert.AreEqual(314159, response.Payload.Body.Length);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(ServiceAccountUser, response.Username);
 | 
	
		
			
				|  |  | +            Assert.AreEqual(defaultServiceAccount, response.Username);
 | 
	
		
			
				|  |  |              Console.WriteLine("Passed!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client)
 | 
	
		
			
				|  |  | +        public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              Console.WriteLine("running oauth2_auth_token");
 | 
	
		
			
				|  |  | -            ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope });
 | 
	
		
			
				|  |  | +            ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
 | 
	
		
			
				|  |  |              string oauth2Token = await credential.GetAccessTokenForRequestAsync();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              client.HeaderInterceptor = AuthInterceptors.FromAccessToken(oauth2Token);
 | 
	
	
		
			
				|  | @@ -404,31 +385,32 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var response = client.UnaryCall(request);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Assert.AreEqual(AuthScopeResponse, response.OauthScope);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(ServiceAccountUser, response.Username);
 | 
	
		
			
				|  |  | +            Assert.False(string.IsNullOrEmpty(response.OauthScope));
 | 
	
		
			
				|  |  | +            Assert.True(oauthScope.Contains(response.OauthScope));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(defaultServiceAccount, response.Username);
 | 
	
		
			
				|  |  |              Console.WriteLine("Passed!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client)
 | 
	
		
			
				|  |  | +        public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              Console.WriteLine("running per_rpc_creds");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope });
 | 
	
		
			
				|  |  | -            string oauth2Token = await credential.GetAccessTokenForRequestAsync();
 | 
	
		
			
				|  |  | -            var headerInterceptor = AuthInterceptors.FromAccessToken(oauth2Token);
 | 
	
		
			
				|  |  | +            ITokenAccess credential = await GoogleCredential.GetApplicationDefaultAsync();
 | 
	
		
			
				|  |  | +            // TODO: currently there's no way how to obtain AuthURI for JWT per-rpc creds.
 | 
	
		
			
				|  |  | +            string authUri = "https://grpc-test.sandbox.google.com/grpc.testing.TestService";
 | 
	
		
			
				|  |  | +            string accessToken = await credential.GetAccessTokenForRequestAsync(authUri);
 | 
	
		
			
				|  |  | +            var headerInterceptor = AuthInterceptors.FromAccessToken(accessToken);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var request = new SimpleRequest
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  FillUsername = true,
 | 
	
		
			
				|  |  | -                FillOauthScope = true
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var headers = new Metadata();
 | 
	
		
			
				|  |  |              headerInterceptor(null, "", headers);
 | 
	
		
			
				|  |  |              var response = client.UnaryCall(request, headers: headers);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Assert.AreEqual(AuthScopeResponse, response.OauthScope);
 | 
	
		
			
				|  |  | -            Assert.AreEqual(ServiceAccountUser, response.Username);
 | 
	
		
			
				|  |  | +            Assert.AreEqual(defaultServiceAccount, response.Username);
 | 
	
		
			
				|  |  |              Console.WriteLine("Passed!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -508,68 +490,5 @@ namespace Grpc.IntegrationTesting
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private static ClientOptions ParseArguments(string[] args)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var options = new ClientOptions();
 | 
	
		
			
				|  |  | -            foreach (string arg in args)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                ParseArgument(arg, options);
 | 
	
		
			
				|  |  | -                if (options.help)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            return options;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private static void ParseArgument(string arg, ClientOptions options)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            Match match;
 | 
	
		
			
				|  |  | -            match = Regex.Match(arg, "--server_host=(.*)");
 | 
	
		
			
				|  |  | -            if (match.Success)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                options.serverHost = match.Groups[1].Value.Trim();
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            match = Regex.Match(arg, "--server_host_override=(.*)");
 | 
	
		
			
				|  |  | -            if (match.Success)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                options.serverHostOverride = match.Groups[1].Value.Trim();
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            match = Regex.Match(arg, "--server_port=(.*)");
 | 
	
		
			
				|  |  | -            if (match.Success)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                options.serverPort = int.Parse(match.Groups[1].Value.Trim());
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            match = Regex.Match(arg, "--test_case=(.*)");
 | 
	
		
			
				|  |  | -            if (match.Success)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                options.testCase = match.Groups[1].Value.Trim();
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            match = Regex.Match(arg, "--use_tls=(.*)");
 | 
	
		
			
				|  |  | -            if (match.Success)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                options.useTls = bool.Parse(match.Groups[1].Value.Trim());
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            match = Regex.Match(arg, "--use_test_ca=(.*)");
 | 
	
		
			
				|  |  | -            if (match.Success)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                options.useTestCa = bool.Parse(match.Groups[1].Value.Trim());
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            Console.WriteLine(string.Format("Unrecognized argument \"{0}\"", arg));
 | 
	
		
			
				|  |  | -            options.help = true;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |