aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp')
-rw-r--r--src/csharp/Grpc.Core.Tests/CallOptionsTest.cs16
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs109
-rw-r--r--src/csharp/Grpc.Core/CallOptions.cs51
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs13
-rw-r--r--src/csharp/Grpc.Core/Version.cs3
-rw-r--r--src/csharp/Grpc.Core/VersionInfo.cs11
-rw-r--r--src/csharp/Grpc.Examples/MathGrpc.cs192
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthGrpc.cs62
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj60
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs45
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs11
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Control.cs160
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj3
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs3
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Metrics.cs452
-rw-r--r--src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs242
-rw-r--r--src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs316
-rw-r--r--src/csharp/Grpc.IntegrationTesting/StressTestClient.cs318
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestGrpc.cs344
-rw-r--r--src/csharp/Grpc.sln8
-rw-r--r--src/csharp/buildall.bat6
-rwxr-xr-xsrc/csharp/generate_proto_csharp.sh2
23 files changed, 2261 insertions, 169 deletions
diff --git a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
index a3a613be74..99a2d47e6e 100644
--- a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
+++ b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
@@ -54,10 +54,20 @@ namespace Grpc.Core.Tests
var deadline = DateTime.UtcNow;
Assert.AreEqual(deadline, options.WithDeadline(deadline).Deadline.Value);
- var token = new CancellationTokenSource().Token;
- Assert.AreEqual(token, options.WithCancellationToken(token).CancellationToken);
+ var cancellationToken = new CancellationTokenSource().Token;
+ Assert.AreEqual(cancellationToken, options.WithCancellationToken(cancellationToken).CancellationToken);
+
+ var writeOptions = new WriteOptions();
+ Assert.AreSame(writeOptions, options.WithWriteOptions(writeOptions).WriteOptions);
+
+ var propagationToken = new ContextPropagationToken(CallSafeHandle.NullInstance, DateTime.UtcNow,
+ CancellationToken.None, ContextPropagationOptions.Default);
+ Assert.AreSame(propagationToken, options.WithPropagationToken(propagationToken).PropagationToken);
+
+ var credentials = new FakeCallCredentials();
+ Assert.AreSame(credentials, options.WithCredentials(credentials).Credentials);
- // Change original instance is unchanged.
+ // Check that the original instance is unchanged.
Assert.IsNull(options.Headers);
Assert.IsNull(options.Deadline);
Assert.AreEqual(CancellationToken.None, options.CancellationToken);
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
index 60530d3250..a678e4dafe 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
@@ -64,28 +64,115 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
- public void AsyncUnary_CompletionSuccess()
+ public void AsyncUnary_CanBeStartedOnlyOnce()
+ {
+ asyncCall.UnaryCallAsync("request1");
+ Assert.Throws(typeof(InvalidOperationException),
+ () => asyncCall.UnaryCallAsync("abc"));
+ }
+
+ [Test]
+ public void AsyncUnary_StreamingOperationsNotAllowed()
+ {
+ asyncCall.UnaryCallAsync("request1");
+ Assert.Throws(typeof(InvalidOperationException),
+ () => asyncCall.StartReadMessage((x,y) => {}));
+ Assert.Throws(typeof(InvalidOperationException),
+ () => asyncCall.StartSendMessage("abc", new WriteFlags(), (x,y) => {}));
+ }
+
+ [Test]
+ public void AsyncUnary_Success()
+ {
+ var resultTask = asyncCall.UnaryCallAsync("request1");
+ fakeCall.UnaryResponseClientHandler(true,
+ new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
+ CreateResponsePayload(),
+ new Metadata());
+
+ AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
+ }
+
+ [Test]
+ public void AsyncUnary_NonSuccessStatusCode()
+ {
+ var resultTask = asyncCall.UnaryCallAsync("request1");
+ fakeCall.UnaryResponseClientHandler(true,
+ CreateClientSideStatus(StatusCode.InvalidArgument),
+ CreateResponsePayload(),
+ new Metadata());
+
+ AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument);
+ }
+
+ [Test]
+ public void AsyncUnary_NullResponsePayload()
+ {
+ var resultTask = asyncCall.UnaryCallAsync("request1");
+ fakeCall.UnaryResponseClientHandler(true,
+ new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
+ null,
+ new Metadata());
+
+ // failure to deserialize will result in InvalidArgument status.
+ AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
+ }
+
+ [Test]
+ public void ClientStreaming_NoRequest_Success()
+ {
+ var resultTask = asyncCall.ClientStreamingCallAsync();
+ fakeCall.UnaryResponseClientHandler(true,
+ new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
+ CreateResponsePayload(),
+ new Metadata());
+
+ AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
+ }
+
+ [Test]
+ public void ClientStreaming_NoRequest_NonSuccessStatusCode()
+ {
+ var resultTask = asyncCall.ClientStreamingCallAsync();
+ fakeCall.UnaryResponseClientHandler(true,
+ CreateClientSideStatus(StatusCode.InvalidArgument),
+ CreateResponsePayload(),
+ new Metadata());
+
+ AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument);
+ }
+
+ ClientSideStatus CreateClientSideStatus(StatusCode statusCode)
+ {
+ return new ClientSideStatus(new Status(statusCode, ""), new Metadata());
+ }
+
+ byte[] CreateResponsePayload()
+ {
+ return Marshallers.StringMarshaller.Serializer("response1");
+ }
+
+ static void AssertUnaryResponseSuccess(AsyncCall<string, string> asyncCall, FakeNativeCall fakeCall, Task<string> resultTask)
{
- var resultTask = asyncCall.UnaryCallAsync("abc");
- fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), new byte[] { 1, 2, 3 }, new Metadata());
Assert.IsTrue(resultTask.IsCompleted);
Assert.IsTrue(fakeCall.IsDisposed);
+
Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus());
+ Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count);
+ Assert.AreEqual(0, asyncCall.GetTrailers().Count);
+ Assert.AreEqual("response1", resultTask.Result);
}
- [Test]
- public void AsyncUnary_CompletionFailure()
+ static void AssertUnaryResponseError(AsyncCall<string, string> asyncCall, FakeNativeCall fakeCall, Task<string> resultTask, StatusCode expectedStatusCode)
{
- var resultTask = asyncCall.UnaryCallAsync("abc");
- fakeCall.UnaryResponseClientHandler(false, new ClientSideStatus(new Status(StatusCode.Internal, ""), null), new byte[] { 1, 2, 3 }, new Metadata());
-
Assert.IsTrue(resultTask.IsCompleted);
Assert.IsTrue(fakeCall.IsDisposed);
- Assert.AreEqual(StatusCode.Internal, asyncCall.GetStatus().StatusCode);
- Assert.IsNull(asyncCall.GetTrailers());
+ Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode);
var ex = Assert.ThrowsAsync<RpcException>(async () => await resultTask);
- Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
+ Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode);
+ Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count);
+ Assert.AreEqual(0, asyncCall.GetTrailers().Count);
}
internal class FakeNativeCall : INativeCall
diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs
index caf8210d91..9ca88849ee 100644
--- a/src/csharp/Grpc.Core/CallOptions.cs
+++ b/src/csharp/Grpc.Core/CallOptions.cs
@@ -100,10 +100,7 @@ namespace Grpc.Core
/// </summary>
public WriteOptions WriteOptions
{
- get
- {
- return this.writeOptions;
- }
+ get { return this.writeOptions; }
}
/// <summary>
@@ -111,10 +108,7 @@ namespace Grpc.Core
/// </summary>
public ContextPropagationToken PropagationToken
{
- get
- {
- return this.propagationToken;
- }
+ get { return this.propagationToken; }
}
/// <summary>
@@ -122,10 +116,7 @@ namespace Grpc.Core
/// </summary>
public CallCredentials Credentials
{
- get
- {
- return this.credentials;
- }
+ get { return this.credentials; }
}
/// <summary>
@@ -165,6 +156,42 @@ namespace Grpc.Core
}
/// <summary>
+ /// Returns new instance of <see cref="CallOptions"/> with
+ /// <c>WriteOptions</c> set to the value provided. Values of all other fields are preserved.
+ /// </summary>
+ /// <param name="writeOptions">The write options.</param>
+ public CallOptions WithWriteOptions(WriteOptions writeOptions)
+ {
+ var newOptions = this;
+ newOptions.writeOptions = writeOptions;
+ return newOptions;
+ }
+
+ /// <summary>
+ /// Returns new instance of <see cref="CallOptions"/> with
+ /// <c>PropagationToken</c> set to the value provided. Values of all other fields are preserved.
+ /// </summary>
+ /// <param name="propagationToken">The context propagation token.</param>
+ public CallOptions WithPropagationToken(ContextPropagationToken propagationToken)
+ {
+ var newOptions = this;
+ newOptions.propagationToken = propagationToken;
+ return newOptions;
+ }
+
+ /// <summary>
+ /// Returns new instance of <see cref="CallOptions"/> with
+ /// <c>Credentials</c> set to the value provided. Values of all other fields are preserved.
+ /// </summary>
+ /// <param name="credentials">The call credentials.</param>
+ public CallOptions WithCredentials(CallCredentials credentials)
+ {
+ var newOptions = this;
+ newOptions.credentials = credentials;
+ return newOptions;
+ }
+
+ /// <summary>
/// Returns a new instance of <see cref="CallOptions"/> with
/// all previously unset values set to their defaults and deadline and cancellation
/// token propagated when appropriate.
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 016e1b8587..50ba617cdb 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -409,10 +409,13 @@ namespace Grpc.Core.Internal
/// </summary>
private void HandleUnaryResponse(bool success, ClientSideStatus receivedStatus, byte[] receivedMessage, Metadata responseHeaders)
{
+ // NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
+ // success will be always set to true.
+
using (Profilers.ForCurrentThread().NewScope("AsyncCall.HandleUnaryResponse"))
{
TResponse msg = default(TResponse);
- var deserializeException = success ? TryDeserialize(receivedMessage, out msg) : null;
+ var deserializeException = TryDeserialize(receivedMessage, out msg);
lock (myLock)
{
@@ -425,14 +428,13 @@ namespace Grpc.Core.Internal
finishedStatus = receivedStatus;
ReleaseResourcesIfPossible();
-
}
responseHeadersTcs.SetResult(responseHeaders);
var status = receivedStatus.Status;
- if (!success || status.StatusCode != StatusCode.OK)
+ if (status.StatusCode != StatusCode.OK)
{
unaryResponseTcs.SetException(new RpcException(status));
return;
@@ -447,6 +449,9 @@ namespace Grpc.Core.Internal
/// </summary>
private void HandleFinished(bool success, ClientSideStatus receivedStatus)
{
+ // NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
+ // success will be always set to true.
+
lock (myLock)
{
finished = true;
@@ -457,7 +462,7 @@ namespace Grpc.Core.Internal
var status = receivedStatus.Status;
- if (!success || status.StatusCode != StatusCode.OK)
+ if (status.StatusCode != StatusCode.OK)
{
streamingCallFinishedTcs.SetException(new RpcException(status));
return;
diff --git a/src/csharp/Grpc.Core/Version.cs b/src/csharp/Grpc.Core/Version.cs
index 8a26bd8362..f5c44fd098 100644
--- a/src/csharp/Grpc.Core/Version.cs
+++ b/src/csharp/Grpc.Core/Version.cs
@@ -33,5 +33,6 @@
using System.Reflection;
-// The current version of gRPC C#.
[assembly: AssemblyVersion(Grpc.Core.VersionInfo.CurrentAssemblyVersion)]
+[assembly: AssemblyFileVersion(Grpc.Core.VersionInfo.CurrentAssemblyFileVersion)]
+[assembly: AssemblyInformationalVersion(Grpc.Core.VersionInfo.CurrentVersion)]
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index 9014a13f40..f7a9cb9c1c 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -35,13 +35,20 @@ namespace Grpc.Core
{
/// <summary>
/// Provides info about current version of gRPC.
+ /// See https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/
+ /// for rationale about assembly versioning.
/// </summary>
public static class VersionInfo
{
/// <summary>
- /// Current version of gRPC C# assemblies
+ /// Current <c>AssemblyVersion</c> attribute of gRPC C# assemblies
/// </summary>
- public const string CurrentAssemblyVersion = "0.14.0.0";
+ public const string CurrentAssemblyVersion = "1.0.0.0";
+
+ /// <summary>
+ /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
+ /// </summary>
+ public const string CurrentAssemblyFileVersion = "0.14.0.0";
/// <summary>
/// Current version of gRPC C#
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index f3bb0d1cdc..2d3034d28b 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -1,5 +1,35 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto
+// Original file comments:
+// 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.
+//
#region Designer generated code
using System;
@@ -45,56 +75,140 @@ namespace Math {
__Marshaller_Num,
__Marshaller_Num);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Math.MathReflection.Descriptor.Services[0]; }
}
- // client interface
+ /// <summary>Client for Math</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IMathClient
{
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options);
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options);
+ /// <summary>
+ /// DivMany accepts an arbitrary number of division args from the client stream
+ /// and sends back the results in the reply stream. The stream continues until
+ /// the client closes its end; the server does the same after sending all the
+ /// replies. The stream ends immediately if either end aborts.
+ /// </summary>
AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// DivMany accepts an arbitrary number of division args from the client stream
+ /// and sends back the results in the reply stream. The stream continues until
+ /// the client closes its end; the server does the same after sending all the
+ /// replies. The stream ends immediately if either end aborts.
+ /// </summary>
AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options);
+ /// <summary>
+ /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ /// generates up to limit numbers; otherwise it continues until the call is
+ /// canceled. Unlike Fib above, Fib has no final FibReply.
+ /// </summary>
AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ /// generates up to limit numbers; otherwise it continues until the call is
+ /// canceled. Unlike Fib above, Fib has no final FibReply.
+ /// </summary>
AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options);
+ /// <summary>
+ /// Sum sums a stream of numbers, returning the final result once the stream
+ /// is closed.
+ /// </summary>
AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Sum sums a stream of numbers, returning the final result once the stream
+ /// is closed.
+ /// </summary>
AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of Math</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IMath
{
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context);
+ /// <summary>
+ /// DivMany accepts an arbitrary number of division args from the client stream
+ /// and sends back the results in the reply stream. The stream continues until
+ /// the client closes its end; the server does the same after sending all the
+ /// replies. The stream ends immediately if either end aborts.
+ /// </summary>
Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context);
+ /// <summary>
+ /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ /// generates up to limit numbers; otherwise it continues until the call is
+ /// canceled. Unlike Fib above, Fib has no final FibReply.
+ /// </summary>
Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context);
+ /// <summary>
+ /// Sum sums a stream of numbers, returning the final result once the stream
+ /// is closed.
+ /// </summary>
Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of Math</summary>
public abstract class MathBase
{
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
public virtual Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// DivMany accepts an arbitrary number of division args from the client stream
+ /// and sends back the results in the reply stream. The stream continues until
+ /// the client closes its end; the server does the same after sending all the
+ /// replies. The stream ends immediately if either end aborts.
+ /// </summary>
public virtual Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ /// generates up to limit numbers; otherwise it continues until the call is
+ /// canceled. Unlike Fib above, Fib has no final FibReply.
+ /// </summary>
public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// Sum sums a stream of numbers, returning the final result once the stream
+ /// is closed.
+ /// </summary>
public virtual Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -102,8 +216,10 @@ namespace Math {
}
- // client stub
+ /// <summary>Client for Math</summary>
+ #pragma warning disable 0618
public class MathClient : ClientBase<MathClient>, IMathClient
+ #pragma warning restore 0618
{
public MathClient(Channel channel) : base(channel)
{
@@ -120,42 +236,88 @@ namespace Math {
{
}
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
public virtual global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return Div(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
public virtual global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request);
}
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return DivAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Div divides args.dividend by args.divisor and returns the quotient and
+ /// remainder.
+ /// </summary>
public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request);
}
+ /// <summary>
+ /// DivMany accepts an arbitrary number of division args from the client stream
+ /// and sends back the results in the reply stream. The stream continues until
+ /// the client closes its end; the server does the same after sending all the
+ /// replies. The stream ends immediately if either end aborts.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return DivMany(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// DivMany accepts an arbitrary number of division args from the client stream
+ /// and sends back the results in the reply stream. The stream continues until
+ /// the client closes its end; the server does the same after sending all the
+ /// replies. The stream ends immediately if either end aborts.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options);
}
+ /// <summary>
+ /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ /// generates up to limit numbers; otherwise it continues until the call is
+ /// canceled. Unlike Fib above, Fib has no final FibReply.
+ /// </summary>
public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return Fib(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ /// generates up to limit numbers; otherwise it continues until the call is
+ /// canceled. Unlike Fib above, Fib has no final FibReply.
+ /// </summary>
public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request);
}
+ /// <summary>
+ /// Sum sums a stream of numbers, returning the final result once the stream
+ /// is closed.
+ /// </summary>
public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return Sum(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Sum sums a stream of numbers, returning the final result once the stream
+ /// is closed.
+ /// </summary>
public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options);
@@ -166,8 +328,16 @@ namespace Math {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for Math</summary>
+ public static MathClient NewClient(Channel channel)
+ {
+ return new MathClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(IMath serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Div, serviceImpl.Div)
@@ -176,8 +346,10 @@ namespace Math {
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(MathBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Div, serviceImpl.Div)
@@ -186,12 +358,6 @@ namespace Math {
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
- // creates a new client
- public static MathClient NewClient(Channel channel)
- {
- return new MathClient(channel);
- }
-
}
}
#endregion
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index 72e11cca3a..967d1170be 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -1,5 +1,35 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: health.proto
+// Original file comments:
+// 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.
+//
#region Designer generated code
using System;
@@ -22,13 +52,13 @@ namespace Grpc.Health.V1 {
__Marshaller_HealthCheckRequest,
__Marshaller_HealthCheckResponse);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Health.V1.HealthReflection.Descriptor.Services[0]; }
}
- // client interface
+ /// <summary>Client for Health</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IHealthClient
{
@@ -38,14 +68,14 @@ namespace Grpc.Health.V1 {
AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of Health</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IHealth
{
Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of Health</summary>
public abstract class HealthBase
{
public virtual Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context)
@@ -55,8 +85,10 @@ namespace Grpc.Health.V1 {
}
- // client stub
+ /// <summary>Client for Health</summary>
+ #pragma warning disable 0618
public class HealthClient : ClientBase<HealthClient>, IHealthClient
+ #pragma warning restore 0618
{
public HealthClient(Channel channel) : base(channel)
{
@@ -95,26 +127,30 @@ namespace Grpc.Health.V1 {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for Health</summary>
+ public static HealthClient NewClient(Channel channel)
+ {
+ return new HealthClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(IHealth serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Check, serviceImpl.Check).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(HealthBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Check, serviceImpl.Check).Build();
}
- // creates a new client
- public static HealthClient NewClient(Channel channel)
- {
- return new HealthClient(channel);
- }
-
}
}
#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore b/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore
new file mode 100644
index 0000000000..a382af2294
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore
@@ -0,0 +1,3 @@
+bin
+obj
+
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj b/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj
new file mode 100644
index 0000000000..d6eba74289
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{ADEBA147-80AE-4710-82E9-5B7F93690266}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Grpc.IntegrationTesting.StressClient</RootNamespace>
+ <AssemblyName>Grpc.IntegrationTesting.StressClient</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\ReleaseSigned</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <SignAssembly>True</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Grpc.Core\Version.cs">
+ <Link>Version.cs</Link>
+ </Compile>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+ <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
+ <Name>Grpc.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj">
+ <Project>{C61154BA-DD4A-4838-8420-0162A28925E0}</Project>
+ <Name>Grpc.IntegrationTesting</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs b/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs
new file mode 100644
index 0000000000..dffdf22fa5
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs
@@ -0,0 +1,45 @@
+#region Copyright notice and license
+
+// Copyright 2016, 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;
+
+namespace Grpc.IntegrationTesting.StressClient
+{
+ class MainClass
+ {
+ public static void Main(string[] args)
+ {
+ StressTestClient.Run(args);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..e845bbfb9e
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.IntegrationTesting.StressClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index 003d2428fa..3fa8d43f38 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -31,7 +31,7 @@ namespace Grpc.Testing {
"cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB",
"KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiQwoO",
"U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
- "X2hvc3Rfb3ZlcnJpZGUYAiABKAki1gMKDENsaWVudENvbmZpZxIWCg5zZXJ2",
+ "X2hvc3Rfb3ZlcnJpZGUYAiABKAki8AMKDENsaWVudENvbmZpZxIWCg5zZXJ2",
"ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdycGMu",
"dGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEoCzIc",
"LmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGluZ19y",
@@ -41,46 +41,48 @@ namespace Grpc.Testing {
"ASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9jb25m",
"aWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBoaXN0",
"b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbVBh",
- "cmFtcxIRCgljb3JlX2xpc3QYDSADKAUSEgoKY29yZV9saW1pdBgOIAEoBSI4",
- "CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRlc3Rpbmcu",
- "Q2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJoCgpDbGllbnRB",
- "cmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVudENvbmZp",
- "Z0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2Fy",
- "Z3R5cGUi/AEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlwZRgBIAEoDjIY",
- "LmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgC",
- "IAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIMCgRwb3J0GAQg",
- "ASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRzGAcgASgFEhIKCmNvcmVfbGlt",
- "aXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcYCSABKAsyGy5ncnBjLnRlc3Rp",
- "bmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xpc3QYCiADKAUiaAoKU2VydmVy",
- "QXJncxIrCgVzZXR1cBgBIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJDb25m",
- "aWdIABIiCgRtYXJrGAIgASgLMhIuZ3JwYy50ZXN0aW5nLk1hcmtIAEIJCgdh",
- "cmd0eXBlIlUKDFNlcnZlclN0YXR1cxIoCgVzdGF0cxgBIAEoCzIZLmdycGMu",
- "dGVzdGluZy5TZXJ2ZXJTdGF0cxIMCgRwb3J0GAIgASgFEg0KBWNvcmVzGAMg",
- "ASgFIg0KC0NvcmVSZXF1ZXN0Ih0KDENvcmVSZXNwb25zZRINCgVjb3JlcxgB",
- "IAEoBSIGCgRWb2lkIv0BCghTY2VuYXJpbxIMCgRuYW1lGAEgASgJEjEKDWNs",
- "aWVudF9jb25maWcYAiABKAsyGi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmln",
- "EhMKC251bV9jbGllbnRzGAMgASgFEjEKDXNlcnZlcl9jb25maWcYBCABKAsy",
- "Gi5ncnBjLnRlc3RpbmcuU2VydmVyQ29uZmlnEhMKC251bV9zZXJ2ZXJzGAUg",
- "ASgFEhYKDndhcm11cF9zZWNvbmRzGAYgASgFEhkKEWJlbmNobWFya19zZWNv",
- "bmRzGAcgASgFEiAKGHNwYXduX2xvY2FsX3dvcmtlcl9jb3VudBgIIAEoBSI2",
- "CglTY2VuYXJpb3MSKQoJc2NlbmFyaW9zGAEgAygLMhYuZ3JwYy50ZXN0aW5n",
- "LlNjZW5hcmlvIpICChVTY2VuYXJpb1Jlc3VsdFN1bW1hcnkSCwoDcXBzGAEg",
- "ASgBEhsKE3Fwc19wZXJfc2VydmVyX2NvcmUYAiABKAESGgoSc2VydmVyX3N5",
- "c3RlbV90aW1lGAMgASgBEhgKEHNlcnZlcl91c2VyX3RpbWUYBCABKAESGgoS",
- "Y2xpZW50X3N5c3RlbV90aW1lGAUgASgBEhgKEGNsaWVudF91c2VyX3RpbWUY",
- "BiABKAESEgoKbGF0ZW5jeV81MBgHIAEoARISCgpsYXRlbmN5XzkwGAggASgB",
- "EhIKCmxhdGVuY3lfOTUYCSABKAESEgoKbGF0ZW5jeV85ORgKIAEoARITCgts",
- "YXRlbmN5Xzk5ORgLIAEoASKYAgoOU2NlbmFyaW9SZXN1bHQSKAoIc2NlbmFy",
- "aW8YASABKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8SLgoJbGF0ZW5jaWVz",
- "GAIgASgLMhsuZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbURhdGESLwoMY2xpZW50",
- "X3N0YXRzGAMgAygLMhkuZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXRzEi8KDHNl",
- "cnZlcl9zdGF0cxgEIAMoCzIZLmdycGMudGVzdGluZy5TZXJ2ZXJTdGF0cxIU",
- "CgxzZXJ2ZXJfY29yZXMYBSADKAUSNAoHc3VtbWFyeRgGIAEoCzIjLmdycGMu",
- "dGVzdGluZy5TY2VuYXJpb1Jlc3VsdFN1bW1hcnkqLwoKQ2xpZW50VHlwZRIP",
- "CgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5DX0NMSUVOVBABKkkKClNlcnZlclR5",
- "cGUSDwoLU1lOQ19TRVJWRVIQABIQCgxBU1lOQ19TRVJWRVIQARIYChRBU1lO",
- "Q19HRU5FUklDX1NFUlZFUhACKiMKB1JwY1R5cGUSCQoFVU5BUlkQABINCglT",
- "VFJFQU1JTkcQAWIGcHJvdG8z"));
+ "cmFtcxIRCgljb3JlX2xpc3QYDSADKAUSEgoKY29yZV9saW1pdBgOIAEoBRIY",
+ "ChBvdGhlcl9jbGllbnRfYXBpGA8gASgJIjgKDENsaWVudFN0YXR1cxIoCgVz",
+ "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
+ "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
+ "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
+ "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSKWAgoMU2VydmVyQ29u",
+ "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
+ "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
+ "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
+ "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
+ "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
+ "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJImgK",
+ "ClNlcnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2Vy",
+ "dmVyQ29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJr",
+ "SABCCQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsy",
+ "GS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVj",
+ "b3JlcxgDIAEoBSINCgtDb3JlUmVxdWVzdCIdCgxDb3JlUmVzcG9uc2USDQoF",
+ "Y29yZXMYASABKAUiBgoEVm9pZCL9AQoIU2NlbmFyaW8SDAoEbmFtZRgBIAEo",
+ "CRIxCg1jbGllbnRfY29uZmlnGAIgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVu",
+ "dENvbmZpZxITCgtudW1fY2xpZW50cxgDIAEoBRIxCg1zZXJ2ZXJfY29uZmln",
+ "GAQgASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZxITCgtudW1fc2Vy",
+ "dmVycxgFIAEoBRIWCg53YXJtdXBfc2Vjb25kcxgGIAEoBRIZChFiZW5jaG1h",
+ "cmtfc2Vjb25kcxgHIAEoBRIgChhzcGF3bl9sb2NhbF93b3JrZXJfY291bnQY",
+ "CCABKAUiNgoJU2NlbmFyaW9zEikKCXNjZW5hcmlvcxgBIAMoCzIWLmdycGMu",
+ "dGVzdGluZy5TY2VuYXJpbyKSAgoVU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EgsK",
+ "A3FwcxgBIAEoARIbChNxcHNfcGVyX3NlcnZlcl9jb3JlGAIgASgBEhoKEnNl",
+ "cnZlcl9zeXN0ZW1fdGltZRgDIAEoARIYChBzZXJ2ZXJfdXNlcl90aW1lGAQg",
+ "ASgBEhoKEmNsaWVudF9zeXN0ZW1fdGltZRgFIAEoARIYChBjbGllbnRfdXNl",
+ "cl90aW1lGAYgASgBEhIKCmxhdGVuY3lfNTAYByABKAESEgoKbGF0ZW5jeV85",
+ "MBgIIAEoARISCgpsYXRlbmN5Xzk1GAkgASgBEhIKCmxhdGVuY3lfOTkYCiAB",
+ "KAESEwoLbGF0ZW5jeV85OTkYCyABKAEimAIKDlNjZW5hcmlvUmVzdWx0EigK",
+ "CHNjZW5hcmlvGAEgASgLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxh",
+ "dGVuY2llcxgCIAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8K",
+ "DGNsaWVudF9zdGF0cxgDIAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0",
+ "cxIvCgxzZXJ2ZXJfc3RhdHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVy",
+ "U3RhdHMSFAoMc2VydmVyX2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsy",
+ "Iy5ncnBjLnRlc3RpbmcuU2NlbmFyaW9SZXN1bHRTdW1tYXJ5KkEKCkNsaWVu",
+ "dFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQARIQCgxP",
+ "VEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VSVkVSEAAS",
+ "EAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJWRVIQAhIQ",
+ "CgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAASDQoJU1RS",
+ "RUFNSU5HEAFiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedCodeInfo[] {
@@ -88,11 +90,11 @@ namespace Grpc.Testing {
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
- new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
- new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
@@ -109,14 +111,26 @@ namespace Grpc.Testing {
}
#region Enums
public enum ClientType {
+ /// <summary>
+ /// Many languages support a basic distinction between using
+ /// sync or async client, and this allows the specification
+ /// </summary>
SYNC_CLIENT = 0,
ASYNC_CLIENT = 1,
+ /// <summary>
+ /// used for some language-specific variants
+ /// </summary>
+ OTHER_CLIENT = 2,
}
public enum ServerType {
SYNC_SERVER = 0,
ASYNC_SERVER = 1,
ASYNC_GENERIC_SERVER = 2,
+ /// <summary>
+ /// used for some language-specific variants
+ /// </summary>
+ OTHER_SERVER = 3,
}
public enum RpcType {
@@ -651,6 +665,7 @@ namespace Grpc.Testing {
HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
coreList_ = other.coreList_.Clone();
coreLimit_ = other.coreLimit_;
+ otherClientApi_ = other.otherClientApi_;
}
public ClientConfig Clone() {
@@ -795,6 +810,19 @@ namespace Grpc.Testing {
}
}
+ /// <summary>Field number for the "other_client_api" field.</summary>
+ public const int OtherClientApiFieldNumber = 15;
+ private string otherClientApi_ = "";
+ /// <summary>
+ /// If we use an OTHER_CLIENT client_type, this string gives more detail
+ /// </summary>
+ public string OtherClientApi {
+ get { return otherClientApi_; }
+ set {
+ otherClientApi_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as ClientConfig);
}
@@ -818,6 +846,7 @@ namespace Grpc.Testing {
if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
if(!coreList_.Equals(other.coreList_)) return false;
if (CoreLimit != other.CoreLimit) return false;
+ if (OtherClientApi != other.OtherClientApi) return false;
return true;
}
@@ -835,6 +864,7 @@ namespace Grpc.Testing {
if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
hash ^= coreList_.GetHashCode();
if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
+ if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
return hash;
}
@@ -885,6 +915,10 @@ namespace Grpc.Testing {
output.WriteRawTag(112);
output.WriteInt32(CoreLimit);
}
+ if (OtherClientApi.Length != 0) {
+ output.WriteRawTag(122);
+ output.WriteString(OtherClientApi);
+ }
}
public int CalculateSize() {
@@ -921,6 +955,9 @@ namespace Grpc.Testing {
if (CoreLimit != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
}
+ if (OtherClientApi.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
+ }
return size;
}
@@ -972,6 +1009,9 @@ namespace Grpc.Testing {
if (other.CoreLimit != 0) {
CoreLimit = other.CoreLimit;
}
+ if (other.OtherClientApi.Length != 0) {
+ OtherClientApi = other.OtherClientApi;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -1042,6 +1082,10 @@ namespace Grpc.Testing {
CoreLimit = input.ReadInt32();
break;
}
+ case 122: {
+ OtherClientApi = input.ReadString();
+ break;
+ }
}
}
}
@@ -1462,6 +1506,7 @@ namespace Grpc.Testing {
coreLimit_ = other.coreLimit_;
PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
coreList_ = other.coreList_.Clone();
+ otherServerApi_ = other.otherServerApi_;
}
public ServerConfig Clone() {
@@ -1552,6 +1597,19 @@ namespace Grpc.Testing {
get { return coreList_; }
}
+ /// <summary>Field number for the "other_server_api" field.</summary>
+ public const int OtherServerApiFieldNumber = 11;
+ private string otherServerApi_ = "";
+ /// <summary>
+ /// If we use an OTHER_SERVER client_type, this string gives more detail
+ /// </summary>
+ public string OtherServerApi {
+ get { return otherServerApi_; }
+ set {
+ otherServerApi_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as ServerConfig);
}
@@ -1570,6 +1628,7 @@ namespace Grpc.Testing {
if (CoreLimit != other.CoreLimit) return false;
if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
if(!coreList_.Equals(other.coreList_)) return false;
+ if (OtherServerApi != other.OtherServerApi) return false;
return true;
}
@@ -1582,6 +1641,7 @@ namespace Grpc.Testing {
if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
hash ^= coreList_.GetHashCode();
+ if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
return hash;
}
@@ -1615,6 +1675,10 @@ namespace Grpc.Testing {
output.WriteMessage(PayloadConfig);
}
coreList_.WriteTo(output, _repeated_coreList_codec);
+ if (OtherServerApi.Length != 0) {
+ output.WriteRawTag(90);
+ output.WriteString(OtherServerApi);
+ }
}
public int CalculateSize() {
@@ -1638,6 +1702,9 @@ namespace Grpc.Testing {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
}
size += coreList_.CalculateSize(_repeated_coreList_codec);
+ if (OtherServerApi.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
+ }
return size;
}
@@ -1670,6 +1737,9 @@ namespace Grpc.Testing {
PayloadConfig.MergeFrom(other.PayloadConfig);
}
coreList_.Add(other.coreList_);
+ if (other.OtherServerApi.Length != 0) {
+ OtherServerApi = other.OtherServerApi;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -1714,6 +1784,10 @@ namespace Grpc.Testing {
coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
break;
}
+ case 90: {
+ OtherServerApi = input.ReadString();
+ break;
+ }
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index c16d0e5c5d..9685cf1837 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -113,6 +113,9 @@
<Compile Include="GeneratedClientTest.cs" />
<Compile Include="InterarrivalTimers.cs" />
<Compile Include="NUnitMain.cs" />
+ <Compile Include="StressTestClient.cs" />
+ <Compile Include="Metrics.cs" />
+ <Compile Include="MetricsGrpc.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 5436517960..b3b1abf1bc 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -494,7 +494,8 @@ namespace Grpc.IntegrationTesting
}
var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
- Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode);
+ // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
+ Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
}
Console.WriteLine("Passed!");
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
new file mode 100644
index 0000000000..3163949d32
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
@@ -0,0 +1,452 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/metrics.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+ /// <summary>Holder for reflection information generated from src/proto/grpc/testing/metrics.proto</summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class MetricsReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for src/proto/grpc/testing/metrics.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static MetricsReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21ldHJpY3MucHJvdG8SDGdycGMu",
+ "dGVzdGluZyJsCg1HYXVnZVJlc3BvbnNlEgwKBG5hbWUYASABKAkSFAoKbG9u",
+ "Z192YWx1ZRgCIAEoA0gAEhYKDGRvdWJsZV92YWx1ZRgDIAEoAUgAEhYKDHN0",
+ "cmluZ192YWx1ZRgEIAEoCUgAQgcKBXZhbHVlIhwKDEdhdWdlUmVxdWVzdBIM",
+ "CgRuYW1lGAEgASgJIg4KDEVtcHR5TWVzc2FnZTKgAQoOTWV0cmljc1NlcnZp",
+ "Y2USSQoMR2V0QWxsR2F1Z2VzEhouZ3JwYy50ZXN0aW5nLkVtcHR5TWVzc2Fn",
+ "ZRobLmdycGMudGVzdGluZy5HYXVnZVJlc3BvbnNlMAESQwoIR2V0R2F1Z2US",
+ "Gi5ncnBjLnRlc3RpbmcuR2F1Z2VSZXF1ZXN0GhsuZ3JwYy50ZXN0aW5nLkdh",
+ "dWdlUmVzcG9uc2ViBnByb3RvMw=="));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.GaugeResponse), global::Grpc.Testing.GaugeResponse.Parser, new[]{ "Name", "LongValue", "DoubleValue", "StringValue" }, new[]{ "Value" }, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.GaugeRequest), global::Grpc.Testing.GaugeRequest.Parser, new[]{ "Name" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.EmptyMessage), global::Grpc.Testing.EmptyMessage.Parser, null, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ /// <summary>
+ /// Reponse message containing the gauge name and value
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class GaugeResponse : pb::IMessage<GaugeResponse> {
+ private static readonly pb::MessageParser<GaugeResponse> _parser = new pb::MessageParser<GaugeResponse>(() => new GaugeResponse());
+ public static pb::MessageParser<GaugeResponse> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public GaugeResponse() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public GaugeResponse(GaugeResponse other) : this() {
+ name_ = other.name_;
+ switch (other.ValueCase) {
+ case ValueOneofCase.LongValue:
+ LongValue = other.LongValue;
+ break;
+ case ValueOneofCase.DoubleValue:
+ DoubleValue = other.DoubleValue;
+ break;
+ case ValueOneofCase.StringValue:
+ StringValue = other.StringValue;
+ break;
+ }
+
+ }
+
+ public GaugeResponse Clone() {
+ return new GaugeResponse(this);
+ }
+
+ /// <summary>Field number for the "name" field.</summary>
+ public const int NameFieldNumber = 1;
+ private string name_ = "";
+ public string Name {
+ get { return name_; }
+ set {
+ name_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "long_value" field.</summary>
+ public const int LongValueFieldNumber = 2;
+ public long LongValue {
+ get { return valueCase_ == ValueOneofCase.LongValue ? (long) value_ : 0L; }
+ set {
+ value_ = value;
+ valueCase_ = ValueOneofCase.LongValue;
+ }
+ }
+
+ /// <summary>Field number for the "double_value" field.</summary>
+ public const int DoubleValueFieldNumber = 3;
+ public double DoubleValue {
+ get { return valueCase_ == ValueOneofCase.DoubleValue ? (double) value_ : 0D; }
+ set {
+ value_ = value;
+ valueCase_ = ValueOneofCase.DoubleValue;
+ }
+ }
+
+ /// <summary>Field number for the "string_value" field.</summary>
+ public const int StringValueFieldNumber = 4;
+ public string StringValue {
+ get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; }
+ set {
+ value_ = pb::Preconditions.CheckNotNull(value, "value");
+ valueCase_ = ValueOneofCase.StringValue;
+ }
+ }
+
+ private object value_;
+ /// <summary>Enum of possible cases for the "value" oneof.</summary>
+ public enum ValueOneofCase {
+ None = 0,
+ LongValue = 2,
+ DoubleValue = 3,
+ StringValue = 4,
+ }
+ private ValueOneofCase valueCase_ = ValueOneofCase.None;
+ public ValueOneofCase ValueCase {
+ get { return valueCase_; }
+ }
+
+ public void ClearValue() {
+ valueCase_ = ValueOneofCase.None;
+ value_ = null;
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as GaugeResponse);
+ }
+
+ public bool Equals(GaugeResponse other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Name != other.Name) return false;
+ if (LongValue != other.LongValue) return false;
+ if (DoubleValue != other.DoubleValue) return false;
+ if (StringValue != other.StringValue) return false;
+ if (ValueCase != other.ValueCase) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Name.Length != 0) hash ^= Name.GetHashCode();
+ if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode();
+ if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= DoubleValue.GetHashCode();
+ if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode();
+ hash ^= (int) valueCase_;
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Name.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(Name);
+ }
+ if (valueCase_ == ValueOneofCase.LongValue) {
+ output.WriteRawTag(16);
+ output.WriteInt64(LongValue);
+ }
+ if (valueCase_ == ValueOneofCase.DoubleValue) {
+ output.WriteRawTag(25);
+ output.WriteDouble(DoubleValue);
+ }
+ if (valueCase_ == ValueOneofCase.StringValue) {
+ output.WriteRawTag(34);
+ output.WriteString(StringValue);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Name.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+ }
+ if (valueCase_ == ValueOneofCase.LongValue) {
+ size += 1 + pb::CodedOutputStream.ComputeInt64Size(LongValue);
+ }
+ if (valueCase_ == ValueOneofCase.DoubleValue) {
+ size += 1 + 8;
+ }
+ if (valueCase_ == ValueOneofCase.StringValue) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
+ }
+ return size;
+ }
+
+ public void MergeFrom(GaugeResponse other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Name.Length != 0) {
+ Name = other.Name;
+ }
+ switch (other.ValueCase) {
+ case ValueOneofCase.LongValue:
+ LongValue = other.LongValue;
+ break;
+ case ValueOneofCase.DoubleValue:
+ DoubleValue = other.DoubleValue;
+ break;
+ case ValueOneofCase.StringValue:
+ StringValue = other.StringValue;
+ break;
+ }
+
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ Name = input.ReadString();
+ break;
+ }
+ case 16: {
+ LongValue = input.ReadInt64();
+ break;
+ }
+ case 25: {
+ DoubleValue = input.ReadDouble();
+ break;
+ }
+ case 34: {
+ StringValue = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Request message containing the gauge name
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class GaugeRequest : pb::IMessage<GaugeRequest> {
+ private static readonly pb::MessageParser<GaugeRequest> _parser = new pb::MessageParser<GaugeRequest>(() => new GaugeRequest());
+ public static pb::MessageParser<GaugeRequest> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[1]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public GaugeRequest() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public GaugeRequest(GaugeRequest other) : this() {
+ name_ = other.name_;
+ }
+
+ public GaugeRequest Clone() {
+ return new GaugeRequest(this);
+ }
+
+ /// <summary>Field number for the "name" field.</summary>
+ public const int NameFieldNumber = 1;
+ private string name_ = "";
+ public string Name {
+ get { return name_; }
+ set {
+ name_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as GaugeRequest);
+ }
+
+ public bool Equals(GaugeRequest other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Name != other.Name) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Name.Length != 0) hash ^= Name.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Name.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(Name);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Name.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+ }
+ return size;
+ }
+
+ public void MergeFrom(GaugeRequest other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Name.Length != 0) {
+ Name = other.Name;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ Name = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class EmptyMessage : pb::IMessage<EmptyMessage> {
+ private static readonly pb::MessageParser<EmptyMessage> _parser = new pb::MessageParser<EmptyMessage>(() => new EmptyMessage());
+ public static pb::MessageParser<EmptyMessage> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[2]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public EmptyMessage() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public EmptyMessage(EmptyMessage other) : this() {
+ }
+
+ public EmptyMessage Clone() {
+ return new EmptyMessage(this);
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as EmptyMessage);
+ }
+
+ public bool Equals(EmptyMessage other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ return size;
+ }
+
+ public void MergeFrom(EmptyMessage other) {
+ if (other == null) {
+ return;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
new file mode 100644
index 0000000000..aa4f1c5c3e
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
@@ -0,0 +1,242 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/metrics.proto
+// Original file comments:
+// Copyright 2015-2016, 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.
+//
+// Contains the definitions for a metrics service and the type of metrics
+// exposed by the service.
+//
+// Currently, 'Gauge' (i.e a metric that represents the measured value of
+// something at an instant of time) is the only metric type supported by the
+// service.
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Testing {
+ public static class MetricsService
+ {
+ static readonly string __ServiceName = "grpc.testing.MetricsService";
+
+ static readonly Marshaller<global::Grpc.Testing.EmptyMessage> __Marshaller_EmptyMessage = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.EmptyMessage.Parser.ParseFrom);
+ static readonly Marshaller<global::Grpc.Testing.GaugeResponse> __Marshaller_GaugeResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeResponse.Parser.ParseFrom);
+ static readonly Marshaller<global::Grpc.Testing.GaugeRequest> __Marshaller_GaugeRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeRequest.Parser.ParseFrom);
+
+ static readonly Method<global::Grpc.Testing.EmptyMessage, global::Grpc.Testing.GaugeResponse> __Method_GetAllGauges = new Method<global::Grpc.Testing.EmptyMessage, global::Grpc.Testing.GaugeResponse>(
+ MethodType.ServerStreaming,
+ __ServiceName,
+ "GetAllGauges",
+ __Marshaller_EmptyMessage,
+ __Marshaller_GaugeResponse);
+
+ static readonly Method<global::Grpc.Testing.GaugeRequest, global::Grpc.Testing.GaugeResponse> __Method_GetGauge = new Method<global::Grpc.Testing.GaugeRequest, global::Grpc.Testing.GaugeResponse>(
+ MethodType.Unary,
+ __ServiceName,
+ "GetGauge",
+ __Marshaller_GaugeRequest,
+ __Marshaller_GaugeResponse);
+
+ /// <summary>Service descriptor</summary>
+ public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+ {
+ get { return global::Grpc.Testing.MetricsReflection.Descriptor.Services[0]; }
+ }
+
+ /// <summary>Client for MetricsService</summary>
+ [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
+ public interface IMetricsServiceClient
+ {
+ /// <summary>
+ /// Returns the values of all the gauges that are currently being maintained by
+ /// the service
+ /// </summary>
+ AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Returns the values of all the gauges that are currently being maintained by
+ /// the service
+ /// </summary>
+ AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options);
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options);
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options);
+ }
+
+ /// <summary>Interface of server-side implementations of MetricsService</summary>
+ [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
+ public interface IMetricsService
+ {
+ /// <summary>
+ /// Returns the values of all the gauges that are currently being maintained by
+ /// the service
+ /// </summary>
+ Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context);
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context);
+ }
+
+ /// <summary>Base class for server-side implementations of MetricsService</summary>
+ public abstract class MetricsServiceBase
+ {
+ /// <summary>
+ /// Returns the values of all the gauges that are currently being maintained by
+ /// the service
+ /// </summary>
+ public virtual Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context)
+ {
+ throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+ }
+
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ public virtual Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context)
+ {
+ throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+ }
+
+ }
+
+ /// <summary>Client for MetricsService</summary>
+ #pragma warning disable 0618
+ public class MetricsServiceClient : ClientBase<MetricsServiceClient>, IMetricsServiceClient
+ #pragma warning restore 0618
+ {
+ public MetricsServiceClient(Channel channel) : base(channel)
+ {
+ }
+ public MetricsServiceClient(CallInvoker callInvoker) : base(callInvoker)
+ {
+ }
+ ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+ protected MetricsServiceClient() : base()
+ {
+ }
+ ///<summary>Protected constructor to allow creation of configured clients.</summary>
+ protected MetricsServiceClient(ClientBaseConfiguration configuration) : base(configuration)
+ {
+ }
+
+ /// <summary>
+ /// Returns the values of all the gauges that are currently being maintained by
+ /// the service
+ /// </summary>
+ public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetAllGauges(request, new CallOptions(headers, deadline, cancellationToken));
+ }
+ /// <summary>
+ /// Returns the values of all the gauges that are currently being maintained by
+ /// the service
+ /// </summary>
+ public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options)
+ {
+ return CallInvoker.AsyncServerStreamingCall(__Method_GetAllGauges, null, options, request);
+ }
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetGauge(request, new CallOptions(headers, deadline, cancellationToken));
+ }
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options)
+ {
+ return CallInvoker.BlockingUnaryCall(__Method_GetGauge, null, options, request);
+ }
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetGaugeAsync(request, new CallOptions(headers, deadline, cancellationToken));
+ }
+ /// <summary>
+ /// Returns the value of one gauge
+ /// </summary>
+ public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options)
+ {
+ return CallInvoker.AsyncUnaryCall(__Method_GetGauge, null, options, request);
+ }
+ protected override MetricsServiceClient NewInstance(ClientBaseConfiguration configuration)
+ {
+ return new MetricsServiceClient(configuration);
+ }
+ }
+
+ /// <summary>Creates a new client for MetricsService</summary>
+ public static MetricsServiceClient NewClient(Channel channel)
+ {
+ return new MetricsServiceClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
+ public static ServerServiceDefinition BindService(IMetricsService serviceImpl)
+ #pragma warning restore 0618
+ {
+ return ServerServiceDefinition.CreateBuilder(__ServiceName)
+ .AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges)
+ .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
+ public static ServerServiceDefinition BindService(MetricsServiceBase serviceImpl)
+ #pragma warning restore 0618
+ {
+ return ServerServiceDefinition.CreateBuilder(__ServiceName)
+ .AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges)
+ .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
+ }
+
+ }
+}
+#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
index 46b16cf202..42bf5e0b58 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
@@ -1,5 +1,37 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/proto/grpc/testing/services.proto
+// Original file comments:
+// 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
#region Designer generated code
using System;
@@ -29,40 +61,80 @@ namespace Grpc.Testing {
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[0]; }
}
- // client interface
+ /// <summary>Client for BenchmarkService</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IBenchmarkServiceClient
{
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of BenchmarkService</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IBenchmarkService
{
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of BenchmarkService</summary>
public abstract class BenchmarkServiceBase
{
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -70,8 +142,10 @@ namespace Grpc.Testing {
}
- // client stub
+ /// <summary>Client for BenchmarkService</summary>
+ #pragma warning disable 0618
public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient
+ #pragma warning restore 0618
{
public BenchmarkServiceClient(Channel channel) : base(channel)
{
@@ -88,26 +162,50 @@ namespace Grpc.Testing {
{
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingCall(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// The server returns the client payload as-is.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
@@ -118,28 +216,32 @@ namespace Grpc.Testing {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for BenchmarkService</summary>
+ public static BenchmarkServiceClient NewClient(Channel channel)
+ {
+ return new BenchmarkServiceClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
- // creates a new client
- public static BenchmarkServiceClient NewClient(Channel channel)
- {
- return new BenchmarkServiceClient(channel);
- }
-
}
public static class WorkerService
{
@@ -181,58 +283,158 @@ namespace Grpc.Testing {
__Marshaller_Void,
__Marshaller_Void);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[1]; }
}
- // client interface
+ /// <summary>Client for WorkerService</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IWorkerServiceClient
{
+ /// <summary>
+ /// Start server with specified workload.
+ /// First request sent specifies the ServerConfig followed by ServerStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test server
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Start server with specified workload.
+ /// First request sent specifies the ServerConfig followed by ServerStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test server
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options);
+ /// <summary>
+ /// Start client with specified workload.
+ /// First request sent specifies the ClientConfig followed by ClientStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test client
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Start client with specified workload.
+ /// First request sent specifies the ClientConfig followed by ClientStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test client
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options);
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options);
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options);
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options);
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of WorkerService</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IWorkerService
{
+ /// <summary>
+ /// Start server with specified workload.
+ /// First request sent specifies the ServerConfig followed by ServerStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test server
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
+ /// <summary>
+ /// Start client with specified workload.
+ /// First request sent specifies the ClientConfig followed by ClientStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test client
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context);
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context);
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of WorkerService</summary>
public abstract class WorkerServiceBase
{
+ /// <summary>
+ /// Start server with specified workload.
+ /// First request sent specifies the ServerConfig followed by ServerStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test server
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
public virtual Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// Start client with specified workload.
+ /// First request sent specifies the ClientConfig followed by ClientStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test client
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
public virtual Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
public virtual Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
public virtual Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -240,8 +442,10 @@ namespace Grpc.Testing {
}
- // client stub
+ /// <summary>Client for WorkerService</summary>
+ #pragma warning disable 0618
public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient
+ #pragma warning restore 0618
{
public WorkerServiceClient(Channel channel) : base(channel)
{
@@ -258,50 +462,106 @@ namespace Grpc.Testing {
{
}
+ /// <summary>
+ /// Start server with specified workload.
+ /// First request sent specifies the ServerConfig followed by ServerStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test server
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return RunServer(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Start server with specified workload.
+ /// First request sent specifies the ServerConfig followed by ServerStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test server
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
}
+ /// <summary>
+ /// Start client with specified workload.
+ /// First request sent specifies the ClientConfig followed by ClientStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test client
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return RunClient(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Start client with specified workload.
+ /// First request sent specifies the ClientConfig followed by ClientStatus
+ /// response. After that, a "Mark" can be sent anytime to request the latest
+ /// stats. Closing the stream will initiate shutdown of the test client
+ /// and once the shutdown has finished, the OK status is sent to terminate
+ /// this RPC.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
}
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return CoreCount(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
}
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return CoreCountAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Just return the core count - unary call
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
}
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return QuitWorker(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
}
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return QuitWorkerAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// Quit this worker
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
@@ -312,8 +572,16 @@ namespace Grpc.Testing {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for WorkerService</summary>
+ public static WorkerServiceClient NewClient(Channel channel)
+ {
+ return new WorkerServiceClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(IWorkerService serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer)
@@ -322,8 +590,10 @@ namespace Grpc.Testing {
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer)
@@ -332,12 +602,6 @@ namespace Grpc.Testing {
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
}
- // creates a new client
- public static WorkerServiceClient NewClient(Channel channel)
- {
- return new WorkerServiceClient(channel);
- }
-
}
}
#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
new file mode 100644
index 0000000000..8db691cb04
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
@@ -0,0 +1,318 @@
+#region Copyright notice and license
+
+// Copyright 2015-2016, 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.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using CommandLine;
+using CommandLine.Text;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+ public class StressTestClient
+ {
+ static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<StressTestClient>();
+ const double SecondsToNanos = 1e9;
+
+ private class ClientOptions
+ {
+ [Option("server_addresses", DefaultValue = "localhost:8080")]
+ public string ServerAddresses { get; set; }
+
+ [Option("test_cases", DefaultValue = "large_unary:100")]
+ public string TestCases { get; set; }
+
+ [Option("test_duration_secs", DefaultValue = -1)]
+ public int TestDurationSecs { get; set; }
+
+ [Option("num_channels_per_server", DefaultValue = 1)]
+ public int NumChannelsPerServer { get; set; }
+
+ [Option("num_stubs_per_channel", DefaultValue = 1)]
+ public int NumStubsPerChannel { get; set; }
+
+ [Option("metrics_port", DefaultValue = 8081)]
+ public int MetricsPort { get; set; }
+
+ [HelpOption]
+ public string GetUsage()
+ {
+ var help = new HelpText
+ {
+ Heading = "gRPC C# stress test client",
+ AddDashesToOption = true
+ };
+ help.AddPreOptionsLine("Usage:");
+ help.AddOptions(this);
+ return help;
+ }
+ }
+
+ ClientOptions options;
+ List<string> serverAddresses;
+ Dictionary<string, int> weightedTestCases;
+ WeightedRandomGenerator testCaseGenerator;
+
+ // cancellation will be emitted once test_duration_secs has elapsed.
+ CancellationTokenSource finishedTokenSource = new CancellationTokenSource();
+ Histogram histogram = new Histogram(0.01, 60 * SecondsToNanos);
+
+ private StressTestClient(ClientOptions options, List<string> serverAddresses, Dictionary<string, int> weightedTestCases)
+ {
+ this.options = options;
+ this.serverAddresses = serverAddresses;
+ this.weightedTestCases = weightedTestCases;
+ this.testCaseGenerator = new WeightedRandomGenerator(this.weightedTestCases);
+ }
+
+ public static void Run(string[] args)
+ {
+ var options = new ClientOptions();
+ if (!Parser.Default.ParseArguments(args, options))
+ {
+ Environment.Exit(1);
+ }
+
+ GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
+ GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
+
+ var serverAddresses = options.ServerAddresses.Split(',');
+ GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
+
+ var testCases = ParseWeightedTestCases(options.TestCases);
+ GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
+
+ var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
+ interopClient.Run().Wait();
+ }
+
+ async Task Run()
+ {
+ var metricsServer = new Server()
+ {
+ Services = { MetricsService.BindService(new MetricsServiceImpl(histogram)) },
+ Ports = { { "[::]", options.MetricsPort, ServerCredentials.Insecure } }
+ };
+ metricsServer.Start();
+
+ if (options.TestDurationSecs >= 0)
+ {
+ finishedTokenSource.CancelAfter(TimeSpan.FromSeconds(options.TestDurationSecs));
+ }
+
+ var tasks = new List<Task>();
+ var channels = new List<Channel>();
+ foreach (var serverAddress in serverAddresses)
+ {
+ for (int i = 0; i < options.NumChannelsPerServer; i++)
+ {
+ var channel = new Channel(serverAddress, ChannelCredentials.Insecure);
+ channels.Add(channel);
+ for (int j = 0; j < options.NumStubsPerChannel; j++)
+ {
+ var client = TestService.NewClient(channel);
+ var task = Task.Factory.StartNew(() => RunBodyAsync(client).GetAwaiter().GetResult(),
+ TaskCreationOptions.LongRunning);
+ tasks.Add(task);
+ }
+ }
+ }
+ await Task.WhenAll(tasks);
+
+ foreach (var channel in channels)
+ {
+ await channel.ShutdownAsync();
+ }
+
+ await metricsServer.ShutdownAsync();
+ }
+
+ async Task RunBodyAsync(TestService.TestServiceClient client)
+ {
+ Logger.Info("Starting stress test client thread.");
+ while (!finishedTokenSource.Token.IsCancellationRequested)
+ {
+ var testCase = testCaseGenerator.GetNext();
+
+ var stopwatch = Stopwatch.StartNew();
+
+ await RunTestCaseAsync(client, testCase);
+
+ stopwatch.Stop();
+ histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+ }
+ Logger.Info("Stress test client thread finished.");
+ }
+
+ async Task RunTestCaseAsync(TestService.TestServiceClient client, string testCase)
+ {
+ switch (testCase)
+ {
+ case "empty_unary":
+ InteropClient.RunEmptyUnary(client);
+ break;
+ case "large_unary":
+ InteropClient.RunLargeUnary(client);
+ break;
+ case "client_streaming":
+ await InteropClient.RunClientStreamingAsync(client);
+ break;
+ case "server_streaming":
+ await InteropClient.RunServerStreamingAsync(client);
+ break;
+ case "ping_pong":
+ await InteropClient.RunPingPongAsync(client);
+ break;
+ case "empty_stream":
+ await InteropClient.RunEmptyStreamAsync(client);
+ break;
+ case "cancel_after_begin":
+ await InteropClient.RunCancelAfterBeginAsync(client);
+ break;
+ case "cancel_after_first_response":
+ await InteropClient.RunCancelAfterFirstResponseAsync(client);
+ break;
+ case "timeout_on_sleeping_server":
+ await InteropClient.RunTimeoutOnSleepingServerAsync(client);
+ break;
+ case "custom_metadata":
+ await InteropClient.RunCustomMetadataAsync(client);
+ break;
+ case "status_code_and_message":
+ await InteropClient.RunStatusCodeAndMessageAsync(client);
+ break;
+ default:
+ throw new ArgumentException("Unsupported test case " + testCase);
+ }
+ }
+
+ static Dictionary<string, int> ParseWeightedTestCases(string weightedTestCases)
+ {
+ var result = new Dictionary<string, int>();
+ foreach (var weightedTestCase in weightedTestCases.Split(','))
+ {
+ var parts = weightedTestCase.Split(new char[] {':'}, 2);
+ GrpcPreconditions.CheckArgument(parts.Length == 2, "Malformed test_cases option.");
+ result.Add(parts[0], int.Parse(parts[1]));
+ }
+ return result;
+ }
+
+ class WeightedRandomGenerator
+ {
+ readonly Random random = new Random();
+ readonly List<Tuple<int, string>> cumulativeSums;
+ readonly int weightSum;
+
+ public WeightedRandomGenerator(Dictionary<string, int> weightedItems)
+ {
+ cumulativeSums = new List<Tuple<int, string>>();
+ weightSum = 0;
+ foreach (var entry in weightedItems)
+ {
+ weightSum += entry.Value;
+ cumulativeSums.Add(Tuple.Create(weightSum, entry.Key));
+ }
+ }
+
+ public string GetNext()
+ {
+ int rand = random.Next(weightSum);
+ foreach (var entry in cumulativeSums)
+ {
+ if (rand < entry.Item1)
+ {
+ return entry.Item2;
+ }
+ }
+ throw new InvalidOperationException("GetNext() failed.");
+ }
+ }
+
+ class MetricsServiceImpl : MetricsService.MetricsServiceBase
+ {
+ const string GaugeName = "csharp_overall_qps";
+
+ readonly Histogram histogram;
+ readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+
+ public MetricsServiceImpl(Histogram histogram)
+ {
+ this.histogram = histogram;
+ }
+
+ public override Task<GaugeResponse> GetGauge(GaugeRequest request, ServerCallContext context)
+ {
+ if (request.Name == GaugeName)
+ {
+ long qps = GetQpsAndReset();
+
+ return Task.FromResult(new GaugeResponse
+ {
+ Name = GaugeName,
+ LongValue = qps
+ });
+ }
+ throw new RpcException(new Status(StatusCode.InvalidArgument, "Gauge does not exist"));
+ }
+
+ public override async Task GetAllGauges(EmptyMessage request, IServerStreamWriter<GaugeResponse> responseStream, ServerCallContext context)
+ {
+ long qps = GetQpsAndReset();
+
+ var response = new GaugeResponse
+ {
+ Name = GaugeName,
+ LongValue = qps
+ };
+ await responseStream.WriteAsync(response);
+ }
+
+ long GetQpsAndReset()
+ {
+ var snapshot = histogram.GetSnapshot(true);
+ var elapsedSnapshot = wallClockStopwatch.GetElapsedSnapshot(true);
+
+ return (long) (snapshot.Count / elapsedSnapshot.Seconds);
+ }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
index 31746cbe71..f1878cbb55 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
@@ -1,5 +1,38 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/proto/grpc/testing/test.proto
+// Original file comments:
+// Copyright 2015-2016, 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
#region Designer generated code
using System;
@@ -8,6 +41,10 @@ using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Testing {
+ /// <summary>
+ /// A simple service to test the various types of RPCs and experiment with
+ /// performance with various types of payload.
+ /// </summary>
public static class TestService
{
static readonly string __ServiceName = "grpc.testing.TestService";
@@ -62,74 +99,186 @@ namespace Grpc.Testing {
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.TestReflection.Descriptor.Services[0]; }
}
- // client interface
+ /// <summary>Client for TestService</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface ITestServiceClient
{
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options);
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options);
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+ /// <summary>
+ /// One request followed by a sequence of responses (streamed download).
+ /// The server returns the payload with client desired type and sizes.
+ /// </summary>
AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// One request followed by a sequence of responses (streamed download).
+ /// The server returns the payload with client desired type and sizes.
+ /// </summary>
AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options);
+ /// <summary>
+ /// A sequence of requests followed by one response (streamed upload).
+ /// The server returns the aggregated size of client payload as the result.
+ /// </summary>
AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// A sequence of requests followed by one response (streamed upload).
+ /// The server returns the aggregated size of client payload as the result.
+ /// </summary>
AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options);
+ /// <summary>
+ /// A sequence of requests with each request served by the server immediately.
+ /// As one request could lead to multiple responses, this interface
+ /// demonstrates the idea of full duplexing.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// A sequence of requests with each request served by the server immediately.
+ /// As one request could lead to multiple responses, this interface
+ /// demonstrates the idea of full duplexing.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options);
+ /// <summary>
+ /// A sequence of requests followed by a sequence of responses.
+ /// The server buffers all the client requests and then serves them in order. A
+ /// stream of responses are returned to the client when the server starts with
+ /// first request.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// A sequence of requests followed by a sequence of responses.
+ /// The server buffers all the client requests and then serves them in order. A
+ /// stream of responses are returned to the client when the server starts with
+ /// first request.
+ /// </summary>
AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of TestService</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface ITestService
{
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context);
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
+ /// <summary>
+ /// One request followed by a sequence of responses (streamed download).
+ /// The server returns the payload with client desired type and sizes.
+ /// </summary>
Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context);
+ /// <summary>
+ /// A sequence of requests followed by one response (streamed upload).
+ /// The server returns the aggregated size of client payload as the result.
+ /// </summary>
Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context);
+ /// <summary>
+ /// A sequence of requests with each request served by the server immediately.
+ /// As one request could lead to multiple responses, this interface
+ /// demonstrates the idea of full duplexing.
+ /// </summary>
Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context);
+ /// <summary>
+ /// A sequence of requests followed by a sequence of responses.
+ /// The server buffers all the client requests and then serves them in order. A
+ /// stream of responses are returned to the client when the server starts with
+ /// first request.
+ /// </summary>
Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of TestService</summary>
public abstract class TestServiceBase
{
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
public virtual Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// One request followed by a sequence of responses (streamed download).
+ /// The server returns the payload with client desired type and sizes.
+ /// </summary>
public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// A sequence of requests followed by one response (streamed upload).
+ /// The server returns the aggregated size of client payload as the result.
+ /// </summary>
public virtual Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// A sequence of requests with each request served by the server immediately.
+ /// As one request could lead to multiple responses, this interface
+ /// demonstrates the idea of full duplexing.
+ /// </summary>
public virtual Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
+ /// <summary>
+ /// A sequence of requests followed by a sequence of responses.
+ /// The server buffers all the client requests and then serves them in order. A
+ /// stream of responses are returned to the client when the server starts with
+ /// first request.
+ /// </summary>
public virtual Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -137,8 +286,10 @@ namespace Grpc.Testing {
}
- // client stub
+ /// <summary>Client for TestService</summary>
+ #pragma warning disable 0618
public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient
+ #pragma warning restore 0618
{
public TestServiceClient(Channel channel) : base(channel)
{
@@ -155,66 +306,128 @@ namespace Grpc.Testing {
{
}
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return EmptyCall(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request);
}
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return EmptyCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One empty request followed by one empty response.
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request);
}
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
}
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One request followed by one response.
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
+ /// <summary>
+ /// One request followed by a sequence of responses (streamed download).
+ /// The server returns the payload with client desired type and sizes.
+ /// </summary>
public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingOutputCall(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// One request followed by a sequence of responses (streamed download).
+ /// The server returns the payload with client desired type and sizes.
+ /// </summary>
public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request);
}
+ /// <summary>
+ /// A sequence of requests followed by one response (streamed upload).
+ /// The server returns the aggregated size of client payload as the result.
+ /// </summary>
public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingInputCall(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// A sequence of requests followed by one response (streamed upload).
+ /// The server returns the aggregated size of client payload as the result.
+ /// </summary>
public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options);
}
+ /// <summary>
+ /// A sequence of requests with each request served by the server immediately.
+ /// As one request could lead to multiple responses, this interface
+ /// demonstrates the idea of full duplexing.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return FullDuplexCall(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// A sequence of requests with each request served by the server immediately.
+ /// As one request could lead to multiple responses, this interface
+ /// demonstrates the idea of full duplexing.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options);
}
+ /// <summary>
+ /// A sequence of requests followed by a sequence of responses.
+ /// The server buffers all the client requests and then serves them in order. A
+ /// stream of responses are returned to the client when the server starts with
+ /// first request.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return HalfDuplexCall(new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// A sequence of requests followed by a sequence of responses.
+ /// The server buffers all the client requests and then serves them in order. A
+ /// stream of responses are returned to the client when the server starts with
+ /// first request.
+ /// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options);
@@ -225,8 +438,16 @@ namespace Grpc.Testing {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for TestService</summary>
+ public static TestServiceClient NewClient(Channel channel)
+ {
+ return new TestServiceClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(ITestService serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
@@ -237,8 +458,10 @@ namespace Grpc.Testing {
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(TestServiceBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
@@ -249,13 +472,11 @@ namespace Grpc.Testing {
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
- // creates a new client
- public static TestServiceClient NewClient(Channel channel)
- {
- return new TestServiceClient(channel);
- }
-
}
+ /// <summary>
+ /// A simple service NOT implemented at servers so clients can test for
+ /// that case.
+ /// </summary>
public static class UnimplementedService
{
static readonly string __ServiceName = "grpc.testing.UnimplementedService";
@@ -269,32 +490,50 @@ namespace Grpc.Testing {
__Marshaller_Empty,
__Marshaller_Empty);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.TestReflection.Descriptor.Services[1]; }
}
- // client interface
+ /// <summary>Client for UnimplementedService</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IUnimplementedServiceClient
{
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options);
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of UnimplementedService</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IUnimplementedService
{
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of UnimplementedService</summary>
public abstract class UnimplementedServiceBase
{
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
public virtual Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -302,8 +541,10 @@ namespace Grpc.Testing {
}
- // client stub
+ /// <summary>Client for UnimplementedService</summary>
+ #pragma warning disable 0618
public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient
+ #pragma warning restore 0618
{
public UnimplementedServiceClient(Channel channel) : base(channel)
{
@@ -320,18 +561,30 @@ namespace Grpc.Testing {
{
}
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
}
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
+ /// <summary>
+ /// A call that no server should implement
+ /// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
@@ -342,27 +595,34 @@ namespace Grpc.Testing {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for UnimplementedService</summary>
+ public static UnimplementedServiceClient NewClient(Channel channel)
+ {
+ return new UnimplementedServiceClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(IUnimplementedService serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
- // creates a new client
- public static UnimplementedServiceClient NewClient(Channel channel)
- {
- return new UnimplementedServiceClient(channel);
- }
-
}
+ /// <summary>
+ /// A service used to control reconnect server.
+ /// </summary>
public static class ReconnectService
{
static readonly string __ServiceName = "grpc.testing.ReconnectService";
@@ -385,13 +645,13 @@ namespace Grpc.Testing {
__Marshaller_Empty,
__Marshaller_ReconnectInfo);
- // service descriptor
+ /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.TestReflection.Descriptor.Services[2]; }
}
- // client interface
+ /// <summary>Client for ReconnectService</summary>
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IReconnectServiceClient
{
@@ -405,7 +665,7 @@ namespace Grpc.Testing {
AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options);
}
- // server-side interface
+ /// <summary>Interface of server-side implementations of ReconnectService</summary>
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IReconnectService
{
@@ -413,7 +673,7 @@ namespace Grpc.Testing {
Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context);
}
- // server-side abstract class
+ /// <summary>Base class for server-side implementations of ReconnectService</summary>
public abstract class ReconnectServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context)
@@ -428,8 +688,10 @@ namespace Grpc.Testing {
}
- // client stub
+ /// <summary>Client for ReconnectService</summary>
+ #pragma warning disable 0618
public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient
+ #pragma warning restore 0618
{
public ReconnectServiceClient(Channel channel) : base(channel)
{
@@ -484,28 +746,32 @@ namespace Grpc.Testing {
}
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates a new client for ReconnectService</summary>
+ public static ReconnectServiceClient NewClient(Channel channel)
+ {
+ return new ReconnectServiceClient(channel);
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(IReconnectService serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Start, serviceImpl.Start)
.AddMethod(__Method_Stop, serviceImpl.Stop).Build();
}
- // creates service definition that can be registered with a server
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ #pragma warning disable 0618
public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl)
+ #pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Start, serviceImpl.Start)
.AddMethod(__Method_Stop, serviceImpl.Stop).Build();
}
- // creates a new client
- public static ReconnectServiceClient NewClient(Channel channel)
- {
- return new ReconnectServiceClient(channel);
- }
-
}
}
#endregion
diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
index 8ff35e8c0d..9be36c0caa 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -34,6 +34,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck.Tests", "G
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{ADEBA147-80AE-4710-82E9-5B7F93690266}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -83,6 +85,12 @@ Global
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.Build.0 = Release|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {ADEBA147-80AE-4710-82E9-5B7F93690266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ADEBA147-80AE-4710-82E9-5B7F93690266}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ADEBA147-80AE-4710-82E9-5B7F93690266}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ADEBA147-80AE-4710-82E9-5B7F93690266}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ADEBA147-80AE-4710-82E9-5B7F93690266}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+ {ADEBA147-80AE-4710-82E9-5B7F93690266}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/src/csharp/buildall.bat b/src/csharp/buildall.bat
index fcc8442656..f800756dfe 100644
--- a/src/csharp/buildall.bat
+++ b/src/csharp/buildall.bat
@@ -8,6 +8,12 @@ cd /d %~dp0
@rem Set VS variables (uses Visual Studio 2013)
@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
+@rem Fetch all dependencies
+nuget restore ..\..\vsprojects\grpc.sln || goto :error
+nuget restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
+nuget restore ..\..\vsprojects\grpc_protoc_plugins.sln || goto :error
+nuget restore Grpc.sln || goto :error
+
@rem Build the C# native extension
msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Debug /p:PlatformToolset=v120 || goto :error
msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index 9ac770b79d..79488e02a5 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -45,4 +45,4 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_D
-I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
- -I . src/proto/grpc/testing/{control,empty,messages,payloads,services,stats,test}.proto
+ -I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto