From b26972fab46cb8ef26945372b1f26942cd41972d Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Thu, 3 Sep 2015 17:47:14 -0700
Subject: [PATCH] update the interop tests based on spec

---
 .../Grpc.IntegrationTesting.csproj            |   3 +
 .../Grpc.IntegrationTesting/InteropClient.cs  | 233 ++++++------------
 .../Grpc.IntegrationTesting/InteropServer.cs  |  82 ++----
 .../Grpc.IntegrationTesting/packages.config   |   1 +
 4 files changed, 105 insertions(+), 214 deletions(-)

diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index a5945be922..a0bcf431f7 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -42,6 +42,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
     </Reference>
+    <Reference Include="CommandLine">
+      <HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
+    </Reference>
     <Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 8343e54122..830206bea2 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -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,30 @@ 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();
+            string accessToken = await credential.GetAccessTokenForRequestAsync();
+            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 +488,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;
-        }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index 718278f30a..513f8722d6 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -37,6 +37,9 @@ using System.Diagnostics;
 using System.IO;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
+
+using CommandLine;
+using CommandLine.Text;
 using Grpc.Core;
 using Grpc.Core.Utils;
 using Grpc.Testing;
@@ -48,9 +51,24 @@ namespace Grpc.IntegrationTesting
     {
         private class ServerOptions
         {
-            public bool help;
-            public int? port = 8070;
-            public bool useTls;
+            [Option("port", DefaultValue = 8070)]
+            public int Port { get; set; }
+
+            [Option("use_tls")]
+            public bool UseTls { get; set; }
+
+            [HelpOption]
+            public string GetUsage()
+            {
+                var help = new HelpText
+                {
+                    Heading = "gRPC C# interop testing server",
+                    AddDashesToOption = true
+                };
+                help.AddPreOptionsLine("Usage:");
+                help.AddOptions(this);
+                return help;
+            }
         }
 
         ServerOptions options;
@@ -62,22 +80,9 @@ namespace Grpc.IntegrationTesting
 
         public static void Run(string[] args)
         {
-            Console.WriteLine("gRPC C# interop testing server");
-            ServerOptions options = ParseArguments(args);
-
-            if (!options.port.HasValue)
-            {
-                Console.WriteLine("Missing required argument.");
-                Console.WriteLine();
-                options.help = true;
-            }
-
-            if (options.help)
+            var options = new ServerOptions();
+            if (!Parser.Default.ParseArguments(args, options))
             {
-                Console.WriteLine("Usage:");
-                Console.WriteLine("  --port=PORT");
-                Console.WriteLine("  --use_tls=BOOLEAN");
-                Console.WriteLine();
                 Environment.Exit(1);
             }
 
@@ -93,54 +98,19 @@ namespace Grpc.IntegrationTesting
             };
 
             string host = "0.0.0.0";
-            int port = options.port.Value;
-            if (options.useTls)
+            int port = options.Port;
+            if (options.UseTls)
             {
                 server.Ports.Add(host, port, TestCredentials.CreateTestServerCredentials());
             }
             else
             {
-                server.Ports.Add(host, options.port.Value, ServerCredentials.Insecure);
+                server.Ports.Add(host, options.Port, ServerCredentials.Insecure);
             }
             Console.WriteLine("Running server on " + string.Format("{0}:{1}", host, port));
             server.Start();
 
             server.ShutdownTask.Wait();
         }
-
-        private static ServerOptions ParseArguments(string[] args)
-        {
-            var options = new ServerOptions();
-            foreach (string arg in args)
-            {
-                ParseArgument(arg, options);
-                if (options.help)
-                {
-                    break;
-                }
-            }
-            return options;
-        }
-
-        private static void ParseArgument(string arg, ServerOptions options)
-        {
-            Match match;
-            match = Regex.Match(arg, "--port=(.*)");
-            if (match.Success)
-            {
-                options.port = int.Parse(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;
-            }
-
-            Console.WriteLine(string.Format("Unrecognized argument \"{0}\"", arg));
-            options.help = true;
-        }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 8dfded1964..bdb3dadf44 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
+  <package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
   <package id="Google.Apis.Auth" version="1.9.3" targetFramework="net45" />
   <package id="Google.Apis.Core" version="1.9.3" targetFramework="net45" />
   <package id="Google.Protobuf" version="3.0.0-alpha4" targetFramework="net45" />
-- 
GitLab