update the interop tests based on spec

pull/3263/head
Jan Tattermusch 9 years ago
parent 1beb02058a
commit b26972fab4
  1. 3
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  2. 233
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  3. 82
      src/csharp/Grpc.IntegrationTesting/InteropServer.cs
  4. 1
      src/csharp/Grpc.IntegrationTesting/packages.config

@ -42,6 +42,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath> <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference> </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"> <Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath> <HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>

@ -37,6 +37,7 @@ using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommandLine;
using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2;
using Google.Protobuf; using Google.Protobuf;
using Grpc.Auth; using Grpc.Auth;
@ -44,25 +45,54 @@ using Grpc.Core;
using Grpc.Core.Utils; using Grpc.Core.Utils;
using Grpc.Testing; using Grpc.Testing;
using NUnit.Framework; using NUnit.Framework;
using CommandLine.Text;
using System.IO;
namespace Grpc.IntegrationTesting namespace Grpc.IntegrationTesting
{ {
public class InteropClient 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 private class ClientOptions
{ {
public bool help; [Option("server_host", DefaultValue = "127.0.0.1")]
public string serverHost = "127.0.0.1"; public string ServerHost { get; set; }
public string serverHostOverride = TestCredentials.DefaultHostOverride;
public int? serverPort; [Option("server_host_override", DefaultValue = TestCredentials.DefaultHostOverride)]
public string testCase = "large_unary"; public string ServerHostOverride { get; set; }
public bool useTls;
public bool useTestCa; [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; ClientOptions options;
@ -74,26 +104,9 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args) public static void Run(string[] args)
{ {
Console.WriteLine("gRPC C# interop testing client"); var options = new ClientOptions();
ClientOptions options = ParseArguments(args); if (!Parser.Default.ParseArguments(args, options))
if (options.serverHost == null || !options.serverPort.HasValue || options.testCase == null)
{
Console.WriteLine("Missing required argument.");
Console.WriteLine();
options.help = true;
}
if (options.help)
{ {
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); Environment.Exit(1);
} }
@ -103,30 +116,27 @@ namespace Grpc.IntegrationTesting
private async Task Run() private async Task Run()
{ {
Credentials credentials = null; var credentials = options.UseTls ? TestCredentials.CreateTestClientCredentials(options.UseTestCa) : Credentials.Insecure;
if (options.useTls)
{
credentials = TestCredentials.CreateTestClientCredentials(options.useTestCa);
}
List<ChannelOption> channelOptions = null; List<ChannelOption> channelOptions = null;
if (!string.IsNullOrEmpty(options.serverHostOverride)) if (!string.IsNullOrEmpty(options.ServerHostOverride))
{ {
channelOptions = new List<ChannelOption> channelOptions = new List<ChannelOption>
{ {
new ChannelOption(ChannelOptions.SslTargetNameOverride, options.serverHostOverride) new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride)
}; };
} }
Console.WriteLine(options.ServerHost);
var channel = new Channel(options.serverHost, options.serverPort.Value, credentials, channelOptions); Console.WriteLine(options.ServerPort);
var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
TestService.TestServiceClient client = new TestService.TestServiceClient(channel); TestService.TestServiceClient client = new TestService.TestServiceClient(channel);
await RunTestCaseAsync(options.testCase, client); await RunTestCaseAsync(client, options);
channel.ShutdownAsync().Wait(); 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": case "empty_unary":
RunEmptyUnary(client); RunEmptyUnary(client);
@ -146,20 +156,17 @@ namespace Grpc.IntegrationTesting
case "empty_stream": case "empty_stream":
await RunEmptyStreamAsync(client); await RunEmptyStreamAsync(client);
break; break;
case "service_account_creds":
await RunServiceAccountCredsAsync(client);
break;
case "compute_engine_creds": case "compute_engine_creds":
await RunComputeEngineCredsAsync(client); await RunComputeEngineCredsAsync(client, options.DefaultServiceAccount, options.OAuthScope);
break; break;
case "jwt_token_creds": case "jwt_token_creds":
await RunJwtTokenCredsAsync(client); await RunJwtTokenCredsAsync(client, options.DefaultServiceAccount);
break; break;
case "oauth2_auth_token": case "oauth2_auth_token":
await RunOAuth2AuthTokenAsync(client); await RunOAuth2AuthTokenAsync(client, options.DefaultServiceAccount, options.OAuthScope);
break; break;
case "per_rpc_creds": case "per_rpc_creds":
await RunPerRpcCredsAsync(client); await RunPerRpcCredsAsync(client, options.DefaultServiceAccount);
break; break;
case "cancel_after_begin": case "cancel_after_begin":
await RunCancelAfterBeginAsync(client); await RunCancelAfterBeginAsync(client);
@ -174,7 +181,7 @@ namespace Grpc.IntegrationTesting
RunBenchmarkEmptyUnary(client); RunBenchmarkEmptyUnary(client);
break; break;
default: 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!"); Console.WriteLine("Passed!");
} }
public static async Task RunServiceAccountCredsAsync(TestService.TestServiceClient client) public static async Task RunComputeEngineCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope)
{
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)
{ {
Console.WriteLine("running compute_engine_creds"); Console.WriteLine("running compute_engine_creds");
var credential = await GoogleCredential.GetApplicationDefaultAsync(); var credential = await GoogleCredential.GetApplicationDefaultAsync();
@ -358,16 +340,16 @@ namespace Grpc.IntegrationTesting
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
Assert.AreEqual(314159, response.Payload.Body.Length); Assert.AreEqual(314159, response.Payload.Body.Length);
Assert.AreEqual(AuthScopeResponse, response.OauthScope); Assert.False(string.IsNullOrEmpty(response.OauthScope));
Assert.AreEqual(ComputeEngineUser, response.Username); Assert.True(oauthScope.Contains(response.OauthScope));
Assert.AreEqual(defaultServiceAccount, response.Username);
Console.WriteLine("Passed!"); 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"); Console.WriteLine("running jwt_token_creds");
var credential = await GoogleCredential.GetApplicationDefaultAsync(); var credential = await GoogleCredential.GetApplicationDefaultAsync();
// check this a credential with scope support, but don't add the scope.
Assert.IsTrue(credential.IsCreateScopedRequired); Assert.IsTrue(credential.IsCreateScopedRequired);
client.HeaderInterceptor = AuthInterceptors.FromCredential(credential); client.HeaderInterceptor = AuthInterceptors.FromCredential(credential);
@ -377,21 +359,20 @@ namespace Grpc.IntegrationTesting
ResponseSize = 314159, ResponseSize = 314159,
Payload = CreateZerosPayload(271828), Payload = CreateZerosPayload(271828),
FillUsername = true, FillUsername = true,
FillOauthScope = true
}; };
var response = client.UnaryCall(request); var response = client.UnaryCall(request);
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
Assert.AreEqual(314159, response.Payload.Body.Length); Assert.AreEqual(314159, response.Payload.Body.Length);
Assert.AreEqual(ServiceAccountUser, response.Username); Assert.AreEqual(defaultServiceAccount, response.Username);
Console.WriteLine("Passed!"); 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"); 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(); string oauth2Token = await credential.GetAccessTokenForRequestAsync();
client.HeaderInterceptor = AuthInterceptors.FromAccessToken(oauth2Token); client.HeaderInterceptor = AuthInterceptors.FromAccessToken(oauth2Token);
@ -404,31 +385,30 @@ namespace Grpc.IntegrationTesting
var response = client.UnaryCall(request); var response = client.UnaryCall(request);
Assert.AreEqual(AuthScopeResponse, response.OauthScope); Assert.False(string.IsNullOrEmpty(response.OauthScope));
Assert.AreEqual(ServiceAccountUser, response.Username); Assert.True(oauthScope.Contains(response.OauthScope));
Assert.AreEqual(defaultServiceAccount, response.Username);
Console.WriteLine("Passed!"); 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"); Console.WriteLine("running per_rpc_creds");
ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope }); ITokenAccess credential = await GoogleCredential.GetApplicationDefaultAsync();
string oauth2Token = await credential.GetAccessTokenForRequestAsync(); string accessToken = await credential.GetAccessTokenForRequestAsync();
var headerInterceptor = AuthInterceptors.FromAccessToken(oauth2Token); var headerInterceptor = AuthInterceptors.FromAccessToken(accessToken);
var request = new SimpleRequest var request = new SimpleRequest
{ {
FillUsername = true, FillUsername = true,
FillOauthScope = true
}; };
var headers = new Metadata(); var headers = new Metadata();
headerInterceptor(null, "", headers); headerInterceptor(null, "", headers);
var response = client.UnaryCall(request, headers: headers); var response = client.UnaryCall(request, headers: headers);
Assert.AreEqual(AuthScopeResponse, response.OauthScope); Assert.AreEqual(defaultServiceAccount, response.Username);
Assert.AreEqual(ServiceAccountUser, response.Username);
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }
@ -508,68 +488,5 @@ namespace Grpc.IntegrationTesting
{ {
return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; 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;
}
} }
} }

@ -37,6 +37,9 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using Grpc.Core; using Grpc.Core;
using Grpc.Core.Utils; using Grpc.Core.Utils;
using Grpc.Testing; using Grpc.Testing;
@ -48,9 +51,24 @@ namespace Grpc.IntegrationTesting
{ {
private class ServerOptions private class ServerOptions
{ {
public bool help; [Option("port", DefaultValue = 8070)]
public int? port = 8070; public int Port { get; set; }
public bool useTls;
[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; ServerOptions options;
@ -62,22 +80,9 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args) public static void Run(string[] args)
{ {
Console.WriteLine("gRPC C# interop testing server"); var options = new ServerOptions();
ServerOptions options = ParseArguments(args); if (!Parser.Default.ParseArguments(args, options))
if (!options.port.HasValue)
{
Console.WriteLine("Missing required argument.");
Console.WriteLine();
options.help = true;
}
if (options.help)
{ {
Console.WriteLine("Usage:");
Console.WriteLine(" --port=PORT");
Console.WriteLine(" --use_tls=BOOLEAN");
Console.WriteLine();
Environment.Exit(1); Environment.Exit(1);
} }
@ -93,54 +98,19 @@ namespace Grpc.IntegrationTesting
}; };
string host = "0.0.0.0"; string host = "0.0.0.0";
int port = options.port.Value; int port = options.Port;
if (options.useTls) if (options.UseTls)
{ {
server.Ports.Add(host, port, TestCredentials.CreateTestServerCredentials()); server.Ports.Add(host, port, TestCredentials.CreateTestServerCredentials());
} }
else 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)); Console.WriteLine("Running server on " + string.Format("{0}:{1}", host, port));
server.Start(); server.Start();
server.ShutdownTask.Wait(); 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;
}
} }
} }

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" /> <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.Auth" version="1.9.3" targetFramework="net45" />
<package id="Google.Apis.Core" 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" /> <package id="Google.Protobuf" version="3.0.0-alpha4" targetFramework="net45" />

Loading…
Cancel
Save