aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp
diff options
context:
space:
mode:
authorGravatar Michael Lumish <mlumish@google.com>2015-12-15 11:43:05 -0800
committerGravatar Michael Lumish <mlumish@google.com>2015-12-15 11:43:05 -0800
commitda61668122b63fc18d64231dede700139234bc75 (patch)
tree3b6fef704fd0e3670c0aa308dd6c24704c4f8c94 /src/csharp
parent960870549a31a354b63823319640a628a2fd1767 (diff)
parent5c8c3e78a5b2cd6fb8504b48bac7b7f030cce787 (diff)
Merge pull request #4454 from grpc/master
Re-cutting the 0.12 release from master.
Diffstat (limited to 'src/csharp')
-rw-r--r--src/csharp/Grpc.Core.Tests/CallOptionsTest.cs88
-rw-r--r--src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs2
-rw-r--r--src/csharp/Grpc.Core.Tests/ChannelTest.cs11
-rw-r--r--src/csharp/Grpc.Core.Tests/ClientServerTest.cs60
-rw-r--r--src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs32
-rw-r--r--src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj3
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs105
-rw-r--r--src/csharp/Grpc.Core.Tests/MetadataTest.cs113
-rw-r--r--src/csharp/Grpc.Core.Tests/MockServiceHelper.cs7
-rw-r--r--src/csharp/Grpc.Core.Tests/PInvokeTest.cs4
-rw-r--r--src/csharp/Grpc.Core.Tests/PerformanceTest.cs8
-rw-r--r--src/csharp/Grpc.Core.Tests/SanityTest.cs125
-rw-r--r--src/csharp/Grpc.Core.Tests/ShutdownTest.cs11
-rw-r--r--src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs101
-rw-r--r--src/csharp/Grpc.Core/CallOptions.cs1
-rw-r--r--src/csharp/Grpc.Core/Channel.cs46
-rw-r--r--src/csharp/Grpc.Core/ChannelOptions.cs7
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj16
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallBase.cs14
-rw-r--r--src/csharp/Grpc.Core/Internal/ClientResponseStream.cs4
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs2
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerCallHandler.cs40
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerRequestStream.cs2
-rw-r--r--src/csharp/Grpc.Core/Internal/Timespec.cs23
-rw-r--r--src/csharp/Grpc.Core/Profiling/IProfiler.cs2
-rw-r--r--src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs3
-rw-r--r--src/csharp/Grpc.Core/Profiling/Profilers.cs13
-rw-r--r--src/csharp/Grpc.Core/Server.cs12
-rw-r--r--src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs12
-rw-r--r--src/csharp/Grpc.Core/packages.config4
-rw-r--r--src/csharp/Grpc.Examples/Grpc.Examples.csproj3
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj63
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs (renamed from src/csharp/Grpc.HealthCheck/proto/health.proto)34
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs11
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config11
-rw-r--r--src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs76
-rw-r--r--src/csharp/Grpc.IntegrationTesting/ClientRunners.cs153
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Control.cs2362
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj71
-rw-r--r--src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs113
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Histogram.cs153
-rw-r--r--src/csharp/Grpc.IntegrationTesting/HistogramTest.cs104
-rw-r--r--src/csharp/Grpc.IntegrationTesting/IClientRunner.cs67
-rw-r--r--src/csharp/Grpc.IntegrationTesting/IServerRunner.cs72
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs119
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs22
-rw-r--r--src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs54
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Payloads.cs580
-rw-r--r--src/csharp/Grpc.IntegrationTesting/QpsWorker.cs108
-rw-r--r--src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs118
-rw-r--r--src/csharp/Grpc.IntegrationTesting/ServerRunners.cs124
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Services.cs44
-rw-r--r--src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs198
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Settings.StyleCop5
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Stats.cs744
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs39
-rw-r--r--src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs (renamed from src/csharp/Grpc.Examples/proto/math.proto)86
-rw-r--r--src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs96
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config1
-rw-r--r--src/csharp/Grpc.sln96
-rwxr-xr-xsrc/csharp/generate_proto_csharp.sh22
-rw-r--r--src/csharp/tests.json45
64 files changed, 6292 insertions, 379 deletions
diff --git a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
new file mode 100644
index 0000000000..a3a613be74
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs
@@ -0,0 +1,88 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class CallOptionsTest
+ {
+ [Test]
+ public void WithMethods()
+ {
+ var options = new CallOptions();
+
+ var metadata = new Metadata();
+ Assert.AreSame(metadata, options.WithHeaders(metadata).Headers);
+
+ var deadline = DateTime.UtcNow;
+ Assert.AreEqual(deadline, options.WithDeadline(deadline).Deadline.Value);
+
+ var token = new CancellationTokenSource().Token;
+ Assert.AreEqual(token, options.WithCancellationToken(token).CancellationToken);
+
+ // Change original instance is unchanged.
+ Assert.IsNull(options.Headers);
+ Assert.IsNull(options.Deadline);
+ Assert.AreEqual(CancellationToken.None, options.CancellationToken);
+ Assert.IsNull(options.WriteOptions);
+ Assert.IsNull(options.PropagationToken);
+ Assert.IsNull(options.Credentials);
+ }
+
+ [Test]
+ public void Normalize()
+ {
+ Assert.AreSame(Metadata.Empty, new CallOptions().Normalize().Headers);
+ Assert.AreEqual(DateTime.MaxValue, new CallOptions().Normalize().Deadline.Value);
+
+ var deadline = DateTime.UtcNow;
+ var propagationToken1 = new ContextPropagationToken(CallSafeHandle.NullInstance, deadline, CancellationToken.None,
+ new ContextPropagationOptions(propagateDeadline: true, propagateCancellation: false));
+ Assert.AreEqual(deadline, new CallOptions(propagationToken: propagationToken1).Normalize().Deadline.Value);
+ Assert.Throws(typeof(ArgumentException), () => new CallOptions(deadline: deadline, propagationToken: propagationToken1).Normalize());
+
+ var token = new CancellationTokenSource().Token;
+ var propagationToken2 = new ContextPropagationToken(CallSafeHandle.NullInstance, deadline, token,
+ new ContextPropagationOptions(propagateDeadline: false, propagateCancellation: true));
+ Assert.AreEqual(token, new CallOptions(propagationToken: propagationToken2).Normalize().CancellationToken);
+ Assert.Throws(typeof(ArgumentException), () => new CallOptions(cancellationToken: token, propagationToken: propagationToken2).Normalize());
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs b/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs
index 52be77c846..d2b5a436fd 100644
--- a/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs
@@ -38,7 +38,7 @@ using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
-namespace Grpc.Core.Internal.Tests
+namespace Grpc.Core.Tests
{
public class ChannelOptionsTest
{
diff --git a/src/csharp/Grpc.Core.Tests/ChannelTest.cs b/src/csharp/Grpc.Core.Tests/ChannelTest.cs
index f4ae9abefd..ed0ec14df5 100644
--- a/src/csharp/Grpc.Core.Tests/ChannelTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ChannelTest.cs
@@ -48,6 +48,17 @@ namespace Grpc.Core.Tests
}
[Test]
+ public void Constructor_RejectsDuplicateOptions()
+ {
+ var options = new ChannelOption[]
+ {
+ new ChannelOption(ChannelOptions.PrimaryUserAgentString, "ABC"),
+ new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ")
+ };
+ Assert.Throws(typeof(ArgumentException), () => new Channel("127.0.0.1", ChannelCredentials.Insecure, options));
+ }
+
+ [Test]
public void State_IdleAfterCreation()
{
var channel = new Channel("localhost", ChannelCredentials.Insecure);
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 25a5a27c8e..77f6a63156 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -32,6 +32,7 @@
#endregion
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
@@ -144,6 +145,45 @@ namespace Grpc.Core.Tests
var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall());
await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" });
Assert.AreEqual("ABC", await call.ResponseAsync);
+
+ Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode);
+ Assert.IsNotNull(call.GetTrailers());
+ }
+
+ [Test]
+ public async Task ServerStreamingCall()
+ {
+ helper.ServerStreamingHandler = new ServerStreamingServerMethod<string, string>(async (request, responseStream, context) =>
+ {
+ await responseStream.WriteAllAsync(request.Split(new []{' '}));
+ context.ResponseTrailers.Add("xyz", "");
+ });
+
+ var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "A B C");
+ CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, await call.ResponseStream.ToListAsync());
+
+ Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode);
+ Assert.IsNotNull("xyz", call.GetTrailers()[0].Key);
+ }
+
+ [Test]
+ public async Task DuplexStreamingCall()
+ {
+ helper.DuplexStreamingHandler = new DuplexStreamingServerMethod<string, string>(async (requestStream, responseStream, context) =>
+ {
+ while (await requestStream.MoveNext())
+ {
+ await responseStream.WriteAsync(requestStream.Current);
+ }
+ context.ResponseTrailers.Add("xyz", "xyz-value");
+ });
+
+ var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall());
+ await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" });
+ CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, await call.ResponseStream.ToListAsync());
+
+ Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode);
+ Assert.IsNotNull("xyz-value", call.GetTrailers()[0].Value);
}
[Test]
@@ -201,7 +241,7 @@ namespace Grpc.Core.Tests
Assert.AreEqual(headers[1].Key, trailers[1].Key);
CollectionAssert.AreEqual(headers[1].ValueBytes, trailers[1].ValueBytes);
}
-
+
[Test]
public void UnknownMethodHandler()
{
@@ -219,27 +259,27 @@ namespace Grpc.Core.Tests
}
[Test]
- public void UserAgentStringPresent()
+ public void ServerCallContext_PeerInfoPresent()
{
helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
{
- return context.RequestHeaders.Where(entry => entry.Key == "user-agent").Single().Value;
+ return context.Peer;
});
- string userAgent = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc");
- Assert.IsTrue(userAgent.StartsWith("grpc-csharp/"));
+ string peer = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc");
+ Assert.IsTrue(peer.Contains(Host));
}
[Test]
- public void PeerInfoPresent()
+ public void ServerCallContext_HostAndMethodPresent()
{
helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
{
- return context.Peer;
+ Assert.IsTrue(context.Host.Contains(Host));
+ Assert.AreEqual("/tests.Test/Unary", context.Method);
+ return "PASS";
});
-
- string peer = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc");
- Assert.IsTrue(peer.Contains(Host));
+ Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
}
[Test]
diff --git a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
index 2db3f286f7..90c510ec61 100644
--- a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs
@@ -69,11 +69,19 @@ namespace Grpc.Core.Tests
[Test]
public async Task PropagateCancellation()
{
+ var readyToCancelTcs = new TaskCompletionSource<object>();
+ var successTcs = new TaskCompletionSource<string>();
+
helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
{
- // check that we didn't obtain the default cancellation token.
- Assert.IsTrue(context.CancellationToken.CanBeCanceled);
- return "PASS";
+ readyToCancelTcs.SetResult(null); // child call running, ready to parent call
+
+ while (!context.CancellationToken.IsCancellationRequested)
+ {
+ await Task.Delay(10);
+ }
+ successTcs.SetResult("CHILD_CALL_CANCELLED");
+ return "";
});
helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
@@ -82,13 +90,23 @@ namespace Grpc.Core.Tests
Assert.IsNotNull(propagationToken.ParentCall);
var callOptions = new CallOptions(propagationToken: propagationToken);
- return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz");
+ try
+ {
+ await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz");
+ }
+ catch(RpcException)
+ {
+ // Child call will get cancelled, eat the exception.
+ }
+ return "";
});
var cts = new CancellationTokenSource();
- var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token)));
- await call.RequestStream.CompleteAsync();
- Assert.AreEqual("PASS", await call);
+ var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token)));
+ await readyToCancelTcs.Task;
+ cts.Cancel();
+ Assert.Throws(typeof(RpcException), async () => await parentCall);
+ Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task);
}
[Test]
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index e5ffa31989..475c792347 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -64,6 +64,8 @@
<Link>Version.cs</Link>
</Compile>
<Compile Include="CallCredentialsTest.cs" />
+ <Compile Include="CallOptionsTest.cs" />
+ <Compile Include="UserAgentStringTest.cs" />
<Compile Include="FakeCredentials.cs" />
<Compile Include="MarshallingErrorsTest.cs" />
<Compile Include="ChannelCredentialsTest.cs" />
@@ -89,6 +91,7 @@
<Compile Include="ContextPropagationTest.cs" />
<Compile Include="MetadataTest.cs" />
<Compile Include="PerformanceTest.cs" />
+ <Compile Include="SanityTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
index 9be5450d81..74f7f2497a 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
@@ -82,17 +82,17 @@ namespace Grpc.Core.Internal.Tests
public void ToDateTime()
{
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
- new Timespec(IntPtr.Zero, 0).ToDateTime());
+ new Timespec(0, 0).ToDateTime());
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50),
- new Timespec(new IntPtr(10), 5000).ToDateTime());
+ new Timespec(10, 5000).ToDateTime());
Assert.AreEqual(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc),
- new Timespec(new IntPtr(1437452508), 0).ToDateTime());
+ new Timespec(1437452508, 0).ToDateTime());
// before epoch
Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10),
- new Timespec(new IntPtr(-5), 1000).ToDateTime());
+ new Timespec(-5, 1000).ToDateTime());
// infinity
Assert.AreEqual(DateTime.MaxValue, Timespec.InfFuture.ToDateTime());
@@ -100,80 +100,62 @@ namespace Grpc.Core.Internal.Tests
// nanos are rounded to ticks are rounded up
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(1),
- new Timespec(IntPtr.Zero, 99).ToDateTime());
+ new Timespec(0, 99).ToDateTime());
// Illegal inputs
Assert.Throws(typeof(InvalidOperationException),
- () => new Timespec(new IntPtr(0), -2).ToDateTime());
+ () => new Timespec(0, -2).ToDateTime());
Assert.Throws(typeof(InvalidOperationException),
- () => new Timespec(new IntPtr(0), 1000 * 1000 * 1000).ToDateTime());
+ () => new Timespec(0, 1000 * 1000 * 1000).ToDateTime());
Assert.Throws(typeof(InvalidOperationException),
- () => new Timespec(new IntPtr(0), 0, GPRClockType.Monotonic).ToDateTime());
+ () => new Timespec(0, 0, GPRClockType.Monotonic).ToDateTime());
}
[Test]
public void ToDateTime_ReturnsUtc()
{
- Assert.AreEqual(DateTimeKind.Utc, new Timespec(new IntPtr(1437452508), 0).ToDateTime().Kind);
- Assert.AreNotEqual(DateTimeKind.Unspecified, new Timespec(new IntPtr(1437452508), 0).ToDateTime().Kind);
+ Assert.AreEqual(DateTimeKind.Utc, new Timespec(1437452508, 0).ToDateTime().Kind);
+ Assert.AreNotEqual(DateTimeKind.Unspecified, new Timespec(1437452508, 0).ToDateTime().Kind);
}
[Test]
public void ToDateTime_Overflow()
- {
- // we can only get overflow in ticks arithmetic on 64-bit
- if (IntPtr.Size == 8)
- {
- var timespec = new Timespec(new IntPtr(long.MaxValue - 100), 0);
- Assert.AreNotEqual(Timespec.InfFuture, timespec);
- Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime());
-
- Assert.AreEqual(DateTime.MinValue, new Timespec(new IntPtr(long.MinValue + 100), 0).ToDateTime());
- }
- else
- {
- Console.WriteLine("Test cannot be run on this platform, skipping the test.");
- }
+ {
+ var timespec = new Timespec(long.MaxValue - 100, 0);
+ Assert.AreNotEqual(Timespec.InfFuture, timespec);
+ Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime());
+
+ Assert.AreEqual(DateTime.MinValue, new Timespec(long.MinValue + 100, 0).ToDateTime());
}
[Test]
public void ToDateTime_OutOfDateTimeRange()
{
- // we can only get out of range on 64-bit, on 32 bit the max
- // timestamp is ~ Jan 19 2038, which is far within range of DateTime
- // same case for min value.
- if (IntPtr.Size == 8)
- {
- // DateTime range goes up to year 9999, 20000 years from now should
- // be out of range.
- long seconds = 20000L * 365L * 24L * 3600L;
-
- var timespec = new Timespec(new IntPtr(seconds), 0);
- Assert.AreNotEqual(Timespec.InfFuture, timespec);
- Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime());
-
- Assert.AreEqual(DateTime.MinValue, new Timespec(new IntPtr(-seconds), 0).ToDateTime());
- }
- else
- {
- Console.WriteLine("Test cannot be run on this platform, skipping the test");
- }
+ // DateTime range goes up to year 9999, 20000 years from now should
+ // be out of range.
+ long seconds = 20000L * 365L * 24L * 3600L;
+
+ var timespec = new Timespec(seconds, 0);
+ Assert.AreNotEqual(Timespec.InfFuture, timespec);
+ Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime());
+
+ Assert.AreEqual(DateTime.MinValue, new Timespec(-seconds, 0).ToDateTime());
}
[Test]
public void FromDateTime()
{
- Assert.AreEqual(new Timespec(IntPtr.Zero, 0),
+ Assert.AreEqual(new Timespec(0, 0),
Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
- Assert.AreEqual(new Timespec(new IntPtr(10), 5000),
+ Assert.AreEqual(new Timespec(10, 5000),
Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50)));
- Assert.AreEqual(new Timespec(new IntPtr(1437452508), 0),
+ Assert.AreEqual(new Timespec(1437452508, 0),
Timespec.FromDateTime(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc)));
// before epoch
- Assert.AreEqual(new Timespec(new IntPtr(-5), 1000),
+ Assert.AreEqual(new Timespec(-5, 1000),
Timespec.FromDateTime(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10)));
// infinity
@@ -184,34 +166,19 @@ namespace Grpc.Core.Internal.Tests
Assert.Throws(typeof(ArgumentException),
() => Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified)));
}
-
- [Test]
- public void FromDateTime_OutOfTimespecRange()
- {
- // we can only get overflow in Timespec on 32-bit
- if (IntPtr.Size == 4)
- {
- Assert.AreEqual(Timespec.InfFuture, Timespec.FromDateTime(new DateTime(2040, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
- Assert.AreEqual(Timespec.InfPast, Timespec.FromDateTime(new DateTime(1800, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
- }
- else
- {
- Console.WriteLine("Test cannot be run on this platform, skipping the test.");
- }
- }
- // Test attribute commented out to prevent running as part of the default test suite.
- // [Test]
- // [Category("Performance")]
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public void NowBenchmark()
{
// approx Timespec.Now latency <33ns
BenchmarkUtil.RunBenchmark(10000000, 1000000000, () => { var now = Timespec.Now; });
}
-
- // Test attribute commented out to prevent running as part of the default test suite.
- // [Test]
- // [Category("Performance")]
+
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public void PreciseNowBenchmark()
{
// approx Timespec.PreciseNow latency <18ns (when compiled with GRPC_TIMERS_RDTSC)
diff --git a/src/csharp/Grpc.Core.Tests/MetadataTest.cs b/src/csharp/Grpc.Core.Tests/MetadataTest.cs
index ddeb7d0926..49e9de1174 100644
--- a/src/csharp/Grpc.Core.Tests/MetadataTest.cs
+++ b/src/csharp/Grpc.Core.Tests/MetadataTest.cs
@@ -127,5 +127,118 @@ namespace Grpc.Core.Tests
Assert.Throws(typeof(InvalidOperationException), () => { var v = entry.Value; });
CollectionAssert.AreEqual(bytes, entry.ValueBytes);
}
+
+ [Test]
+ public void IndexOf()
+ {
+ var metadata = CreateMetadata();
+ Assert.AreEqual(0, metadata.IndexOf(metadata[0]));
+ Assert.AreEqual(1, metadata.IndexOf(metadata[1]));
+ }
+
+ [Test]
+ public void Insert()
+ {
+ var metadata = CreateMetadata();
+ metadata.Insert(0, new Metadata.Entry("new-key", "new-value"));
+ Assert.AreEqual(3, metadata.Count);
+ Assert.AreEqual("new-key", metadata[0].Key);
+ Assert.AreEqual("abc", metadata[1].Key);
+ }
+
+ [Test]
+ public void RemoveAt()
+ {
+ var metadata = CreateMetadata();
+ metadata.RemoveAt(0);
+ Assert.AreEqual(1, metadata.Count);
+ Assert.AreEqual("xyz", metadata[0].Key);
+ }
+
+ [Test]
+ public void Remove()
+ {
+ var metadata = CreateMetadata();
+ metadata.Remove(metadata[0]);
+ Assert.AreEqual(1, metadata.Count);
+ Assert.AreEqual("xyz", metadata[0].Key);
+ }
+
+ [Test]
+ public void Indexer_Set()
+ {
+ var metadata = CreateMetadata();
+ var entry = new Metadata.Entry("new-key", "new-value");
+
+ metadata[1] = entry;
+ Assert.AreEqual(entry, metadata[1]);
+ }
+
+ [Test]
+ public void Clear()
+ {
+ var metadata = CreateMetadata();
+ metadata.Clear();
+ Assert.AreEqual(0, metadata.Count);
+ }
+
+ [Test]
+ public void Contains()
+ {
+ var metadata = CreateMetadata();
+ Assert.IsTrue(metadata.Contains(metadata[0]));
+ Assert.IsFalse(metadata.Contains(new Metadata.Entry("new-key", "new-value")));
+ }
+
+ [Test]
+ public void CopyTo()
+ {
+ var metadata = CreateMetadata();
+ var array = new Metadata.Entry[metadata.Count + 1];
+
+ metadata.CopyTo(array, 1);
+ Assert.AreEqual(default(Metadata.Entry), array[0]);
+ Assert.AreEqual(metadata[0], array[1]);
+ }
+
+ [Test]
+ public void IEnumerableGetEnumerator()
+ {
+ var metadata = CreateMetadata();
+ var enumerator = (metadata as System.Collections.IEnumerable).GetEnumerator();
+
+ int i = 0;
+ while (enumerator.MoveNext())
+ {
+ Assert.AreEqual(metadata[i], enumerator.Current);
+ i++;
+ }
+ }
+
+ [Test]
+ public void FreezeMakesReadOnly()
+ {
+ var entry = new Metadata.Entry("new-key", "new-value");
+ var metadata = CreateMetadata().Freeze();
+
+ Assert.IsTrue(metadata.IsReadOnly);
+ Assert.Throws<InvalidOperationException>(() => metadata.Insert(0, entry));
+ Assert.Throws<InvalidOperationException>(() => metadata.RemoveAt(0));
+ Assert.Throws<InvalidOperationException>(() => metadata[0] = entry);
+ Assert.Throws<InvalidOperationException>(() => metadata.Add(entry));
+ Assert.Throws<InvalidOperationException>(() => metadata.Add("new-key", "new-value"));
+ Assert.Throws<InvalidOperationException>(() => metadata.Add("new-key-bin", new byte[] { 0xaa }));
+ Assert.Throws<InvalidOperationException>(() => metadata.Clear());
+ Assert.Throws<InvalidOperationException>(() => metadata.Remove(metadata[0]));
+ }
+
+ private Metadata CreateMetadata()
+ {
+ return new Metadata
+ {
+ { "abc", "abc-value" },
+ { "xyz", "xyz-value" },
+ };
+ }
}
}
diff --git a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs
index 567e04eddc..3047314345 100644
--- a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs
+++ b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs
@@ -32,6 +32,7 @@
#endregion
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
@@ -52,6 +53,7 @@ namespace Grpc.Core.Tests
readonly string host;
readonly ServerServiceDefinition serviceDefinition;
+ readonly IEnumerable<ChannelOption> channelOptions;
readonly Method<string, string> unaryMethod;
readonly Method<string, string> clientStreamingMethod;
@@ -66,9 +68,10 @@ namespace Grpc.Core.Tests
Server server;
Channel channel;
- public MockServiceHelper(string host = null, Marshaller<string> marshaller = null)
+ public MockServiceHelper(string host = null, Marshaller<string> marshaller = null, IEnumerable<ChannelOption> channelOptions = null)
{
this.host = host ?? "localhost";
+ this.channelOptions = channelOptions;
marshaller = marshaller ?? Marshallers.StringMarshaller;
unaryMethod = new Method<string, string>(
@@ -154,7 +157,7 @@ namespace Grpc.Core.Tests
{
if (channel == null)
{
- channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure);
+ channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, channelOptions);
}
return channel;
}
diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
index 073c502daf..af55cb0566 100644
--- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
@@ -59,6 +59,8 @@ namespace Grpc.Core.Tests
[Test]
public void CompletionQueueCreateDestroyBenchmark()
{
+ GrpcEnvironment.AddRef(); // completion queue requires gRPC environment being initialized.
+
BenchmarkUtil.RunBenchmark(
10, 10,
() =>
@@ -66,6 +68,8 @@ namespace Grpc.Core.Tests
CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create();
cq.Dispose();
});
+
+ GrpcEnvironment.Release();
}
/// <summary>
diff --git a/src/csharp/Grpc.Core.Tests/PerformanceTest.cs b/src/csharp/Grpc.Core.Tests/PerformanceTest.cs
index 5516cd3377..6815839992 100644
--- a/src/csharp/Grpc.Core.Tests/PerformanceTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PerformanceTest.cs
@@ -67,10 +67,10 @@ namespace Grpc.Core.Tests
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
-
- // Test attribute commented out to prevent running as part of the default test suite.
- //[Test]
- //[Category("Performance")]
+
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public void UnaryCallPerformance()
{
var profiler = new BasicProfiler();
diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs
new file mode 100644
index 0000000000..343ab1e85a
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs
@@ -0,0 +1,125 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class SanityTest
+ {
+ /// <summary>
+ /// Because we depend on a native library, sometimes when things go wrong, the
+ /// entire NUnit test process crashes. To be able to track down problems better,
+ /// the NUnit tests are run by run_tests.py script in a separate process per test class.
+ /// The list of tests to run is stored in src/csharp/tests.json.
+ /// This test checks that the tests.json file is up to date by discovering all the
+ /// existing NUnit tests in all test assemblies and comparing to contents of tests.json.
+ /// </summary>
+ [Test]
+ public void TestsJsonUpToDate()
+ {
+ var testClasses = DiscoverAllTestClasses();
+ string testsJson = GetTestsJson();
+
+ // we don't have a JSON parser at hand, but check that the test class
+ // name is contained in the file instead.
+ foreach (var className in testClasses) {
+ Assert.IsTrue(testsJson.Contains(className),
+ string.Format("Test class \"{0}\" is missing in C# tests.json file", className));
+ }
+ }
+
+ /// <summary>
+ /// Gets list of all test classes obtained by inspecting all the test assemblies.
+ /// </summary>
+ private List<string> DiscoverAllTestClasses()
+ {
+ var assemblies = GetTestAssemblies();
+
+ var testClasses = new List<string>();
+ foreach (var assembly in assemblies)
+ {
+ foreach (var t in assembly.GetTypes())
+ {
+ foreach (var m in t.GetMethods())
+ {
+ var attributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true);
+ if (attributes.Length > 0)
+ {
+ testClasses.Add(t.FullName);
+ break;
+ }
+
+ }
+ }
+ }
+ testClasses.Sort();
+ return testClasses;
+ }
+
+ private string GetTestsJson()
+ {
+ var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ var testsJsonFile = Path.Combine(assemblyDir, "..", "..", "..", "tests.json");
+
+ return File.ReadAllText(testsJsonFile);
+ }
+
+ private List<Assembly> GetTestAssemblies()
+ {
+ var result = new List<Assembly>();
+ var executingAssembly = Assembly.GetExecutingAssembly();
+
+ result.Add(executingAssembly);
+
+ var otherAssemblies = new[] {
+ "Grpc.Examples.Tests",
+ "Grpc.HealthCheck.Tests",
+ "Grpc.IntegrationTesting"
+ };
+ foreach (var assemblyName in otherAssemblies)
+ {
+ var location = executingAssembly.Location.Replace("Grpc.Core.Tests", assemblyName);
+ result.Add(Assembly.LoadFrom(location));
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
index a2be7ddd5e..10d666d109 100644
--- a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
@@ -61,17 +61,20 @@ namespace Grpc.Core.Tests
}
[Test]
- public async Task AbandonedCall()
+ public async Task AbandonedCall_ServerKillAsync()
{
+ var readyToShutdown = new TaskCompletionSource<object>();
helper.DuplexStreamingHandler = new DuplexStreamingServerMethod<string, string>(async (requestStream, responseStream, context) =>
{
+ readyToShutdown.SetResult(null);
await requestStream.ToListAsync();
});
- var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall(new CallOptions(deadline: DateTime.UtcNow.AddMilliseconds(1))));
+ var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall());
+ await readyToShutdown.Task; // make sure handler is running
- channel.ShutdownAsync().Wait();
- server.ShutdownAsync().Wait();
+ await channel.ShutdownAsync(); // channel.ShutdownAsync() works even if there's a pending call.
+ await server.KillAsync(); // server.ShutdownAsync() would hang waiting for the call to finish.
}
}
}
diff --git a/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs b/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs
new file mode 100644
index 0000000000..cc830086a6
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs
@@ -0,0 +1,101 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Profiling;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class UserAgentStringTest
+ {
+ const string Host = "127.0.0.1";
+
+ MockServiceHelper helper;
+ Server server;
+ Channel channel;
+
+ [TearDown]
+ public void Cleanup()
+ {
+ channel.ShutdownAsync().Wait();
+ server.ShutdownAsync().Wait();
+ }
+
+ [Test]
+ public void DefaultUserAgentString()
+ {
+ helper = new MockServiceHelper(Host);
+ server = helper.GetServer();
+ server.Start();
+ channel = helper.GetChannel();
+
+ helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+ {
+ var userAgentString = context.RequestHeaders.First(m => (m.Key == "user-agent")).Value;
+ var parts = userAgentString.Split(new [] {' '}, 2);
+ Assert.AreEqual(string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion), parts[0]);
+ Assert.IsTrue(parts[1].StartsWith("grpc-c/"));
+ return Task.FromResult("PASS");
+ });
+ Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), ""));
+ }
+
+ [Test]
+ public void ApplicationUserAgentString()
+ {
+ helper = new MockServiceHelper(Host,
+ channelOptions: new[] { new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ") });
+ server = helper.GetServer();
+ server.Start();
+ channel = helper.GetChannel();
+
+ channel = helper.GetChannel();
+ helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+ {
+ var userAgentString = context.RequestHeaders.First(m => (m.Key == "user-agent")).Value;
+ var parts = userAgentString.Split(new[] { ' ' }, 3);
+ Assert.AreEqual("XYZ", parts[0]);
+ return Task.FromResult("PASS");
+ });
+ Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), ""));
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs
index c0f94c63c2..1fda80cb90 100644
--- a/src/csharp/Grpc.Core/CallOptions.cs
+++ b/src/csharp/Grpc.Core/CallOptions.cs
@@ -184,6 +184,7 @@ namespace Grpc.Core
{
Preconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled,
"Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value.");
+ newOptions.cancellationToken = propagationToken.ParentCancellationToken;
}
}
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index f5eec969f5..d8d43c7998 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -32,8 +32,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.InteropServices;
-using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
@@ -57,7 +55,7 @@ namespace Grpc.Core
readonly string target;
readonly GrpcEnvironment environment;
readonly ChannelSafeHandle handle;
- readonly List<ChannelOption> options;
+ readonly Dictionary<string, ChannelOption> options;
bool shutdownRequested;
@@ -71,12 +69,12 @@ namespace Grpc.Core
public Channel(string target, ChannelCredentials credentials, IEnumerable<ChannelOption> options = null)
{
this.target = Preconditions.CheckNotNull(target, "target");
+ this.options = CreateOptionsDictionary(options);
+ EnsureUserAgentChannelOption(this.options);
this.environment = GrpcEnvironment.AddRef();
- this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();
- EnsureUserAgentChannelOption(this.options);
using (var nativeCredentials = credentials.ToNativeCredentials())
- using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options))
+ using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options.Values))
{
if (nativeCredentials != null)
{
@@ -173,7 +171,7 @@ namespace Grpc.Core
{
throw new OperationCanceledException("Channel has reached FatalFailure state.");
}
- await WaitForStateChangedAsync(currentState, deadline);
+ await WaitForStateChangedAsync(currentState, deadline).ConfigureAwait(false);
currentState = handle.CheckConnectivityState(false);
}
}
@@ -198,7 +196,7 @@ namespace Grpc.Core
handle.Dispose();
- await Task.Run(() => GrpcEnvironment.Release());
+ await Task.Run(() => GrpcEnvironment.Release()).ConfigureAwait(false);
}
internal ChannelSafeHandle Handle
@@ -233,18 +231,36 @@ namespace Grpc.Core
activeCallCounter.Decrement();
}
- private static void EnsureUserAgentChannelOption(List<ChannelOption> options)
+ private static void EnsureUserAgentChannelOption(Dictionary<string, ChannelOption> options)
{
- if (!options.Any((option) => option.Name == ChannelOptions.PrimaryUserAgentString))
+ var key = ChannelOptions.PrimaryUserAgentString;
+ var userAgentString = "";
+
+ ChannelOption option;
+ if (options.TryGetValue(key, out option))
{
- options.Add(new ChannelOption(ChannelOptions.PrimaryUserAgentString, GetUserAgentString()));
- }
+ // user-provided userAgentString needs to be at the beginning
+ userAgentString = option.StringValue + " ";
+ };
+
+ // TODO(jtattermusch): it would be useful to also provide .NET/mono version.
+ userAgentString += string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion);
+
+ options[ChannelOptions.PrimaryUserAgentString] = new ChannelOption(key, userAgentString);
}
- private static string GetUserAgentString()
+ private static Dictionary<string, ChannelOption> CreateOptionsDictionary(IEnumerable<ChannelOption> options)
{
- // TODO(jtattermusch): it would be useful to also provide .NET/mono version.
- return string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion);
+ var dict = new Dictionary<string, ChannelOption>();
+ if (options == null)
+ {
+ return dict;
+ }
+ foreach (var option in options)
+ {
+ dict.Add(option.Name, option);
+ }
+ return dict;
}
}
}
diff --git a/src/csharp/Grpc.Core/ChannelOptions.cs b/src/csharp/Grpc.Core/ChannelOptions.cs
index f5ef63af54..d70673cf78 100644
--- a/src/csharp/Grpc.Core/ChannelOptions.cs
+++ b/src/csharp/Grpc.Core/ChannelOptions.cs
@@ -169,7 +169,7 @@ namespace Grpc.Core
/// Creates native object for a collection of channel options.
/// </summary>
/// <returns>The native channel arguments.</returns>
- internal static ChannelArgsSafeHandle CreateChannelArgs(List<ChannelOption> options)
+ internal static ChannelArgsSafeHandle CreateChannelArgs(ICollection<ChannelOption> options)
{
if (options == null || options.Count == 0)
{
@@ -179,9 +179,9 @@ namespace Grpc.Core
try
{
nativeArgs = ChannelArgsSafeHandle.Create(options.Count);
- for (int i = 0; i < options.Count; i++)
+ int i = 0;
+ foreach (var option in options)
{
- var option = options[i];
if (option.Type == ChannelOption.OptionType.Integer)
{
nativeArgs.SetInteger(i, option.Name, option.IntValue);
@@ -194,6 +194,7 @@ namespace Grpc.Core
{
throw new InvalidOperationException("Unknown option type");
}
+ i++;
}
return nativeArgs;
}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 486e47945c..5b3da7c6c9 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" />
- <Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -10,7 +8,7 @@
<RootNamespace>Grpc.Core</RootNamespace>
<AssemblyName>Grpc.Core</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <NuGetPackageImportStamp>8bb563fb</NuGetPackageImportStamp>
+ <NuGetPackageImportStamp>be3e9d03</NuGetPackageImportStamp>
<DocumentationFile>bin\$(Configuration)\Grpc.Core.Xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -148,13 +146,11 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
- <Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props'))" />
- <Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets'))" />
- <Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props'))" />
- <Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets'))" />
+ <Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.openssl.redist.targets'))" />
+ <Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.zlib.redist.targets'))" />
</Target>
- <Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
- <Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
+ <Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.openssl.redist.targets')" />
+ <Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\portable-net45+netcore45+wpa81+wp8\grpc.dependencies.zlib.redist.targets')" />
<ItemGroup />
<ItemGroup />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 953f61aa1e..92f8d77e85 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -238,20 +238,6 @@ namespace Grpc.Core.Internal
}
}
- protected Exception TrySerialize(TWrite msg, out byte[] payload)
- {
- try
- {
- payload = serializer(msg);
- return null;
- }
- catch (Exception e)
- {
- payload = null;
- return e;
- }
- }
-
protected Exception TryDeserialize(byte[] payload, out TRead msg)
{
using (Profilers.ForCurrentThread().NewScope("AsyncCallBase.TryDeserialize"))
diff --git a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
index b4a7335c7c..d6e34a0f04 100644
--- a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
@@ -70,12 +70,12 @@ namespace Grpc.Core.Internal
}
var taskSource = new AsyncCompletionTaskSource<TResponse>();
call.StartReadMessage(taskSource.CompletionDelegate);
- var result = await taskSource.Task;
+ var result = await taskSource.Task.ConfigureAwait(false);
this.current = result;
if (result == null)
{
- await call.StreamingCallFinishedTask;
+ await call.StreamingCallFinishedTask.ConfigureAwait(false);
return false;
}
return true;
diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
index 69a7cd98cb..8bb646d303 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
@@ -97,7 +97,7 @@ namespace Grpc.Core.Internal
try
{
var metadata = new Metadata();
- await interceptor(context, metadata);
+ await interceptor(context, metadata).ConfigureAwait(false);
using (var metadataArray = MetadataArraySafeHandle.Create(metadata))
{
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 59f4c5727c..de66759b94 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -78,13 +78,13 @@ namespace Grpc.Core.Internal
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken);
try
{
- Preconditions.CheckArgument(await requestStream.MoveNext());
+ Preconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false));
var request = requestStream.Current;
// TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated.
- Preconditions.CheckArgument(!await requestStream.MoveNext());
- var result = await handler(request, context);
+ Preconditions.CheckArgument(!await requestStream.MoveNext().ConfigureAwait(false));
+ var result = await handler(request, context).ConfigureAwait(false);
status = context.Status;
- await responseStream.WriteAsync(result);
+ await responseStream.WriteAsync(result).ConfigureAwait(false);
}
catch (Exception e)
{
@@ -93,13 +93,13 @@ namespace Grpc.Core.Internal
}
try
{
- await responseStream.WriteStatusAsync(status, context.ResponseTrailers);
+ await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// Call has been already cancelled.
}
- await finishedTask;
+ await finishedTask.ConfigureAwait(false);
}
}
@@ -134,11 +134,11 @@ namespace Grpc.Core.Internal
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken);
try
{
- Preconditions.CheckArgument(await requestStream.MoveNext());
+ Preconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false));
var request = requestStream.Current;
// TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated.
- Preconditions.CheckArgument(!await requestStream.MoveNext());
- await handler(request, responseStream, context);
+ Preconditions.CheckArgument(!await requestStream.MoveNext().ConfigureAwait(false));
+ await handler(request, responseStream, context).ConfigureAwait(false);
status = context.Status;
}
catch (Exception e)
@@ -149,13 +149,13 @@ namespace Grpc.Core.Internal
try
{
- await responseStream.WriteStatusAsync(status, context.ResponseTrailers);
+ await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// Call has been already cancelled.
}
- await finishedTask;
+ await finishedTask.ConfigureAwait(false);
}
}
@@ -190,11 +190,11 @@ namespace Grpc.Core.Internal
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken);
try
{
- var result = await handler(requestStream, context);
+ var result = await handler(requestStream, context).ConfigureAwait(false);
status = context.Status;
try
{
- await responseStream.WriteAsync(result);
+ await responseStream.WriteAsync(result).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -209,13 +209,13 @@ namespace Grpc.Core.Internal
try
{
- await responseStream.WriteStatusAsync(status, context.ResponseTrailers);
+ await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// Call has been already cancelled.
}
- await finishedTask;
+ await finishedTask.ConfigureAwait(false);
}
}
@@ -250,7 +250,7 @@ namespace Grpc.Core.Internal
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken);
try
{
- await handler(requestStream, responseStream, context);
+ await handler(requestStream, responseStream, context).ConfigureAwait(false);
status = context.Status;
}
catch (Exception e)
@@ -260,13 +260,13 @@ namespace Grpc.Core.Internal
}
try
{
- await responseStream.WriteStatusAsync(status, context.ResponseTrailers);
+ await responseStream.WriteStatusAsync(status, context.ResponseTrailers).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// Call has been already cancelled.
}
- await finishedTask;
+ await finishedTask.ConfigureAwait(false);
}
}
@@ -284,8 +284,8 @@ namespace Grpc.Core.Internal
var finishedTask = asyncCall.ServerSideCallAsync();
var responseStream = new ServerResponseStream<byte[], byte[]>(asyncCall);
- await responseStream.WriteStatusAsync(new Status(StatusCode.Unimplemented, "No such method."), Metadata.Empty);
- await finishedTask;
+ await responseStream.WriteStatusAsync(new Status(StatusCode.Unimplemented, ""), Metadata.Empty).ConfigureAwait(false);
+ await finishedTask.ConfigureAwait(false);
}
}
diff --git a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs
index 3fccb88abb..e7be82c318 100644
--- a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs
@@ -70,7 +70,7 @@ namespace Grpc.Core.Internal
}
var taskSource = new AsyncCompletionTaskSource<TRequest>();
call.StartReadMessage(taskSource.CompletionDelegate);
- var result = await taskSource.Task;
+ var result = await taskSource.Task.ConfigureAwait(false);
this.current = result;
return result != null;
}
diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs
index 38fc067d9f..3031175c8a 100644
--- a/src/csharp/Grpc.Core/Internal/Timespec.cs
+++ b/src/csharp/Grpc.Core/Internal/Timespec.cs
@@ -63,20 +63,18 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern int gprsharp_sizeof_timespec();
- public Timespec(IntPtr tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, GPRClockType.Realtime)
+ public Timespec(long tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, GPRClockType.Realtime)
{
}
- public Timespec(IntPtr tv_sec, int tv_nsec, GPRClockType clock_type)
+ public Timespec(long tv_sec, int tv_nsec, GPRClockType clock_type)
{
this.tv_sec = tv_sec;
this.tv_nsec = tv_nsec;
this.clock_type = clock_type;
}
- // NOTE: on linux 64bit sizeof(gpr_timespec) = 16, on windows 32bit sizeof(gpr_timespec) = 8
- // so IntPtr seems to have the right size to work on both.
- private System.IntPtr tv_sec;
+ private long tv_sec;
private int tv_nsec;
private GPRClockType clock_type;
@@ -116,7 +114,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Seconds since unix epoch.
/// </summary>
- public IntPtr TimevalSeconds
+ public long TimevalSeconds
{
get
{
@@ -176,18 +174,18 @@ namespace Grpc.Core.Internal
{
// convert nanos to ticks, round up to the nearest tick
long ticksFromNanos = tv_nsec / NanosPerTick + ((tv_nsec % NanosPerTick != 0) ? 1 : 0);
- long ticksTotal = checked(tv_sec.ToInt64() * TicksPerSecond + ticksFromNanos);
+ long ticksTotal = checked(tv_sec * TicksPerSecond + ticksFromNanos);
return UnixEpoch.AddTicks(ticksTotal);
}
catch (OverflowException)
{
// ticks out of long range
- return tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue;
+ return tv_sec > 0 ? DateTime.MaxValue : DateTime.MinValue;
}
catch (ArgumentOutOfRangeException)
{
// resulting date time would be larger than MaxValue
- return tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue;
+ return tv_sec > 0 ? DateTime.MaxValue : DateTime.MinValue;
}
}
@@ -226,12 +224,7 @@ namespace Grpc.Core.Internal
seconds--;
nanos += (int)NanosPerSecond;
}
- // new IntPtr possibly throws OverflowException
- return new Timespec(new IntPtr(seconds), nanos);
- }
- catch (OverflowException)
- {
- return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast;
+ return new Timespec(seconds, nanos);
}
catch (ArgumentOutOfRangeException)
{
diff --git a/src/csharp/Grpc.Core/Profiling/IProfiler.cs b/src/csharp/Grpc.Core/Profiling/IProfiler.cs
index c426c365d2..e850375004 100644
--- a/src/csharp/Grpc.Core/Profiling/IProfiler.cs
+++ b/src/csharp/Grpc.Core/Profiling/IProfiler.cs
@@ -41,7 +41,9 @@ namespace Grpc.Core.Profiling
internal interface IProfiler
{
void Begin(string tag);
+
void End(string tag);
+
void Mark(string tag);
}
}
diff --git a/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs b/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
index 5cc4c3c054..792e3c3cd0 100644
--- a/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
+++ b/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
@@ -40,7 +40,8 @@ namespace Grpc.Core.Profiling
{
internal struct ProfilerEntry
{
- public enum Type {
+ public enum Type
+ {
BEGIN,
END,
MARK
diff --git a/src/csharp/Grpc.Core/Profiling/Profilers.cs b/src/csharp/Grpc.Core/Profiling/Profilers.cs
index c8123347f2..471ee20875 100644
--- a/src/csharp/Grpc.Core/Profiling/Profilers.cs
+++ b/src/csharp/Grpc.Core/Profiling/Profilers.cs
@@ -40,12 +40,12 @@ namespace Grpc.Core.Profiling
{
internal static class Profilers
{
- static readonly NopProfiler defaultProfiler = new NopProfiler();
+ static readonly NopProfiler DefaultProfiler = new NopProfiler();
static readonly ThreadLocal<IProfiler> profilers = new ThreadLocal<IProfiler>();
public static IProfiler ForCurrentThread()
{
- return profilers.Value ?? defaultProfiler;
+ return profilers.Value ?? DefaultProfiler;
}
public static void SetForCurrentThread(IProfiler profiler)
@@ -89,15 +89,18 @@ namespace Grpc.Core.Profiling
this.entries = new ProfilerEntry[capacity];
}
- public void Begin(string tag) {
+ public void Begin(string tag)
+ {
AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.BEGIN, tag));
}
- public void End(string tag) {
+ public void End(string tag)
+ {
AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.END, tag));
}
- public void Mark(string tag) {
+ public void Mark(string tag)
+ {
AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.MARK, tag));
}
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 7c94d21561..d120f95fdf 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -148,10 +148,10 @@ namespace Grpc.Core
}
handle.ShutdownAndNotify(HandleServerShutdown, environment);
- await shutdownTcs.Task;
+ await shutdownTcs.Task.ConfigureAwait(false);
DisposeHandle();
- await Task.Run(() => GrpcEnvironment.Release());
+ await Task.Run(() => GrpcEnvironment.Release()).ConfigureAwait(false);
}
/// <summary>
@@ -169,8 +169,10 @@ namespace Grpc.Core
handle.ShutdownAndNotify(HandleServerShutdown, environment);
handle.CancelAllCalls();
- await shutdownTcs.Task;
+ await shutdownTcs.Task.ConfigureAwait(false);
DisposeHandle();
+
+ await Task.Run(() => GrpcEnvironment.Release()).ConfigureAwait(false);
}
internal void AddCallReference(object call)
@@ -268,7 +270,7 @@ namespace Grpc.Core
{
callHandler = NoSuchMethodCallHandler.Instance;
}
- await callHandler.HandleCall(newRpc, environment);
+ await callHandler.HandleCall(newRpc, environment).ConfigureAwait(false);
}
catch (Exception e)
{
@@ -288,7 +290,7 @@ namespace Grpc.Core
// after server shutdown, the callback returns with null call
if (!newRpc.Call.IsInvalid)
{
- Task.Run(async () => await HandleCallAsync(newRpc));
+ Task.Run(async () => await HandleCallAsync(newRpc)).ConfigureAwait(false);
}
}
diff --git a/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs b/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs
index cdf1e51026..02a47568e7 100644
--- a/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs
+++ b/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs
@@ -48,9 +48,9 @@ namespace Grpc.Core.Utils
public static async Task ForEachAsync<T>(this IAsyncStreamReader<T> streamReader, Func<T, Task> asyncAction)
where T : class
{
- while (await streamReader.MoveNext())
+ while (await streamReader.MoveNext().ConfigureAwait(false))
{
- await asyncAction(streamReader.Current);
+ await asyncAction(streamReader.Current).ConfigureAwait(false);
}
}
@@ -61,7 +61,7 @@ namespace Grpc.Core.Utils
where T : class
{
var result = new List<T>();
- while (await streamReader.MoveNext())
+ while (await streamReader.MoveNext().ConfigureAwait(false))
{
result.Add(streamReader.Current);
}
@@ -77,11 +77,11 @@ namespace Grpc.Core.Utils
{
foreach (var element in elements)
{
- await streamWriter.WriteAsync(element);
+ await streamWriter.WriteAsync(element).ConfigureAwait(false);
}
if (complete)
{
- await streamWriter.CompleteAsync();
+ await streamWriter.CompleteAsync().ConfigureAwait(false);
}
}
@@ -93,7 +93,7 @@ namespace Grpc.Core.Utils
{
foreach (var element in elements)
{
- await streamWriter.WriteAsync(element);
+ await streamWriter.WriteAsync(element).ConfigureAwait(false);
}
}
}
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
index 9b12b9b096..89600744a7 100644
--- a/src/csharp/Grpc.Core/packages.config
+++ b/src/csharp/Grpc.Core/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
- <package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
+ <package id="grpc.dependencies.openssl.redist" version="1.0.204.1" targetFramework="net45" />
+ <package id="grpc.dependencies.zlib.redist" version="1.2.8.10" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index 55462e02fd..53b2bb78c4 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -66,6 +66,5 @@
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
- <None Include="proto\math.proto" />
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
index 8fce5d39aa..4e775a7a0c 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -65,7 +65,6 @@
<ItemGroup>
<None Include="Grpc.HealthCheck.nuspec" />
<None Include="packages.config" />
- <None Include="proto\health.proto" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
@@ -81,4 +80,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore b/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore
new file mode 100644
index 0000000000..a382af2294
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore
@@ -0,0 +1,3 @@
+bin
+obj
+
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
new file mode 100644
index 0000000000..342eead1a3
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
@@ -0,0 +1,63 @@
+<?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>{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Grpc.IntegrationTesting.QpsWorker</RootNamespace>
+ <AssemblyName>Grpc.IntegrationTesting.QpsWorker</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>C:\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>
+ <ItemGroup>
+ <None Include="app.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/proto/health.proto b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs
index 01aa3fcf57..308463337f 100644
--- a/src/csharp/Grpc.HealthCheck/proto/health.proto
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs
@@ -1,3 +1,5 @@
+#region Copyright notice and license
+
// Copyright 2015, Google Inc.
// All rights reserved.
//
@@ -27,26 +29,18 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// TODO(jtattermusch): switch to proto3 once C# supports that.
-syntax = "proto3";
-
-package grpc.health.v1alpha;
-option csharp_namespace = "Grpc.Health.V1Alpha";
+#endregion
-message HealthCheckRequest {
- string host = 1;
- string service = 2;
-}
+using System;
+using Grpc.IntegrationTesting;
-message HealthCheckResponse {
- enum ServingStatus {
- UNKNOWN = 0;
- SERVING = 1;
- NOT_SERVING = 2;
- }
- ServingStatus status = 1;
+namespace Grpc.IntegrationTesting
+{
+ class Program
+ {
+ public static void Main(string[] args)
+ {
+ QpsWorker.Run(args);
+ }
+ }
}
-
-service Health {
- rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
-} \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..aacfc16ef4
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.IntegrationTesting.QpsWorker")]
+[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.QpsWorker/app.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
new file mode 100644
index 0000000000..940d25cae3
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
new file mode 100644
index 0000000000..47a15224f1
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
@@ -0,0 +1,76 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+
+namespace Grpc.Testing
+{
+ /// <summary>
+ /// Implementation of BenchmarkService server
+ /// </summary>
+ public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService
+ {
+ private readonly int responseSize;
+
+ public BenchmarkServiceImpl(int responseSize)
+ {
+ this.responseSize = responseSize;
+ }
+
+ public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+ {
+ var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
+ return Task.FromResult(response);
+ }
+
+ public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
+ {
+ await requestStream.ForEachAsync(async request =>
+ {
+ var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
+ await responseStream.WriteAsync(response);
+ });
+ }
+
+ private static Payload CreateZerosPayload(int size)
+ {
+ return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
new file mode 100644
index 0000000000..e9e659cb1f
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
@@ -0,0 +1,153 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Helper methods to start client runners for performance testing.
+ /// </summary>
+ public static class ClientRunners
+ {
+ /// <summary>
+ /// Creates a started client runner.
+ /// </summary>
+ public static IClientRunner CreateStarted(ClientConfig config)
+ {
+ string target = config.ServerTargets.Single();
+ Grpc.Core.Utils.Preconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop);
+
+ var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
+ var channel = new Channel(target, credentials);
+
+ switch (config.RpcType)
+ {
+ case RpcType.UNARY:
+ return new SyncUnaryClientRunner(channel,
+ config.PayloadConfig.SimpleParams.ReqSize,
+ config.HistogramParams);
+
+ case RpcType.STREAMING:
+ default:
+ throw new ArgumentException("Unsupported RpcType.");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Client that starts synchronous unary calls in a closed loop.
+ /// </summary>
+ public class SyncUnaryClientRunner : IClientRunner
+ {
+ const double SecondsToNanos = 1e9;
+
+ readonly Channel channel;
+ readonly int payloadSize;
+ readonly Histogram histogram;
+
+ readonly BenchmarkService.IBenchmarkServiceClient client;
+ readonly Task runnerTask;
+ readonly CancellationTokenSource stoppedCts;
+ readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+
+ public SyncUnaryClientRunner(Channel channel, int payloadSize, HistogramParams histogramParams)
+ {
+ this.channel = Grpc.Core.Utils.Preconditions.CheckNotNull(channel);
+ this.payloadSize = payloadSize;
+ this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
+
+ this.stoppedCts = new CancellationTokenSource();
+ this.client = BenchmarkService.NewClient(channel);
+ this.runnerTask = Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning);
+ }
+
+ public ClientStats GetStats(bool reset)
+ {
+ var histogramData = histogram.GetSnapshot(reset);
+ var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
+
+ // TODO: populate user time and system time
+ return new ClientStats
+ {
+ Latencies = histogramData,
+ TimeElapsed = secondsElapsed,
+ TimeUser = 0,
+ TimeSystem = 0
+ };
+ }
+
+ public async Task StopAsync()
+ {
+ stoppedCts.Cancel();
+ await runnerTask;
+ await channel.ShutdownAsync();
+ }
+
+ private void Run()
+ {
+ var request = new SimpleRequest
+ {
+ Payload = CreateZerosPayload(payloadSize)
+ };
+ var stopwatch = new Stopwatch();
+
+ while (!stoppedCts.Token.IsCancellationRequested)
+ {
+ stopwatch.Restart();
+ client.UnaryCall(request);
+ stopwatch.Stop();
+
+ // spec requires data point in nanoseconds.
+ histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+ }
+ }
+
+ private static Payload CreateZerosPayload(int size)
+ {
+ return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
new file mode 100644
index 0000000000..4764e1072b
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -0,0 +1,2362 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: test/proto/benchmarks/control.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 {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Control {
+
+ #region Descriptor
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static Control() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CiN0ZXN0L3Byb3RvL2JlbmNobWFya3MvY29udHJvbC5wcm90bxIMZ3JwYy50",
+ "ZXN0aW5nGiR0ZXN0L3Byb3RvL2JlbmNobWFya3MvcGF5bG9hZHMucHJvdG8a",
+ "IXRlc3QvcHJvdG8vYmVuY2htYXJrcy9zdGF0cy5wcm90byIlCg1Qb2lzc29u",
+ "UGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASJBCg1Vbmlmb3JtUGFyYW1z",
+ "EhcKD2ludGVyYXJyaXZhbF9sbxgBIAEoARIXCg9pbnRlcmFycml2YWxfaGkY",
+ "AiABKAEiKwoTRGV0ZXJtaW5pc3RpY1BhcmFtcxIUCgxvZmZlcmVkX2xvYWQY",
+ "ASABKAEiOAoMUGFyZXRvUGFyYW1zEhkKEWludGVyYXJyaXZhbF9iYXNlGAEg",
+ "ASgBEg0KBWFscGhhGAIgASgBIhIKEENsb3NlZExvb3BQYXJhbXMijgIKCkxv",
+ "YWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5ncnBjLnRlc3Rpbmcu",
+ "Q2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiABKAsyGy5ncnBjLnRl",
+ "c3RpbmcuUG9pc3NvblBhcmFtc0gAEi4KB3VuaWZvcm0YAyABKAsyGy5ncnBj",
+ "LnRlc3RpbmcuVW5pZm9ybVBhcmFtc0gAEjMKBmRldGVybRgEIAEoCzIhLmdy",
+ "cGMudGVzdGluZy5EZXRlcm1pbmlzdGljUGFyYW1zSAASLAoGcGFyZXRvGAUg",
+ "ASgLMhouZ3JwYy50ZXN0aW5nLlBhcmV0b1BhcmFtc0gAQgYKBGxvYWQiQwoO",
+ "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
+ "X2hvc3Rfb3ZlcnJpZGUYAiABKAkirwMKDENsaWVudENvbmZpZxIWCg5zZXJ2",
+ "ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdycGMu",
+ "dGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEoCzIc",
+ "LmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGluZ19y",
+ "cGNzX3Blcl9jaGFubmVsGAQgASgFEhcKD2NsaWVudF9jaGFubmVscxgFIAEo",
+ "BRIcChRhc3luY19jbGllbnRfdGhyZWFkcxgHIAEoBRInCghycGNfdHlwZRgI",
+ "IAEoDjIVLmdycGMudGVzdGluZy5ScGNUeXBlEi0KC2xvYWRfcGFyYW1zGAog",
+ "ASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9jb25m",
+ "aWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBoaXN0",
+ "b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbVBh",
+ "cmFtcyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRl",
+ "c3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJoCgpD",
+ "bGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVu",
+ "dENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFya0gA",
+ "QgkKB2FyZ3R5cGUi9wEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlwZRgB",
+ "IAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5X3Bh",
+ "cmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIMCgRo",
+ "b3N0GAMgASgJEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVyX3RocmVh",
+ "ZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2FkX2NvbmZp",
+ "ZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnImgKClNlcnZl",
+ "ckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2VydmVyQ29u",
+ "ZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJrSABCCQoH",
+ "YXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBj",
+ "LnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVjb3JlcxgD",
+ "IAEoBSovCgpDbGllbnRUeXBlEg8KC1NZTkNfQ0xJRU5UEAASEAoMQVNZTkNf",
+ "Q0xJRU5UEAEqLwoKU2VydmVyVHlwZRIPCgtTWU5DX1NFUlZFUhAAEhAKDEFT",
+ "WU5DX1NFUlZFUhABKiMKB1JwY1R5cGUSCQoFVU5BUlkQABINCglTVFJFQU1J",
+ "TkcQAWIGcHJvdG8z"));
+ descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbr::FileDescriptor[] { global::Grpc.Testing.Payloads.Descriptor, global::Grpc.Testing.Stats.Descriptor, },
+ new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedCodeInfo[] {
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PoissonParams), new[]{ "OfferedLoad" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.UniformParams), new[]{ "InterarrivalLo", "InterarrivalHi" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.DeterministicParams), new[]{ "OfferedLoad" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ParetoParams), new[]{ "InterarrivalBase", "Alpha" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), null, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.LoadParams), new[]{ "ClosedLoop", "Poisson", "Uniform", "Determ", "Pareto" }, new[]{ "Load" }, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SecurityParams), new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStatus), new[]{ "Stats" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Mark), new[]{ "Reset" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientArgs), new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), new[]{ "ServerType", "SecurityParams", "Host", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerArgs), new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), new[]{ "Stats", "Port", "Cores" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Enums
+ public enum ClientType {
+ SYNC_CLIENT = 0,
+ ASYNC_CLIENT = 1,
+ }
+
+ public enum ServerType {
+ SYNC_SERVER = 0,
+ ASYNC_SERVER = 1,
+ }
+
+ public enum RpcType {
+ UNARY = 0,
+ STREAMING = 1,
+ }
+
+ #endregion
+
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
+ private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
+ public static pb::MessageParser<PoissonParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[0]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public PoissonParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public PoissonParams(PoissonParams other) : this() {
+ offeredLoad_ = other.offeredLoad_;
+ }
+
+ public PoissonParams Clone() {
+ return new PoissonParams(this);
+ }
+
+ public const int OfferedLoadFieldNumber = 1;
+ private double offeredLoad_;
+ public double OfferedLoad {
+ get { return offeredLoad_; }
+ set {
+ offeredLoad_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as PoissonParams);
+ }
+
+ public bool Equals(PoissonParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (OfferedLoad != other.OfferedLoad) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (OfferedLoad != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(OfferedLoad);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (OfferedLoad != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(PoissonParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.OfferedLoad != 0D) {
+ OfferedLoad = other.OfferedLoad;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ OfferedLoad = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class UniformParams : pb::IMessage<UniformParams> {
+ private static readonly pb::MessageParser<UniformParams> _parser = new pb::MessageParser<UniformParams>(() => new UniformParams());
+ public static pb::MessageParser<UniformParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[1]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public UniformParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public UniformParams(UniformParams other) : this() {
+ interarrivalLo_ = other.interarrivalLo_;
+ interarrivalHi_ = other.interarrivalHi_;
+ }
+
+ public UniformParams Clone() {
+ return new UniformParams(this);
+ }
+
+ public const int InterarrivalLoFieldNumber = 1;
+ private double interarrivalLo_;
+ public double InterarrivalLo {
+ get { return interarrivalLo_; }
+ set {
+ interarrivalLo_ = value;
+ }
+ }
+
+ public const int InterarrivalHiFieldNumber = 2;
+ private double interarrivalHi_;
+ public double InterarrivalHi {
+ get { return interarrivalHi_; }
+ set {
+ interarrivalHi_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as UniformParams);
+ }
+
+ public bool Equals(UniformParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (InterarrivalLo != other.InterarrivalLo) return false;
+ if (InterarrivalHi != other.InterarrivalHi) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (InterarrivalLo != 0D) hash ^= InterarrivalLo.GetHashCode();
+ if (InterarrivalHi != 0D) hash ^= InterarrivalHi.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (InterarrivalLo != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(InterarrivalLo);
+ }
+ if (InterarrivalHi != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(InterarrivalHi);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (InterarrivalLo != 0D) {
+ size += 1 + 8;
+ }
+ if (InterarrivalHi != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(UniformParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.InterarrivalLo != 0D) {
+ InterarrivalLo = other.InterarrivalLo;
+ }
+ if (other.InterarrivalHi != 0D) {
+ InterarrivalHi = other.InterarrivalHi;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ InterarrivalLo = input.ReadDouble();
+ break;
+ }
+ case 17: {
+ InterarrivalHi = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class DeterministicParams : pb::IMessage<DeterministicParams> {
+ private static readonly pb::MessageParser<DeterministicParams> _parser = new pb::MessageParser<DeterministicParams>(() => new DeterministicParams());
+ public static pb::MessageParser<DeterministicParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[2]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public DeterministicParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public DeterministicParams(DeterministicParams other) : this() {
+ offeredLoad_ = other.offeredLoad_;
+ }
+
+ public DeterministicParams Clone() {
+ return new DeterministicParams(this);
+ }
+
+ public const int OfferedLoadFieldNumber = 1;
+ private double offeredLoad_;
+ public double OfferedLoad {
+ get { return offeredLoad_; }
+ set {
+ offeredLoad_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as DeterministicParams);
+ }
+
+ public bool Equals(DeterministicParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (OfferedLoad != other.OfferedLoad) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (OfferedLoad != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(OfferedLoad);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (OfferedLoad != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(DeterministicParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.OfferedLoad != 0D) {
+ OfferedLoad = other.OfferedLoad;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ OfferedLoad = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ParetoParams : pb::IMessage<ParetoParams> {
+ private static readonly pb::MessageParser<ParetoParams> _parser = new pb::MessageParser<ParetoParams>(() => new ParetoParams());
+ public static pb::MessageParser<ParetoParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[3]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ParetoParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ParetoParams(ParetoParams other) : this() {
+ interarrivalBase_ = other.interarrivalBase_;
+ alpha_ = other.alpha_;
+ }
+
+ public ParetoParams Clone() {
+ return new ParetoParams(this);
+ }
+
+ public const int InterarrivalBaseFieldNumber = 1;
+ private double interarrivalBase_;
+ public double InterarrivalBase {
+ get { return interarrivalBase_; }
+ set {
+ interarrivalBase_ = value;
+ }
+ }
+
+ public const int AlphaFieldNumber = 2;
+ private double alpha_;
+ public double Alpha {
+ get { return alpha_; }
+ set {
+ alpha_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ParetoParams);
+ }
+
+ public bool Equals(ParetoParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (InterarrivalBase != other.InterarrivalBase) return false;
+ if (Alpha != other.Alpha) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (InterarrivalBase != 0D) hash ^= InterarrivalBase.GetHashCode();
+ if (Alpha != 0D) hash ^= Alpha.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (InterarrivalBase != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(InterarrivalBase);
+ }
+ if (Alpha != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(Alpha);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (InterarrivalBase != 0D) {
+ size += 1 + 8;
+ }
+ if (Alpha != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(ParetoParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.InterarrivalBase != 0D) {
+ InterarrivalBase = other.InterarrivalBase;
+ }
+ if (other.Alpha != 0D) {
+ Alpha = other.Alpha;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ InterarrivalBase = input.ReadDouble();
+ break;
+ }
+ case 17: {
+ Alpha = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
+ private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
+ public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[4]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ClosedLoopParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ClosedLoopParams(ClosedLoopParams other) : this() {
+ }
+
+ public ClosedLoopParams Clone() {
+ return new ClosedLoopParams(this);
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ClosedLoopParams);
+ }
+
+ public bool Equals(ClosedLoopParams 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.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ return size;
+ }
+
+ public void MergeFrom(ClosedLoopParams other) {
+ if (other == null) {
+ return;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class LoadParams : pb::IMessage<LoadParams> {
+ private static readonly pb::MessageParser<LoadParams> _parser = new pb::MessageParser<LoadParams>(() => new LoadParams());
+ public static pb::MessageParser<LoadParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[5]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public LoadParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public LoadParams(LoadParams other) : this() {
+ switch (other.LoadCase) {
+ case LoadOneofCase.ClosedLoop:
+ ClosedLoop = other.ClosedLoop.Clone();
+ break;
+ case LoadOneofCase.Poisson:
+ Poisson = other.Poisson.Clone();
+ break;
+ case LoadOneofCase.Uniform:
+ Uniform = other.Uniform.Clone();
+ break;
+ case LoadOneofCase.Determ:
+ Determ = other.Determ.Clone();
+ break;
+ case LoadOneofCase.Pareto:
+ Pareto = other.Pareto.Clone();
+ break;
+ }
+
+ }
+
+ public LoadParams Clone() {
+ return new LoadParams(this);
+ }
+
+ public const int ClosedLoopFieldNumber = 1;
+ public global::Grpc.Testing.ClosedLoopParams ClosedLoop {
+ get { return loadCase_ == LoadOneofCase.ClosedLoop ? (global::Grpc.Testing.ClosedLoopParams) load_ : null; }
+ set {
+ load_ = value;
+ loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.ClosedLoop;
+ }
+ }
+
+ public const int PoissonFieldNumber = 2;
+ public global::Grpc.Testing.PoissonParams Poisson {
+ get { return loadCase_ == LoadOneofCase.Poisson ? (global::Grpc.Testing.PoissonParams) load_ : null; }
+ set {
+ load_ = value;
+ loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Poisson;
+ }
+ }
+
+ public const int UniformFieldNumber = 3;
+ public global::Grpc.Testing.UniformParams Uniform {
+ get { return loadCase_ == LoadOneofCase.Uniform ? (global::Grpc.Testing.UniformParams) load_ : null; }
+ set {
+ load_ = value;
+ loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Uniform;
+ }
+ }
+
+ public const int DetermFieldNumber = 4;
+ public global::Grpc.Testing.DeterministicParams Determ {
+ get { return loadCase_ == LoadOneofCase.Determ ? (global::Grpc.Testing.DeterministicParams) load_ : null; }
+ set {
+ load_ = value;
+ loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Determ;
+ }
+ }
+
+ public const int ParetoFieldNumber = 5;
+ public global::Grpc.Testing.ParetoParams Pareto {
+ get { return loadCase_ == LoadOneofCase.Pareto ? (global::Grpc.Testing.ParetoParams) load_ : null; }
+ set {
+ load_ = value;
+ loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Pareto;
+ }
+ }
+
+ private object load_;
+ public enum LoadOneofCase {
+ None = 0,
+ ClosedLoop = 1,
+ Poisson = 2,
+ Uniform = 3,
+ Determ = 4,
+ Pareto = 5,
+ }
+ private LoadOneofCase loadCase_ = LoadOneofCase.None;
+ public LoadOneofCase LoadCase {
+ get { return loadCase_; }
+ }
+
+ public void ClearLoad() {
+ loadCase_ = LoadOneofCase.None;
+ load_ = null;
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as LoadParams);
+ }
+
+ public bool Equals(LoadParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
+ if (!object.Equals(Poisson, other.Poisson)) return false;
+ if (!object.Equals(Uniform, other.Uniform)) return false;
+ if (!object.Equals(Determ, other.Determ)) return false;
+ if (!object.Equals(Pareto, other.Pareto)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
+ if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
+ if (loadCase_ == LoadOneofCase.Uniform) hash ^= Uniform.GetHashCode();
+ if (loadCase_ == LoadOneofCase.Determ) hash ^= Determ.GetHashCode();
+ if (loadCase_ == LoadOneofCase.Pareto) hash ^= Pareto.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (loadCase_ == LoadOneofCase.ClosedLoop) {
+ output.WriteRawTag(10);
+ output.WriteMessage(ClosedLoop);
+ }
+ if (loadCase_ == LoadOneofCase.Poisson) {
+ output.WriteRawTag(18);
+ output.WriteMessage(Poisson);
+ }
+ if (loadCase_ == LoadOneofCase.Uniform) {
+ output.WriteRawTag(26);
+ output.WriteMessage(Uniform);
+ }
+ if (loadCase_ == LoadOneofCase.Determ) {
+ output.WriteRawTag(34);
+ output.WriteMessage(Determ);
+ }
+ if (loadCase_ == LoadOneofCase.Pareto) {
+ output.WriteRawTag(42);
+ output.WriteMessage(Pareto);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (loadCase_ == LoadOneofCase.ClosedLoop) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClosedLoop);
+ }
+ if (loadCase_ == LoadOneofCase.Poisson) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
+ }
+ if (loadCase_ == LoadOneofCase.Uniform) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Uniform);
+ }
+ if (loadCase_ == LoadOneofCase.Determ) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Determ);
+ }
+ if (loadCase_ == LoadOneofCase.Pareto) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Pareto);
+ }
+ return size;
+ }
+
+ public void MergeFrom(LoadParams other) {
+ if (other == null) {
+ return;
+ }
+ switch (other.LoadCase) {
+ case LoadOneofCase.ClosedLoop:
+ ClosedLoop = other.ClosedLoop;
+ break;
+ case LoadOneofCase.Poisson:
+ Poisson = other.Poisson;
+ break;
+ case LoadOneofCase.Uniform:
+ Uniform = other.Uniform;
+ break;
+ case LoadOneofCase.Determ:
+ Determ = other.Determ;
+ break;
+ case LoadOneofCase.Pareto:
+ Pareto = other.Pareto;
+ break;
+ }
+
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams();
+ if (loadCase_ == LoadOneofCase.ClosedLoop) {
+ subBuilder.MergeFrom(ClosedLoop);
+ }
+ input.ReadMessage(subBuilder);
+ ClosedLoop = subBuilder;
+ break;
+ }
+ case 18: {
+ global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams();
+ if (loadCase_ == LoadOneofCase.Poisson) {
+ subBuilder.MergeFrom(Poisson);
+ }
+ input.ReadMessage(subBuilder);
+ Poisson = subBuilder;
+ break;
+ }
+ case 26: {
+ global::Grpc.Testing.UniformParams subBuilder = new global::Grpc.Testing.UniformParams();
+ if (loadCase_ == LoadOneofCase.Uniform) {
+ subBuilder.MergeFrom(Uniform);
+ }
+ input.ReadMessage(subBuilder);
+ Uniform = subBuilder;
+ break;
+ }
+ case 34: {
+ global::Grpc.Testing.DeterministicParams subBuilder = new global::Grpc.Testing.DeterministicParams();
+ if (loadCase_ == LoadOneofCase.Determ) {
+ subBuilder.MergeFrom(Determ);
+ }
+ input.ReadMessage(subBuilder);
+ Determ = subBuilder;
+ break;
+ }
+ case 42: {
+ global::Grpc.Testing.ParetoParams subBuilder = new global::Grpc.Testing.ParetoParams();
+ if (loadCase_ == LoadOneofCase.Pareto) {
+ subBuilder.MergeFrom(Pareto);
+ }
+ input.ReadMessage(subBuilder);
+ Pareto = subBuilder;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
+ private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
+ public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[6]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public SecurityParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public SecurityParams(SecurityParams other) : this() {
+ useTestCa_ = other.useTestCa_;
+ serverHostOverride_ = other.serverHostOverride_;
+ }
+
+ public SecurityParams Clone() {
+ return new SecurityParams(this);
+ }
+
+ public const int UseTestCaFieldNumber = 1;
+ private bool useTestCa_;
+ public bool UseTestCa {
+ get { return useTestCa_; }
+ set {
+ useTestCa_ = value;
+ }
+ }
+
+ public const int ServerHostOverrideFieldNumber = 2;
+ private string serverHostOverride_ = "";
+ public string ServerHostOverride {
+ get { return serverHostOverride_; }
+ set {
+ serverHostOverride_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as SecurityParams);
+ }
+
+ public bool Equals(SecurityParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (UseTestCa != other.UseTestCa) return false;
+ if (ServerHostOverride != other.ServerHostOverride) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (UseTestCa != false) hash ^= UseTestCa.GetHashCode();
+ if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (UseTestCa != false) {
+ output.WriteRawTag(8);
+ output.WriteBool(UseTestCa);
+ }
+ if (ServerHostOverride.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(ServerHostOverride);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (UseTestCa != false) {
+ size += 1 + 1;
+ }
+ if (ServerHostOverride.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(ServerHostOverride);
+ }
+ return size;
+ }
+
+ public void MergeFrom(SecurityParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.UseTestCa != false) {
+ UseTestCa = other.UseTestCa;
+ }
+ if (other.ServerHostOverride.Length != 0) {
+ ServerHostOverride = other.ServerHostOverride;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 8: {
+ UseTestCa = input.ReadBool();
+ break;
+ }
+ case 18: {
+ ServerHostOverride = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ClientConfig : pb::IMessage<ClientConfig> {
+ private static readonly pb::MessageParser<ClientConfig> _parser = new pb::MessageParser<ClientConfig>(() => new ClientConfig());
+ public static pb::MessageParser<ClientConfig> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[7]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ClientConfig() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ClientConfig(ClientConfig other) : this() {
+ serverTargets_ = other.serverTargets_.Clone();
+ clientType_ = other.clientType_;
+ SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
+ outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_;
+ clientChannels_ = other.clientChannels_;
+ asyncClientThreads_ = other.asyncClientThreads_;
+ rpcType_ = other.rpcType_;
+ LoadParams = other.loadParams_ != null ? other.LoadParams.Clone() : null;
+ PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
+ HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
+ }
+
+ public ClientConfig Clone() {
+ return new ClientConfig(this);
+ }
+
+ public const int ServerTargetsFieldNumber = 1;
+ private static readonly pb::FieldCodec<string> _repeated_serverTargets_codec
+ = pb::FieldCodec.ForString(10);
+ private readonly pbc::RepeatedField<string> serverTargets_ = new pbc::RepeatedField<string>();
+ public pbc::RepeatedField<string> ServerTargets {
+ get { return serverTargets_; }
+ }
+
+ public const int ClientTypeFieldNumber = 2;
+ private global::Grpc.Testing.ClientType clientType_ = global::Grpc.Testing.ClientType.SYNC_CLIENT;
+ public global::Grpc.Testing.ClientType ClientType {
+ get { return clientType_; }
+ set {
+ clientType_ = value;
+ }
+ }
+
+ public const int SecurityParamsFieldNumber = 3;
+ private global::Grpc.Testing.SecurityParams securityParams_;
+ public global::Grpc.Testing.SecurityParams SecurityParams {
+ get { return securityParams_; }
+ set {
+ securityParams_ = value;
+ }
+ }
+
+ public const int OutstandingRpcsPerChannelFieldNumber = 4;
+ private int outstandingRpcsPerChannel_;
+ public int OutstandingRpcsPerChannel {
+ get { return outstandingRpcsPerChannel_; }
+ set {
+ outstandingRpcsPerChannel_ = value;
+ }
+ }
+
+ public const int ClientChannelsFieldNumber = 5;
+ private int clientChannels_;
+ public int ClientChannels {
+ get { return clientChannels_; }
+ set {
+ clientChannels_ = value;
+ }
+ }
+
+ public const int AsyncClientThreadsFieldNumber = 7;
+ private int asyncClientThreads_;
+ public int AsyncClientThreads {
+ get { return asyncClientThreads_; }
+ set {
+ asyncClientThreads_ = value;
+ }
+ }
+
+ public const int RpcTypeFieldNumber = 8;
+ private global::Grpc.Testing.RpcType rpcType_ = global::Grpc.Testing.RpcType.UNARY;
+ public global::Grpc.Testing.RpcType RpcType {
+ get { return rpcType_; }
+ set {
+ rpcType_ = value;
+ }
+ }
+
+ public const int LoadParamsFieldNumber = 10;
+ private global::Grpc.Testing.LoadParams loadParams_;
+ public global::Grpc.Testing.LoadParams LoadParams {
+ get { return loadParams_; }
+ set {
+ loadParams_ = value;
+ }
+ }
+
+ public const int PayloadConfigFieldNumber = 11;
+ private global::Grpc.Testing.PayloadConfig payloadConfig_;
+ public global::Grpc.Testing.PayloadConfig PayloadConfig {
+ get { return payloadConfig_; }
+ set {
+ payloadConfig_ = value;
+ }
+ }
+
+ public const int HistogramParamsFieldNumber = 12;
+ private global::Grpc.Testing.HistogramParams histogramParams_;
+ public global::Grpc.Testing.HistogramParams HistogramParams {
+ get { return histogramParams_; }
+ set {
+ histogramParams_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ClientConfig);
+ }
+
+ public bool Equals(ClientConfig other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if(!serverTargets_.Equals(other.serverTargets_)) return false;
+ if (ClientType != other.ClientType) return false;
+ if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
+ if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false;
+ if (ClientChannels != other.ClientChannels) return false;
+ if (AsyncClientThreads != other.AsyncClientThreads) return false;
+ if (RpcType != other.RpcType) return false;
+ if (!object.Equals(LoadParams, other.LoadParams)) return false;
+ if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
+ if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ hash ^= serverTargets_.GetHashCode();
+ if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) hash ^= ClientType.GetHashCode();
+ if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
+ if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode();
+ if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode();
+ if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode();
+ if (RpcType != global::Grpc.Testing.RpcType.UNARY) hash ^= RpcType.GetHashCode();
+ if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
+ if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
+ if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ serverTargets_.WriteTo(output, _repeated_serverTargets_codec);
+ if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+ output.WriteRawTag(16);
+ output.WriteEnum((int) ClientType);
+ }
+ if (securityParams_ != null) {
+ output.WriteRawTag(26);
+ output.WriteMessage(SecurityParams);
+ }
+ if (OutstandingRpcsPerChannel != 0) {
+ output.WriteRawTag(32);
+ output.WriteInt32(OutstandingRpcsPerChannel);
+ }
+ if (ClientChannels != 0) {
+ output.WriteRawTag(40);
+ output.WriteInt32(ClientChannels);
+ }
+ if (AsyncClientThreads != 0) {
+ output.WriteRawTag(56);
+ output.WriteInt32(AsyncClientThreads);
+ }
+ if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
+ output.WriteRawTag(64);
+ output.WriteEnum((int) RpcType);
+ }
+ if (loadParams_ != null) {
+ output.WriteRawTag(82);
+ output.WriteMessage(LoadParams);
+ }
+ if (payloadConfig_ != null) {
+ output.WriteRawTag(90);
+ output.WriteMessage(PayloadConfig);
+ }
+ if (histogramParams_ != null) {
+ output.WriteRawTag(98);
+ output.WriteMessage(HistogramParams);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ size += serverTargets_.CalculateSize(_repeated_serverTargets_codec);
+ if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType);
+ }
+ if (securityParams_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
+ }
+ if (OutstandingRpcsPerChannel != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(OutstandingRpcsPerChannel);
+ }
+ if (ClientChannels != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientChannels);
+ }
+ if (AsyncClientThreads != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads);
+ }
+ if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType);
+ }
+ if (loadParams_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(LoadParams);
+ }
+ if (payloadConfig_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
+ }
+ if (histogramParams_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ClientConfig other) {
+ if (other == null) {
+ return;
+ }
+ serverTargets_.Add(other.serverTargets_);
+ if (other.ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+ ClientType = other.ClientType;
+ }
+ if (other.securityParams_ != null) {
+ if (securityParams_ == null) {
+ securityParams_ = new global::Grpc.Testing.SecurityParams();
+ }
+ SecurityParams.MergeFrom(other.SecurityParams);
+ }
+ if (other.OutstandingRpcsPerChannel != 0) {
+ OutstandingRpcsPerChannel = other.OutstandingRpcsPerChannel;
+ }
+ if (other.ClientChannels != 0) {
+ ClientChannels = other.ClientChannels;
+ }
+ if (other.AsyncClientThreads != 0) {
+ AsyncClientThreads = other.AsyncClientThreads;
+ }
+ if (other.RpcType != global::Grpc.Testing.RpcType.UNARY) {
+ RpcType = other.RpcType;
+ }
+ if (other.loadParams_ != null) {
+ if (loadParams_ == null) {
+ loadParams_ = new global::Grpc.Testing.LoadParams();
+ }
+ LoadParams.MergeFrom(other.LoadParams);
+ }
+ if (other.payloadConfig_ != null) {
+ if (payloadConfig_ == null) {
+ payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+ }
+ PayloadConfig.MergeFrom(other.PayloadConfig);
+ }
+ if (other.histogramParams_ != null) {
+ if (histogramParams_ == null) {
+ histogramParams_ = new global::Grpc.Testing.HistogramParams();
+ }
+ HistogramParams.MergeFrom(other.HistogramParams);
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec);
+ break;
+ }
+ case 16: {
+ clientType_ = (global::Grpc.Testing.ClientType) input.ReadEnum();
+ break;
+ }
+ case 26: {
+ if (securityParams_ == null) {
+ securityParams_ = new global::Grpc.Testing.SecurityParams();
+ }
+ input.ReadMessage(securityParams_);
+ break;
+ }
+ case 32: {
+ OutstandingRpcsPerChannel = input.ReadInt32();
+ break;
+ }
+ case 40: {
+ ClientChannels = input.ReadInt32();
+ break;
+ }
+ case 56: {
+ AsyncClientThreads = input.ReadInt32();
+ break;
+ }
+ case 64: {
+ rpcType_ = (global::Grpc.Testing.RpcType) input.ReadEnum();
+ break;
+ }
+ case 82: {
+ if (loadParams_ == null) {
+ loadParams_ = new global::Grpc.Testing.LoadParams();
+ }
+ input.ReadMessage(loadParams_);
+ break;
+ }
+ case 90: {
+ if (payloadConfig_ == null) {
+ payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+ }
+ input.ReadMessage(payloadConfig_);
+ break;
+ }
+ case 98: {
+ if (histogramParams_ == null) {
+ histogramParams_ = new global::Grpc.Testing.HistogramParams();
+ }
+ input.ReadMessage(histogramParams_);
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
+ private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
+ public static pb::MessageParser<ClientStatus> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[8]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ClientStatus() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ClientStatus(ClientStatus other) : this() {
+ Stats = other.stats_ != null ? other.Stats.Clone() : null;
+ }
+
+ public ClientStatus Clone() {
+ return new ClientStatus(this);
+ }
+
+ public const int StatsFieldNumber = 1;
+ private global::Grpc.Testing.ClientStats stats_;
+ public global::Grpc.Testing.ClientStats Stats {
+ get { return stats_; }
+ set {
+ stats_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ClientStatus);
+ }
+
+ public bool Equals(ClientStatus other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(Stats, other.Stats)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (stats_ != null) hash ^= Stats.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (stats_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(Stats);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (stats_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ClientStatus other) {
+ if (other == null) {
+ return;
+ }
+ if (other.stats_ != null) {
+ if (stats_ == null) {
+ stats_ = new global::Grpc.Testing.ClientStats();
+ }
+ Stats.MergeFrom(other.Stats);
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ if (stats_ == null) {
+ stats_ = new global::Grpc.Testing.ClientStats();
+ }
+ input.ReadMessage(stats_);
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Mark : pb::IMessage<Mark> {
+ private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
+ public static pb::MessageParser<Mark> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[9]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public Mark() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public Mark(Mark other) : this() {
+ reset_ = other.reset_;
+ }
+
+ public Mark Clone() {
+ return new Mark(this);
+ }
+
+ public const int ResetFieldNumber = 1;
+ private bool reset_;
+ public bool Reset {
+ get { return reset_; }
+ set {
+ reset_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as Mark);
+ }
+
+ public bool Equals(Mark other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Reset != other.Reset) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Reset != false) hash ^= Reset.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Reset != false) {
+ output.WriteRawTag(8);
+ output.WriteBool(Reset);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Reset != false) {
+ size += 1 + 1;
+ }
+ return size;
+ }
+
+ public void MergeFrom(Mark other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Reset != false) {
+ Reset = other.Reset;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 8: {
+ Reset = input.ReadBool();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ClientArgs : pb::IMessage<ClientArgs> {
+ private static readonly pb::MessageParser<ClientArgs> _parser = new pb::MessageParser<ClientArgs>(() => new ClientArgs());
+ public static pb::MessageParser<ClientArgs> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[10]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ClientArgs() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ClientArgs(ClientArgs other) : this() {
+ switch (other.ArgtypeCase) {
+ case ArgtypeOneofCase.Setup:
+ Setup = other.Setup.Clone();
+ break;
+ case ArgtypeOneofCase.Mark:
+ Mark = other.Mark.Clone();
+ break;
+ }
+
+ }
+
+ public ClientArgs Clone() {
+ return new ClientArgs(this);
+ }
+
+ public const int SetupFieldNumber = 1;
+ public global::Grpc.Testing.ClientConfig Setup {
+ get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ClientConfig) argtype_ : null; }
+ set {
+ argtype_ = value;
+ argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
+ }
+ }
+
+ public const int MarkFieldNumber = 2;
+ public global::Grpc.Testing.Mark Mark {
+ get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
+ set {
+ argtype_ = value;
+ argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
+ }
+ }
+
+ private object argtype_;
+ public enum ArgtypeOneofCase {
+ None = 0,
+ Setup = 1,
+ Mark = 2,
+ }
+ private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
+ public ArgtypeOneofCase ArgtypeCase {
+ get { return argtypeCase_; }
+ }
+
+ public void ClearArgtype() {
+ argtypeCase_ = ArgtypeOneofCase.None;
+ argtype_ = null;
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ClientArgs);
+ }
+
+ public bool Equals(ClientArgs other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(Setup, other.Setup)) return false;
+ if (!object.Equals(Mark, other.Mark)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+ output.WriteRawTag(10);
+ output.WriteMessage(Setup);
+ }
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+ output.WriteRawTag(18);
+ output.WriteMessage(Mark);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
+ }
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ClientArgs other) {
+ if (other == null) {
+ return;
+ }
+ switch (other.ArgtypeCase) {
+ case ArgtypeOneofCase.Setup:
+ Setup = other.Setup;
+ break;
+ case ArgtypeOneofCase.Mark:
+ Mark = other.Mark;
+ break;
+ }
+
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig();
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+ subBuilder.MergeFrom(Setup);
+ }
+ input.ReadMessage(subBuilder);
+ Setup = subBuilder;
+ break;
+ }
+ case 18: {
+ global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+ subBuilder.MergeFrom(Mark);
+ }
+ input.ReadMessage(subBuilder);
+ Mark = subBuilder;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ServerConfig : pb::IMessage<ServerConfig> {
+ private static readonly pb::MessageParser<ServerConfig> _parser = new pb::MessageParser<ServerConfig>(() => new ServerConfig());
+ public static pb::MessageParser<ServerConfig> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[11]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ServerConfig() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ServerConfig(ServerConfig other) : this() {
+ serverType_ = other.serverType_;
+ SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
+ host_ = other.host_;
+ port_ = other.port_;
+ asyncServerThreads_ = other.asyncServerThreads_;
+ coreLimit_ = other.coreLimit_;
+ PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
+ }
+
+ public ServerConfig Clone() {
+ return new ServerConfig(this);
+ }
+
+ public const int ServerTypeFieldNumber = 1;
+ private global::Grpc.Testing.ServerType serverType_ = global::Grpc.Testing.ServerType.SYNC_SERVER;
+ public global::Grpc.Testing.ServerType ServerType {
+ get { return serverType_; }
+ set {
+ serverType_ = value;
+ }
+ }
+
+ public const int SecurityParamsFieldNumber = 2;
+ private global::Grpc.Testing.SecurityParams securityParams_;
+ public global::Grpc.Testing.SecurityParams SecurityParams {
+ get { return securityParams_; }
+ set {
+ securityParams_ = value;
+ }
+ }
+
+ public const int HostFieldNumber = 3;
+ private string host_ = "";
+ public string Host {
+ get { return host_; }
+ set {
+ host_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public const int PortFieldNumber = 4;
+ private int port_;
+ public int Port {
+ get { return port_; }
+ set {
+ port_ = value;
+ }
+ }
+
+ public const int AsyncServerThreadsFieldNumber = 7;
+ private int asyncServerThreads_;
+ public int AsyncServerThreads {
+ get { return asyncServerThreads_; }
+ set {
+ asyncServerThreads_ = value;
+ }
+ }
+
+ public const int CoreLimitFieldNumber = 8;
+ private int coreLimit_;
+ public int CoreLimit {
+ get { return coreLimit_; }
+ set {
+ coreLimit_ = value;
+ }
+ }
+
+ public const int PayloadConfigFieldNumber = 9;
+ private global::Grpc.Testing.PayloadConfig payloadConfig_;
+ public global::Grpc.Testing.PayloadConfig PayloadConfig {
+ get { return payloadConfig_; }
+ set {
+ payloadConfig_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ServerConfig);
+ }
+
+ public bool Equals(ServerConfig other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (ServerType != other.ServerType) return false;
+ if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
+ if (Host != other.Host) return false;
+ if (Port != other.Port) return false;
+ if (AsyncServerThreads != other.AsyncServerThreads) return false;
+ if (CoreLimit != other.CoreLimit) return false;
+ if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) hash ^= ServerType.GetHashCode();
+ if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
+ if (Host.Length != 0) hash ^= Host.GetHashCode();
+ if (Port != 0) hash ^= Port.GetHashCode();
+ if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode();
+ if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
+ if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+ output.WriteRawTag(8);
+ output.WriteEnum((int) ServerType);
+ }
+ if (securityParams_ != null) {
+ output.WriteRawTag(18);
+ output.WriteMessage(SecurityParams);
+ }
+ if (Host.Length != 0) {
+ output.WriteRawTag(26);
+ output.WriteString(Host);
+ }
+ if (Port != 0) {
+ output.WriteRawTag(32);
+ output.WriteInt32(Port);
+ }
+ if (AsyncServerThreads != 0) {
+ output.WriteRawTag(56);
+ output.WriteInt32(AsyncServerThreads);
+ }
+ if (CoreLimit != 0) {
+ output.WriteRawTag(64);
+ output.WriteInt32(CoreLimit);
+ }
+ if (payloadConfig_ != null) {
+ output.WriteRawTag(74);
+ output.WriteMessage(PayloadConfig);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType);
+ }
+ if (securityParams_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
+ }
+ if (Host.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
+ }
+ if (Port != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
+ }
+ if (AsyncServerThreads != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncServerThreads);
+ }
+ if (CoreLimit != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
+ }
+ if (payloadConfig_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ServerConfig other) {
+ if (other == null) {
+ return;
+ }
+ if (other.ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+ ServerType = other.ServerType;
+ }
+ if (other.securityParams_ != null) {
+ if (securityParams_ == null) {
+ securityParams_ = new global::Grpc.Testing.SecurityParams();
+ }
+ SecurityParams.MergeFrom(other.SecurityParams);
+ }
+ if (other.Host.Length != 0) {
+ Host = other.Host;
+ }
+ if (other.Port != 0) {
+ Port = other.Port;
+ }
+ if (other.AsyncServerThreads != 0) {
+ AsyncServerThreads = other.AsyncServerThreads;
+ }
+ if (other.CoreLimit != 0) {
+ CoreLimit = other.CoreLimit;
+ }
+ if (other.payloadConfig_ != null) {
+ if (payloadConfig_ == null) {
+ payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+ }
+ PayloadConfig.MergeFrom(other.PayloadConfig);
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 8: {
+ serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum();
+ break;
+ }
+ case 18: {
+ if (securityParams_ == null) {
+ securityParams_ = new global::Grpc.Testing.SecurityParams();
+ }
+ input.ReadMessage(securityParams_);
+ break;
+ }
+ case 26: {
+ Host = input.ReadString();
+ break;
+ }
+ case 32: {
+ Port = input.ReadInt32();
+ break;
+ }
+ case 56: {
+ AsyncServerThreads = input.ReadInt32();
+ break;
+ }
+ case 64: {
+ CoreLimit = input.ReadInt32();
+ break;
+ }
+ case 74: {
+ if (payloadConfig_ == null) {
+ payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+ }
+ input.ReadMessage(payloadConfig_);
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ServerArgs : pb::IMessage<ServerArgs> {
+ private static readonly pb::MessageParser<ServerArgs> _parser = new pb::MessageParser<ServerArgs>(() => new ServerArgs());
+ public static pb::MessageParser<ServerArgs> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[12]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ServerArgs() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ServerArgs(ServerArgs other) : this() {
+ switch (other.ArgtypeCase) {
+ case ArgtypeOneofCase.Setup:
+ Setup = other.Setup.Clone();
+ break;
+ case ArgtypeOneofCase.Mark:
+ Mark = other.Mark.Clone();
+ break;
+ }
+
+ }
+
+ public ServerArgs Clone() {
+ return new ServerArgs(this);
+ }
+
+ public const int SetupFieldNumber = 1;
+ public global::Grpc.Testing.ServerConfig Setup {
+ get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ServerConfig) argtype_ : null; }
+ set {
+ argtype_ = value;
+ argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
+ }
+ }
+
+ public const int MarkFieldNumber = 2;
+ public global::Grpc.Testing.Mark Mark {
+ get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
+ set {
+ argtype_ = value;
+ argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
+ }
+ }
+
+ private object argtype_;
+ public enum ArgtypeOneofCase {
+ None = 0,
+ Setup = 1,
+ Mark = 2,
+ }
+ private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
+ public ArgtypeOneofCase ArgtypeCase {
+ get { return argtypeCase_; }
+ }
+
+ public void ClearArgtype() {
+ argtypeCase_ = ArgtypeOneofCase.None;
+ argtype_ = null;
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ServerArgs);
+ }
+
+ public bool Equals(ServerArgs other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(Setup, other.Setup)) return false;
+ if (!object.Equals(Mark, other.Mark)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+ output.WriteRawTag(10);
+ output.WriteMessage(Setup);
+ }
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+ output.WriteRawTag(18);
+ output.WriteMessage(Mark);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
+ }
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ServerArgs other) {
+ if (other == null) {
+ return;
+ }
+ switch (other.ArgtypeCase) {
+ case ArgtypeOneofCase.Setup:
+ Setup = other.Setup;
+ break;
+ case ArgtypeOneofCase.Mark:
+ Mark = other.Mark;
+ break;
+ }
+
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig();
+ if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+ subBuilder.MergeFrom(Setup);
+ }
+ input.ReadMessage(subBuilder);
+ Setup = subBuilder;
+ break;
+ }
+ case 18: {
+ global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
+ if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+ subBuilder.MergeFrom(Mark);
+ }
+ input.ReadMessage(subBuilder);
+ Mark = subBuilder;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ServerStatus : pb::IMessage<ServerStatus> {
+ private static readonly pb::MessageParser<ServerStatus> _parser = new pb::MessageParser<ServerStatus>(() => new ServerStatus());
+ public static pb::MessageParser<ServerStatus> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[13]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ServerStatus() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ServerStatus(ServerStatus other) : this() {
+ Stats = other.stats_ != null ? other.Stats.Clone() : null;
+ port_ = other.port_;
+ cores_ = other.cores_;
+ }
+
+ public ServerStatus Clone() {
+ return new ServerStatus(this);
+ }
+
+ public const int StatsFieldNumber = 1;
+ private global::Grpc.Testing.ServerStats stats_;
+ public global::Grpc.Testing.ServerStats Stats {
+ get { return stats_; }
+ set {
+ stats_ = value;
+ }
+ }
+
+ public const int PortFieldNumber = 2;
+ private int port_;
+ public int Port {
+ get { return port_; }
+ set {
+ port_ = value;
+ }
+ }
+
+ public const int CoresFieldNumber = 3;
+ private int cores_;
+ public int Cores {
+ get { return cores_; }
+ set {
+ cores_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ServerStatus);
+ }
+
+ public bool Equals(ServerStatus other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(Stats, other.Stats)) return false;
+ if (Port != other.Port) return false;
+ if (Cores != other.Cores) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (stats_ != null) hash ^= Stats.GetHashCode();
+ if (Port != 0) hash ^= Port.GetHashCode();
+ if (Cores != 0) hash ^= Cores.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (stats_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(Stats);
+ }
+ if (Port != 0) {
+ output.WriteRawTag(16);
+ output.WriteInt32(Port);
+ }
+ if (Cores != 0) {
+ output.WriteRawTag(24);
+ output.WriteInt32(Cores);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (stats_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
+ }
+ if (Port != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
+ }
+ if (Cores != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ServerStatus other) {
+ if (other == null) {
+ return;
+ }
+ if (other.stats_ != null) {
+ if (stats_ == null) {
+ stats_ = new global::Grpc.Testing.ServerStats();
+ }
+ Stats.MergeFrom(other.Stats);
+ }
+ if (other.Port != 0) {
+ Port = other.Port;
+ }
+ if (other.Cores != 0) {
+ Cores = other.Cores;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ if (stats_ == null) {
+ stats_ = new global::Grpc.Testing.ServerStats();
+ }
+ input.ReadMessage(stats_);
+ break;
+ }
+ case 16: {
+ Port = input.ReadInt32();
+ break;
+ }
+ case 24: {
+ Cores = input.ReadInt32();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 2b75305731..b0d920a34c 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -38,60 +38,55 @@
<AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
- </Reference>
<Reference Include="CommandLine">
<HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Moq">
+ <HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
+ <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth">
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.3.19383, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Google.Apis.Core">
<HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
- <Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
- <Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
- <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Interactive.Async">
- <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
- </Reference>
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
+ <Compile Include="HeaderInterceptorTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Empty.cs" />
<Compile Include="Messages.cs" />
@@ -104,6 +99,22 @@
<Compile Include="TestGrpc.cs" />
<Compile Include="SslCredentialsTest.cs" />
<Compile Include="Test.cs" />
+ <Compile Include="IClientRunner.cs" />
+ <Compile Include="ClientRunners.cs" />
+ <Compile Include="IServerRunner.cs" />
+ <Compile Include="ServerRunners.cs" />
+ <Compile Include="RunnerClientServerTest.cs" />
+ <Compile Include="Control.cs" />
+ <Compile Include="Payloads.cs" />
+ <Compile Include="Services.cs" />
+ <Compile Include="ServicesGrpc.cs" />
+ <Compile Include="Stats.cs" />
+ <Compile Include="BenchmarkServiceImpl.cs" />
+ <Compile Include="Histogram.cs" />
+ <Compile Include="HistogramTest.cs" />
+ <Compile Include="WorkerServiceImpl.cs" />
+ <Compile Include="QpsWorker.cs" />
+ <Compile Include="WallClockStopwatch.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs b/src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs
new file mode 100644
index 0000000000..1d758b7540
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/HeaderInterceptorTest.cs
@@ -0,0 +1,113 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+ public class HeaderInterceptorTest
+ {
+ const string Host = "localhost";
+ Server server;
+ Channel channel;
+ TestService.TestServiceClient client;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ server = new Server
+ {
+ Services = { TestService.BindService(new TestServiceImpl()) },
+ Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
+ };
+ server.Start();
+
+ channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
+ client = TestService.NewClient(channel);
+ }
+
+ [TestFixtureTearDown]
+ public void Cleanup()
+ {
+ channel.ShutdownAsync().Wait();
+ server.ShutdownAsync().Wait();
+ }
+
+ [Test]
+ public async Task HeaderInterceptor_CreateMetadata()
+ {
+ var key = "x-grpc-test-echo-initial";
+ client.HeaderInterceptor = new HeaderInterceptor((method, metadata) =>
+ {
+ metadata.Add(key, "ABC");
+ });
+
+ var call = client.UnaryCallAsync(new SimpleRequest());
+ await call;
+
+ var responseHeaders = await call.ResponseHeadersAsync;
+ Assert.AreEqual("ABC", responseHeaders.First((entry) => entry.Key == key).Value);
+ }
+
+ [Test]
+ public async Task HeaderInterceptor_AppendMetadata()
+ {
+ var initialKey = "x-grpc-test-echo-initial";
+ var trailingKey = "x-grpc-test-echo-trailing-bin";
+
+ client.HeaderInterceptor = new HeaderInterceptor((method, metadata) =>
+ {
+ metadata.Add(initialKey, "ABC");
+ });
+
+ var headers = new Metadata
+ {
+ { trailingKey, new byte[] {0xaa} }
+ };
+ var call = client.UnaryCallAsync(new SimpleRequest(), headers: headers);
+ await call;
+
+ var responseHeaders = await call.ResponseHeadersAsync;
+ Assert.AreEqual("ABC", responseHeaders.First((entry) => entry.Key == initialKey).Value);
+ CollectionAssert.AreEqual(new byte[] {0xaa}, call.GetTrailers().First((entry) => entry.Key == trailingKey).ValueBytes);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Histogram.cs b/src/csharp/Grpc.IntegrationTesting/Histogram.cs
new file mode 100644
index 0000000000..7e7cb2c4de
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Histogram.cs
@@ -0,0 +1,153 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Basic implementation of histogram based on grpc/support/histogram.h.
+ /// </summary>
+ public class Histogram
+ {
+ readonly object myLock = new object();
+ readonly double multiplier;
+ readonly double oneOnLogMultiplier;
+ readonly double maxPossible;
+ readonly uint[] buckets;
+
+ int count;
+ double sum;
+ double sumOfSquares;
+ double min;
+ double max;
+
+ public Histogram(double resolution, double maxPossible)
+ {
+ Grpc.Core.Utils.Preconditions.CheckArgument(resolution > 0);
+ Grpc.Core.Utils.Preconditions.CheckArgument(maxPossible > 0);
+ this.maxPossible = maxPossible;
+ this.multiplier = 1.0 + resolution;
+ this.oneOnLogMultiplier = 1.0 / Math.Log(1.0 + resolution);
+ this.buckets = new uint[FindBucket(maxPossible) + 1];
+
+ ResetUnsafe();
+ }
+
+ public void AddObservation(double value)
+ {
+ lock (myLock)
+ {
+ AddObservationUnsafe(value);
+ }
+ }
+
+
+ /// <summary>
+ /// Gets snapshot of stats and reset
+ /// </summary>
+ public HistogramData GetSnapshot(bool reset = false)
+ {
+ lock (myLock)
+ {
+ return GetSnapshotUnsafe(reset);
+ }
+ }
+
+ /// <summary>
+ /// Finds bucket index to which given observation should go.
+ /// </summary>
+ private int FindBucket(double value)
+ {
+ value = Math.Max(value, 1.0);
+ value = Math.Min(value, this.maxPossible);
+ return (int)(Math.Log(value) * oneOnLogMultiplier);
+ }
+
+ private void AddObservationUnsafe(double value)
+ {
+ this.count++;
+ this.sum += value;
+ this.sumOfSquares += value * value;
+ this.min = Math.Min(this.min, value);
+ this.max = Math.Max(this.max, value);
+
+ this.buckets[FindBucket(value)]++;
+ }
+
+ private HistogramData GetSnapshotUnsafe(bool reset)
+ {
+ var data = new HistogramData
+ {
+ Count = count,
+ Sum = sum,
+ SumOfSquares = sumOfSquares,
+ MinSeen = min,
+ MaxSeen = max,
+ Bucket = { buckets }
+ };
+
+ if (reset)
+ {
+ ResetUnsafe();
+ }
+
+ return data;
+ }
+
+ private void ResetUnsafe()
+ {
+ this.count = 0;
+ this.sum = 0;
+ this.sumOfSquares = 0;
+ this.min = double.PositiveInfinity;
+ this.max = double.NegativeInfinity;
+ for (int i = 0; i < this.buckets.Length; i++)
+ {
+ this.buckets[i] = 0;
+ }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs b/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
new file mode 100644
index 0000000000..fa160cbd15
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
@@ -0,0 +1,104 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+ public class HistogramTest
+ {
+ [Test]
+ public void Simple()
+ {
+ var hist = new Histogram(0.01, 60e9);
+ hist.AddObservation(10000);
+ hist.AddObservation(10000);
+ hist.AddObservation(11000);
+ hist.AddObservation(11000);
+
+ var data = hist.GetSnapshot();
+
+ Assert.AreEqual(4, data.Count);
+ Assert.AreEqual(42000.0, data.Sum, 1e-6);
+ Assert.AreEqual(10000, data.MinSeen);
+ Assert.AreEqual(11000, data.MaxSeen);
+ Assert.AreEqual(2.0*10000*10000 + 2.0*11000*11000, data.SumOfSquares, 1e-6);
+
+ // 1.01^925 < 10000 < 1.01^926
+ Assert.AreEqual(2, data.Bucket[925]);
+ Assert.AreEqual(2, data.Bucket[935]);
+ }
+
+ [Test]
+ public void ExtremeObservations()
+ {
+ var hist = new Histogram(0.01, 60e9);
+ hist.AddObservation(-0.5); // should be in the first bucket
+ hist.AddObservation(1e12); // should be in the last bucket
+
+ var data = hist.GetSnapshot();
+ Assert.AreEqual(1, data.Bucket[0]);
+ Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]);
+ }
+
+ [Test]
+ public void Reset()
+ {
+ var hist = new Histogram(0.01, 60e9);
+ hist.AddObservation(10000);
+ hist.AddObservation(11000);
+
+ var data = hist.GetSnapshot(true); // snapshot contains data before reset
+ Assert.AreEqual(2, data.Count);
+ Assert.AreEqual(10000, data.MinSeen);
+ Assert.AreEqual(11000, data.MaxSeen);
+
+ data = hist.GetSnapshot(); // snapshot contains state after reset
+ Assert.AreEqual(0, data.Count);
+ Assert.AreEqual(double.PositiveInfinity, data.MinSeen);
+ Assert.AreEqual(double.NegativeInfinity, data.MaxSeen);
+ Assert.AreEqual(0, data.Sum);
+ Assert.AreEqual(0, data.SumOfSquares);
+ CollectionAssert.AreEqual(new uint[data.Bucket.Count], data.Bucket);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs b/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs
new file mode 100644
index 0000000000..39b94f1e6d
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs
@@ -0,0 +1,67 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Abstract client runner.
+ /// </summary>
+ public interface IClientRunner
+ {
+ /// <summary>
+ /// Gets stats snapshot.
+ /// </summary>
+ /// <returns>The stats.</returns>
+ ClientStats GetStats(bool reset);
+
+ /// <summary>
+ /// Asynchronously stops the client.
+ /// </summary>
+ /// <returns>Task that finishes when client has come to a full stop.</returns>
+ Task StopAsync();
+ }
+
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs b/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs
new file mode 100644
index 0000000000..53a62fbf1c
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs
@@ -0,0 +1,72 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Abstract server runner.
+ /// </summary>
+ public interface IServerRunner
+ {
+ /// <summary>
+ /// Port on which the server is listening.
+ /// </summary>
+ int BoundPort { get; }
+
+ /// <summary>
+ /// Gets server stats.
+ /// </summary>
+ /// <returns>The stats.</returns>
+ ServerStats GetStats(bool reset);
+
+ /// <summary>
+ /// Asynchronously stops the server.
+ /// </summary>
+ /// <returns>Task that finishes when server has shutdown.</returns>
+ Task StopAsync();
+ }
+
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 5eec11abf7..b0e33e49f7 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -34,6 +34,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -130,8 +131,7 @@ namespace Grpc.IntegrationTesting
};
}
var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions);
- TestService.TestServiceClient client = new TestService.TestServiceClient(channel);
- await RunTestCaseAsync(client, options);
+ await RunTestCaseAsync(channel, options);
await channel.ShutdownAsync();
}
@@ -159,8 +159,9 @@ namespace Grpc.IntegrationTesting
return credentials;
}
- private async Task RunTestCaseAsync(TestService.TestServiceClient client, ClientOptions options)
+ private async Task RunTestCaseAsync(Channel channel, ClientOptions options)
{
+ var client = new TestService.TestServiceClient(channel);
switch (options.TestCase)
{
case "empty_unary":
@@ -202,8 +203,14 @@ namespace Grpc.IntegrationTesting
case "timeout_on_sleeping_server":
await RunTimeoutOnSleepingServerAsync(client);
break;
- case "benchmark_empty_unary":
- RunBenchmarkEmptyUnary(client);
+ case "custom_metadata":
+ await RunCustomMetadataAsync(client);
+ break;
+ case "status_code_and_message":
+ await RunStatusCodeAndMessageAsync(client);
+ break;
+ case "unimplemented_method":
+ RunUnimplementedMethod(new UnimplementedService.UnimplementedServiceClient(channel));
break;
default:
throw new ArgumentException("Unknown test case " + options.TestCase);
@@ -227,7 +234,6 @@ namespace Grpc.IntegrationTesting
ResponseSize = 314159,
Payload = CreateZerosPayload(271828)
};
-
var response = client.UnaryCall(request);
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
@@ -493,11 +499,95 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
- // This is not an official interop test, but it's useful.
- public static void RunBenchmarkEmptyUnary(TestService.ITestServiceClient client)
+ public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client)
{
- BenchmarkUtil.RunBenchmark(10000, 10000,
- () => { client.EmptyCall(new Empty()); });
+ Console.WriteLine("running custom_metadata");
+ {
+ // step 1: test unary call
+ var request = new SimpleRequest
+ {
+ ResponseType = PayloadType.COMPRESSABLE,
+ ResponseSize = 314159,
+ Payload = CreateZerosPayload(271828)
+ };
+
+ var call = client.UnaryCallAsync(request, headers: CreateTestMetadata());
+ await call.ResponseAsync;
+
+ var responseHeaders = await call.ResponseHeadersAsync;
+ var responseTrailers = call.GetTrailers();
+
+ Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
+ CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
+ }
+
+ {
+ // step 2: test full duplex call
+ var request = new StreamingOutputCallRequest
+ {
+ ResponseType = PayloadType.COMPRESSABLE,
+ ResponseParameters = { new ResponseParameters { Size = 31415 } },
+ Payload = CreateZerosPayload(27182)
+ };
+
+ var call = client.FullDuplexCall(headers: CreateTestMetadata());
+ var responseHeaders = await call.ResponseHeadersAsync;
+
+ await call.RequestStream.WriteAsync(request);
+ await call.RequestStream.CompleteAsync();
+ await call.ResponseStream.ToListAsync();
+
+ var responseTrailers = call.GetTrailers();
+
+ Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value);
+ CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes);
+ }
+
+ Console.WriteLine("Passed!");
+ }
+
+ public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client)
+ {
+ Console.WriteLine("running status_code_and_message");
+ var echoStatus = new EchoStatus
+ {
+ Code = 2,
+ Message = "test status message"
+ };
+
+ {
+ // step 1: test unary call
+ var request = new SimpleRequest { ResponseStatus = echoStatus };
+
+ var e = Assert.Throws<RpcException>(() => client.UnaryCall(request));
+ Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
+ Assert.AreEqual(echoStatus.Message, e.Status.Detail);
+ }
+
+ {
+ // step 2: test full duplex call
+ var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus };
+
+ var call = client.FullDuplexCall();
+ await call.RequestStream.WriteAsync(request);
+ await call.RequestStream.CompleteAsync();
+
+ var e = Assert.Throws<RpcException>(async () => await call.ResponseStream.ToListAsync());
+ Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
+ Assert.AreEqual(echoStatus.Message, e.Status.Detail);
+ }
+
+ Console.WriteLine("Passed!");
+ }
+
+ public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client)
+ {
+ Console.WriteLine("running unimplemented_method");
+ var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
+
+ Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
+ Assert.AreEqual("", e.Status.Detail);
+ Console.WriteLine("Passed!");
}
private static Payload CreateZerosPayload(int size)
@@ -516,5 +606,14 @@ namespace Grpc.IntegrationTesting
Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
return email;
}
+
+ private static Metadata CreateTestMetadata()
+ {
+ return new Metadata
+ {
+ {"x-grpc-test-echo-initial", "test_initial_metadata_value"},
+ {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}}
+ };
+ }
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 837ae74c45..18168f9970 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -128,9 +128,29 @@ namespace Grpc.IntegrationTesting
}
[Test]
- public async Task TimeoutOnSleepingServerAsync()
+ public async Task TimeoutOnSleepingServer()
{
await InteropClient.RunTimeoutOnSleepingServerAsync(client);
}
+
+ [Test]
+ public async Task CustomMetadata()
+ {
+ await InteropClient.RunCustomMetadataAsync(client);
+ }
+
+ [Test]
+ [Ignore("TODO: see #4427")]
+ public async Task StatusCodeAndMessage()
+ {
+ await InteropClient.RunStatusCodeAndMessageAsync(client);
+ }
+
+ [Test]
+ [Ignore("TODO: see #4427")]
+ public void UnimplementedMethod()
+ {
+ InteropClient.RunUnimplementedMethod(UnimplementedService.NewClient(channel));
+ }
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
index 35230f48c1..1c8bfed1f6 100644
--- a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
@@ -40,6 +40,7 @@ using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
+using Moq;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
@@ -50,37 +51,37 @@ namespace Grpc.IntegrationTesting
Server server;
Channel channel;
TestService.ITestServiceClient client;
+ List<ChannelOption> options;
+ Mock<TestService.ITestService> serviceMock;
+ AsyncAuthInterceptor asyncAuthInterceptor;
- [TestFixtureSetUp]
+ [SetUp]
public void Init()
{
- var serverCredentials = new SslServerCredentials(new[] { new KeyCertificatePair(File.ReadAllText(TestCredentials.ServerCertChainPath), File.ReadAllText(TestCredentials.ServerPrivateKeyPath)) });
+ serviceMock = new Mock<TestService.ITestService>();
+ serviceMock.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<ServerCallContext>()))
+ .Returns(new Func<SimpleRequest, ServerCallContext, Task<SimpleResponse>>(UnaryCallHandler));
+
server = new Server
{
- Services = { TestService.BindService(new TestServiceImpl()) },
- Ports = { { Host, ServerPort.PickUnused, serverCredentials } }
+ Services = { TestService.BindService(serviceMock.Object) },
+ Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateSslServerCredentials() } }
};
server.Start();
- var options = new List<ChannelOption>
+ options = new List<ChannelOption>
{
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
};
- var asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) =>
+ asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) =>
{
- await Task.Delay(100); // make sure the operation is asynchronous.
+ await Task.Delay(100).ConfigureAwait(false); // make sure the operation is asynchronous.
metadata.Add("authorization", "SECRET_TOKEN");
});
-
- var clientCredentials = ChannelCredentials.Create(
- new SslCredentials(File.ReadAllText(TestCredentials.ClientCertAuthorityPath)),
- CallCredentials.FromInterceptor(asyncAuthInterceptor));
- channel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options);
- client = TestService.NewClient(channel);
}
- [TestFixtureTearDown]
+ [TearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
@@ -90,8 +91,29 @@ namespace Grpc.IntegrationTesting
[Test]
public void MetadataCredentials()
{
- var response = client.UnaryCall(new SimpleRequest { ResponseSize = 10 });
- Assert.AreEqual(10, response.Payload.Body.Length);
+ var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(),
+ CallCredentials.FromInterceptor(asyncAuthInterceptor));
+ channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options);
+ client = TestService.NewClient(channel);
+
+ client.UnaryCall(new SimpleRequest {});
+ }
+
+ [Test]
+ public void MetadataCredentials_PerCall()
+ {
+ channel = new Channel(Host, server.Ports.Single().BoundPort, TestCredentials.CreateSslCredentials(), options);
+ client = TestService.NewClient(channel);
+
+ var callCredentials = CallCredentials.FromInterceptor(asyncAuthInterceptor);
+ client.UnaryCall(new SimpleRequest { }, new CallOptions(credentials: callCredentials));
+ }
+
+ private Task<SimpleResponse> UnaryCallHandler(SimpleRequest request, ServerCallContext context)
+ {
+ var authToken = context.RequestHeaders.First((entry) => entry.Key == "authorization").Value;
+ Assert.AreEqual("SECRET_TOKEN", authToken);
+ return Task.FromResult(new SimpleResponse());
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
new file mode 100644
index 0000000000..a37dd9a685
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
@@ -0,0 +1,580 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: test/proto/benchmarks/payloads.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 {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Payloads {
+
+ #region Descriptor
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static Payloads() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CiR0ZXN0L3Byb3RvL2JlbmNobWFya3MvcGF5bG9hZHMucHJvdG8SDGdycGMu",
+ "dGVzdGluZyI3ChBCeXRlQnVmZmVyUGFyYW1zEhAKCHJlcV9zaXplGAEgASgF",
+ "EhEKCXJlc3Bfc2l6ZRgCIAEoBSI4ChFTaW1wbGVQcm90b1BhcmFtcxIQCghy",
+ "ZXFfc2l6ZRgBIAEoBRIRCglyZXNwX3NpemUYAiABKAUiFAoSQ29tcGxleFBy",
+ "b3RvUGFyYW1zIsoBCg1QYXlsb2FkQ29uZmlnEjgKDmJ5dGVidWZfcGFyYW1z",
+ "GAEgASgLMh4uZ3JwYy50ZXN0aW5nLkJ5dGVCdWZmZXJQYXJhbXNIABI4Cg1z",
+ "aW1wbGVfcGFyYW1zGAIgASgLMh8uZ3JwYy50ZXN0aW5nLlNpbXBsZVByb3Rv",
+ "UGFyYW1zSAASOgoOY29tcGxleF9wYXJhbXMYAyABKAsyIC5ncnBjLnRlc3Rp",
+ "bmcuQ29tcGxleFByb3RvUGFyYW1zSABCCQoHcGF5bG9hZGIGcHJvdG8z"));
+ descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ByteBufferParams), new[]{ "ReqSize", "RespSize" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), new[]{ "ReqSize", "RespSize" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), null, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PayloadConfig), new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ByteBufferParams : pb::IMessage<ByteBufferParams> {
+ private static readonly pb::MessageParser<ByteBufferParams> _parser = new pb::MessageParser<ByteBufferParams>(() => new ByteBufferParams());
+ public static pb::MessageParser<ByteBufferParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[0]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ByteBufferParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ByteBufferParams(ByteBufferParams other) : this() {
+ reqSize_ = other.reqSize_;
+ respSize_ = other.respSize_;
+ }
+
+ public ByteBufferParams Clone() {
+ return new ByteBufferParams(this);
+ }
+
+ public const int ReqSizeFieldNumber = 1;
+ private int reqSize_;
+ public int ReqSize {
+ get { return reqSize_; }
+ set {
+ reqSize_ = value;
+ }
+ }
+
+ public const int RespSizeFieldNumber = 2;
+ private int respSize_;
+ public int RespSize {
+ get { return respSize_; }
+ set {
+ respSize_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ByteBufferParams);
+ }
+
+ public bool Equals(ByteBufferParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (ReqSize != other.ReqSize) return false;
+ if (RespSize != other.RespSize) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
+ if (RespSize != 0) hash ^= RespSize.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (ReqSize != 0) {
+ output.WriteRawTag(8);
+ output.WriteInt32(ReqSize);
+ }
+ if (RespSize != 0) {
+ output.WriteRawTag(16);
+ output.WriteInt32(RespSize);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (ReqSize != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize);
+ }
+ if (RespSize != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
+ }
+ return size;
+ }
+
+ public void MergeFrom(ByteBufferParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.ReqSize != 0) {
+ ReqSize = other.ReqSize;
+ }
+ if (other.RespSize != 0) {
+ RespSize = other.RespSize;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 8: {
+ ReqSize = input.ReadInt32();
+ break;
+ }
+ case 16: {
+ RespSize = input.ReadInt32();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class SimpleProtoParams : pb::IMessage<SimpleProtoParams> {
+ private static readonly pb::MessageParser<SimpleProtoParams> _parser = new pb::MessageParser<SimpleProtoParams>(() => new SimpleProtoParams());
+ public static pb::MessageParser<SimpleProtoParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[1]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public SimpleProtoParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public SimpleProtoParams(SimpleProtoParams other) : this() {
+ reqSize_ = other.reqSize_;
+ respSize_ = other.respSize_;
+ }
+
+ public SimpleProtoParams Clone() {
+ return new SimpleProtoParams(this);
+ }
+
+ public const int ReqSizeFieldNumber = 1;
+ private int reqSize_;
+ public int ReqSize {
+ get { return reqSize_; }
+ set {
+ reqSize_ = value;
+ }
+ }
+
+ public const int RespSizeFieldNumber = 2;
+ private int respSize_;
+ public int RespSize {
+ get { return respSize_; }
+ set {
+ respSize_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as SimpleProtoParams);
+ }
+
+ public bool Equals(SimpleProtoParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (ReqSize != other.ReqSize) return false;
+ if (RespSize != other.RespSize) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
+ if (RespSize != 0) hash ^= RespSize.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (ReqSize != 0) {
+ output.WriteRawTag(8);
+ output.WriteInt32(ReqSize);
+ }
+ if (RespSize != 0) {
+ output.WriteRawTag(16);
+ output.WriteInt32(RespSize);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (ReqSize != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize);
+ }
+ if (RespSize != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
+ }
+ return size;
+ }
+
+ public void MergeFrom(SimpleProtoParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.ReqSize != 0) {
+ ReqSize = other.ReqSize;
+ }
+ if (other.RespSize != 0) {
+ RespSize = other.RespSize;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 8: {
+ ReqSize = input.ReadInt32();
+ break;
+ }
+ case 16: {
+ RespSize = input.ReadInt32();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> {
+ private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams());
+ public static pb::MessageParser<ComplexProtoParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[2]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ComplexProtoParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ComplexProtoParams(ComplexProtoParams other) : this() {
+ }
+
+ public ComplexProtoParams Clone() {
+ return new ComplexProtoParams(this);
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ComplexProtoParams);
+ }
+
+ public bool Equals(ComplexProtoParams 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.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ return size;
+ }
+
+ public void MergeFrom(ComplexProtoParams other) {
+ if (other == null) {
+ return;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class PayloadConfig : pb::IMessage<PayloadConfig> {
+ private static readonly pb::MessageParser<PayloadConfig> _parser = new pb::MessageParser<PayloadConfig>(() => new PayloadConfig());
+ public static pb::MessageParser<PayloadConfig> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[3]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public PayloadConfig() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public PayloadConfig(PayloadConfig other) : this() {
+ switch (other.PayloadCase) {
+ case PayloadOneofCase.BytebufParams:
+ BytebufParams = other.BytebufParams.Clone();
+ break;
+ case PayloadOneofCase.SimpleParams:
+ SimpleParams = other.SimpleParams.Clone();
+ break;
+ case PayloadOneofCase.ComplexParams:
+ ComplexParams = other.ComplexParams.Clone();
+ break;
+ }
+
+ }
+
+ public PayloadConfig Clone() {
+ return new PayloadConfig(this);
+ }
+
+ public const int BytebufParamsFieldNumber = 1;
+ public global::Grpc.Testing.ByteBufferParams BytebufParams {
+ get { return payloadCase_ == PayloadOneofCase.BytebufParams ? (global::Grpc.Testing.ByteBufferParams) payload_ : null; }
+ set {
+ payload_ = value;
+ payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.BytebufParams;
+ }
+ }
+
+ public const int SimpleParamsFieldNumber = 2;
+ public global::Grpc.Testing.SimpleProtoParams SimpleParams {
+ get { return payloadCase_ == PayloadOneofCase.SimpleParams ? (global::Grpc.Testing.SimpleProtoParams) payload_ : null; }
+ set {
+ payload_ = value;
+ payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.SimpleParams;
+ }
+ }
+
+ public const int ComplexParamsFieldNumber = 3;
+ public global::Grpc.Testing.ComplexProtoParams ComplexParams {
+ get { return payloadCase_ == PayloadOneofCase.ComplexParams ? (global::Grpc.Testing.ComplexProtoParams) payload_ : null; }
+ set {
+ payload_ = value;
+ payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.ComplexParams;
+ }
+ }
+
+ private object payload_;
+ public enum PayloadOneofCase {
+ None = 0,
+ BytebufParams = 1,
+ SimpleParams = 2,
+ ComplexParams = 3,
+ }
+ private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
+ public PayloadOneofCase PayloadCase {
+ get { return payloadCase_; }
+ }
+
+ public void ClearPayload() {
+ payloadCase_ = PayloadOneofCase.None;
+ payload_ = null;
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as PayloadConfig);
+ }
+
+ public bool Equals(PayloadConfig other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(BytebufParams, other.BytebufParams)) return false;
+ if (!object.Equals(SimpleParams, other.SimpleParams)) return false;
+ if (!object.Equals(ComplexParams, other.ComplexParams)) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (payloadCase_ == PayloadOneofCase.BytebufParams) hash ^= BytebufParams.GetHashCode();
+ if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode();
+ if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (payloadCase_ == PayloadOneofCase.BytebufParams) {
+ output.WriteRawTag(10);
+ output.WriteMessage(BytebufParams);
+ }
+ if (payloadCase_ == PayloadOneofCase.SimpleParams) {
+ output.WriteRawTag(18);
+ output.WriteMessage(SimpleParams);
+ }
+ if (payloadCase_ == PayloadOneofCase.ComplexParams) {
+ output.WriteRawTag(26);
+ output.WriteMessage(ComplexParams);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (payloadCase_ == PayloadOneofCase.BytebufParams) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(BytebufParams);
+ }
+ if (payloadCase_ == PayloadOneofCase.SimpleParams) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(SimpleParams);
+ }
+ if (payloadCase_ == PayloadOneofCase.ComplexParams) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams);
+ }
+ return size;
+ }
+
+ public void MergeFrom(PayloadConfig other) {
+ if (other == null) {
+ return;
+ }
+ switch (other.PayloadCase) {
+ case PayloadOneofCase.BytebufParams:
+ BytebufParams = other.BytebufParams;
+ break;
+ case PayloadOneofCase.SimpleParams:
+ SimpleParams = other.SimpleParams;
+ break;
+ case PayloadOneofCase.ComplexParams:
+ ComplexParams = other.ComplexParams;
+ break;
+ }
+
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams();
+ if (payloadCase_ == PayloadOneofCase.BytebufParams) {
+ subBuilder.MergeFrom(BytebufParams);
+ }
+ input.ReadMessage(subBuilder);
+ BytebufParams = subBuilder;
+ break;
+ }
+ case 18: {
+ global::Grpc.Testing.SimpleProtoParams subBuilder = new global::Grpc.Testing.SimpleProtoParams();
+ if (payloadCase_ == PayloadOneofCase.SimpleParams) {
+ subBuilder.MergeFrom(SimpleParams);
+ }
+ input.ReadMessage(subBuilder);
+ SimpleParams = subBuilder;
+ break;
+ }
+ case 26: {
+ global::Grpc.Testing.ComplexProtoParams subBuilder = new global::Grpc.Testing.ComplexProtoParams();
+ if (payloadCase_ == PayloadOneofCase.ComplexParams) {
+ subBuilder.MergeFrom(ComplexParams);
+ }
+ input.ReadMessage(subBuilder);
+ ComplexParams = subBuilder;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
new file mode 100644
index 0000000000..686b484345
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -0,0 +1,108 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+using CommandLine;
+using CommandLine.Text;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+ public class QpsWorker
+ {
+ private class ServerOptions
+ {
+ [Option("driver_port", DefaultValue = 0)]
+ public int DriverPort { get; set; }
+
+ [HelpOption]
+ public string GetUsage()
+ {
+ var help = new HelpText
+ {
+ Heading = "gRPC C# performance testing worker",
+ AddDashesToOption = true
+ };
+ help.AddPreOptionsLine("Usage:");
+ help.AddOptions(this);
+ return help;
+ }
+ }
+
+ ServerOptions options;
+
+ private QpsWorker(ServerOptions options)
+ {
+ this.options = options;
+ }
+
+ public static void Run(string[] args)
+ {
+ var options = new ServerOptions();
+ if (!Parser.Default.ParseArguments(args, options))
+ {
+ Environment.Exit(1);
+ }
+
+ var workerServer = new QpsWorker(options);
+ workerServer.Run();
+ }
+
+ private void Run()
+ {
+ string host = "0.0.0.0";
+ int port = options.DriverPort;
+
+ var server = new Server
+ {
+ Services = { WorkerService.BindService(new WorkerServiceImpl()) },
+ Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )}
+ };
+ int boundPort = server.Ports.Single().BoundPort;
+ Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort));
+ server.Start();
+
+ server.ShutdownTask.Wait();
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
new file mode 100644
index 0000000000..3dd91b7948
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -0,0 +1,118 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Runs performance tests in-process.
+ /// </summary>
+ public class RunnerClientServerTest
+ {
+ const string Host = "localhost";
+ IServerRunner serverRunner;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ var serverConfig = new ServerConfig
+ {
+ ServerType = ServerType.ASYNC_SERVER,
+ Host = Host,
+ PayloadConfig = new PayloadConfig
+ {
+ SimpleParams = new SimpleProtoParams
+ {
+ RespSize = 100
+ }
+ }
+ };
+ serverRunner = ServerRunners.CreateStarted(serverConfig);
+ }
+
+ [TestFixtureTearDown]
+ public void Cleanup()
+ {
+ serverRunner.StopAsync().Wait();
+ }
+
+
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
+ public async Task ClientServerRunner()
+ {
+ var config = new ClientConfig
+ {
+ ServerTargets = { string.Format("{0}:{1}", Host, serverRunner.BoundPort) },
+ RpcType = RpcType.UNARY,
+ LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() },
+ PayloadConfig = new PayloadConfig
+ {
+ SimpleParams = new SimpleProtoParams
+ {
+ ReqSize = 100
+ }
+ },
+ HistogramParams = new HistogramParams
+ {
+ Resolution = 0.01,
+ MaxPossible = 60e9
+ }
+ };
+
+ var runner = ClientRunners.CreateStarted(config);
+
+ System.Console.WriteLine("Warming up");
+ await Task.Delay(3000);
+ runner.GetStats(true); // throw away warm-up data
+
+ System.Console.WriteLine("Benchmarking");
+ await Task.Delay(3000);
+ var stats = runner.GetStats(true);
+ await runner.StopAsync();
+
+ System.Console.WriteLine(stats);
+ System.Console.WriteLine("avg micros/call " + (long) (stats.Latencies.Sum / stats.Latencies.Count / 1000.0));
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
new file mode 100644
index 0000000000..e8be7758ce
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
@@ -0,0 +1,124 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Helper methods to start server runners for performance testing.
+ /// </summary>
+ public static class ServerRunners
+ {
+ /// <summary>
+ /// Creates a started server runner.
+ /// </summary>
+ public static IServerRunner CreateStarted(ServerConfig config)
+ {
+ Grpc.Core.Utils.Preconditions.CheckArgument(config.ServerType == ServerType.ASYNC_SERVER);
+ var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure;
+
+ // TODO: qps_driver needs to setup payload properly...
+ int responseSize = config.PayloadConfig != null ? config.PayloadConfig.SimpleParams.RespSize : 0;
+ var server = new Server
+ {
+ Services = { BenchmarkService.BindService(new BenchmarkServiceImpl(responseSize)) },
+ Ports = { new ServerPort(config.Host, config.Port, credentials) }
+ };
+
+ server.Start();
+ return new ServerRunnerImpl(server);
+ }
+ }
+
+ /// <summary>
+ /// Server runner.
+ /// </summary>
+ public class ServerRunnerImpl : IServerRunner
+ {
+ readonly Server server;
+ readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+
+ public ServerRunnerImpl(Server server)
+ {
+ this.server = Grpc.Core.Utils.Preconditions.CheckNotNull(server);
+ }
+
+ public int BoundPort
+ {
+ get
+ {
+ return server.Ports.Single().BoundPort;
+ }
+ }
+
+ /// <summary>
+ /// Gets server stats.
+ /// </summary>
+ /// <returns>The stats.</returns>
+ public ServerStats GetStats(bool reset)
+ {
+ var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
+
+ // TODO: populate user time and system time
+ return new ServerStats
+ {
+ TimeElapsed = secondsElapsed,
+ TimeUser = 0,
+ TimeSystem = 0
+ };
+ }
+
+ /// <summary>
+ /// Asynchronously stops the server.
+ /// </summary>
+ /// <returns>Task that finishes when server has shutdown.</returns>
+ public Task StopAsync()
+ {
+ return server.ShutdownAsync();
+ }
+ }
+
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Services.cs b/src/csharp/Grpc.IntegrationTesting/Services.cs
new file mode 100644
index 0000000000..b648da6734
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Services.cs
@@ -0,0 +1,44 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: test/proto/benchmarks/services.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 {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Services {
+
+ #region Descriptor
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static Services() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CiR0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc2VydmljZXMucHJvdG8SDGdycGMu",
+ "dGVzdGluZxoZdGVzdC9wcm90by9tZXNzYWdlcy5wcm90bxojdGVzdC9wcm90",
+ "by9iZW5jaG1hcmtzL2NvbnRyb2wucHJvdG8yqgEKEEJlbmNobWFya1NlcnZp",
+ "Y2USRgoJVW5hcnlDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa",
+ "HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2USTgoNU3RyZWFtaW5nQ2Fs",
+ "bBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5n",
+ "LlNpbXBsZVJlc3BvbnNlKAEwATKdAQoNV29ya2VyU2VydmljZRJFCglSdW5T",
+ "ZXJ2ZXISGC5ncnBjLnRlc3RpbmcuU2VydmVyQXJncxoaLmdycGMudGVzdGlu",
+ "Zy5TZXJ2ZXJTdGF0dXMoATABEkUKCVJ1bkNsaWVudBIYLmdycGMudGVzdGlu",
+ "Zy5DbGllbnRBcmdzGhouZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXR1cygBMAFi",
+ "BnByb3RvMw=="));
+ descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbr::FileDescriptor[] { global::Grpc.Testing.Messages.Descriptor, global::Grpc.Testing.Control.Descriptor, },
+ new pbr::GeneratedCodeInfo(null, null));
+ }
+ #endregion
+
+ }
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
new file mode 100644
index 0000000000..ce388c6d5c
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
@@ -0,0 +1,198 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: test/proto/benchmarks/services.proto
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Testing {
+ public static class BenchmarkService
+ {
+ static readonly string __ServiceName = "grpc.testing.BenchmarkService";
+
+ static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom);
+ static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom);
+
+ static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+ MethodType.Unary,
+ __ServiceName,
+ "UnaryCall",
+ __Marshaller_SimpleRequest,
+ __Marshaller_SimpleResponse);
+
+ static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+ MethodType.DuplexStreaming,
+ __ServiceName,
+ "StreamingCall",
+ __Marshaller_SimpleRequest,
+ __Marshaller_SimpleResponse);
+
+ // service descriptor
+ public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+ {
+ get { return global::Grpc.Testing.Services.Descriptor.Services[0]; }
+ }
+
+ // client interface
+ public interface IBenchmarkServiceClient
+ {
+ global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+ AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+ AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options);
+ }
+
+ // server-side interface
+ public interface IBenchmarkService
+ {
+ Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
+ Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
+ }
+
+ // client stub
+ public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient
+ {
+ public BenchmarkServiceClient(Channel channel) : base(channel)
+ {
+ }
+ public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.BlockingUnaryCall(call, request);
+ }
+ public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_UnaryCall, options);
+ return Calls.BlockingUnaryCall(call, request);
+ }
+ public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncUnaryCall(call, request);
+ }
+ public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_UnaryCall, options);
+ return Calls.AsyncUnaryCall(call, request);
+ }
+ public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
+ {
+ var call = CreateCall(__Method_StreamingCall, options);
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ }
+
+ // creates service definition that can be registered with a server
+ public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl)
+ {
+ 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
+ {
+ static readonly string __ServiceName = "grpc.testing.WorkerService";
+
+ static readonly Marshaller<global::Grpc.Testing.ServerArgs> __Marshaller_ServerArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom);
+ static readonly Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom);
+ static readonly Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom);
+ static readonly Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom);
+
+ static readonly Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>(
+ MethodType.DuplexStreaming,
+ __ServiceName,
+ "RunServer",
+ __Marshaller_ServerArgs,
+ __Marshaller_ServerStatus);
+
+ static readonly Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> __Method_RunClient = new Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus>(
+ MethodType.DuplexStreaming,
+ __ServiceName,
+ "RunClient",
+ __Marshaller_ClientArgs,
+ __Marshaller_ClientStatus);
+
+ // service descriptor
+ public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+ {
+ get { return global::Grpc.Testing.Services.Descriptor.Services[1]; }
+ }
+
+ // client interface
+ public interface IWorkerServiceClient
+ {
+ AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options);
+ AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options);
+ }
+
+ // server-side interface
+ public interface IWorkerService
+ {
+ Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
+ Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context);
+ }
+
+ // client stub
+ public class WorkerServiceClient : ClientBase, IWorkerServiceClient
+ {
+ public WorkerServiceClient(Channel channel) : base(channel)
+ {
+ }
+ public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
+ {
+ var call = CreateCall(__Method_RunServer, options);
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
+ {
+ var call = CreateCall(__Method_RunClient, options);
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ }
+
+ // creates service definition that can be registered with a server
+ public static ServerServiceDefinition BindService(IWorkerService serviceImpl)
+ {
+ return ServerServiceDefinition.CreateBuilder(__ServiceName)
+ .AddMethod(__Method_RunServer, serviceImpl.RunServer)
+ .AddMethod(__Method_RunClient, serviceImpl.RunClient).Build();
+ }
+
+ // creates a new client
+ public static WorkerServiceClient NewClient(Channel channel)
+ {
+ return new WorkerServiceClient(channel);
+ }
+
+ }
+}
+#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
index fb99cd4af1..746f2ef5ce 100644
--- a/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
+++ b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
@@ -1,7 +1,10 @@
<StyleCopSettings Version="105">
<SourceFileList>
- <SourceFile>Messages.cs</SourceFile>
<SourceFile>Empty.cs</SourceFile>
+ <SourceFile>Control.cs</SourceFile>
+ <SourceFile>Messages.cs</SourceFile>
+ <SourceFile>Payloads.cs</SourceFile>
+ <SourceFile>Stats.cs</SourceFile>
<Settings>
<GlobalSettings>
<BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
new file mode 100644
index 0000000000..4ae66baffa
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -0,0 +1,744 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: test/proto/benchmarks/stats.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 {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Stats {
+
+ #region Descriptor
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static Stats() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CiF0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc3RhdHMucHJvdG8SDGdycGMudGVz",
+ "dGluZyJLCgtTZXJ2ZXJTdGF0cxIUCgx0aW1lX2VsYXBzZWQYASABKAESEQoJ",
+ "dGltZV91c2VyGAIgASgBEhMKC3RpbWVfc3lzdGVtGAMgASgBIjsKD0hpc3Rv",
+ "Z3JhbVBhcmFtcxISCgpyZXNvbHV0aW9uGAEgASgBEhQKDG1heF9wb3NzaWJs",
+ "ZRgCIAEoASJ3Cg1IaXN0b2dyYW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQCght",
+ "aW5fc2VlbhgCIAEoARIQCghtYXhfc2VlbhgDIAEoARILCgNzdW0YBCABKAES",
+ "FgoOc3VtX29mX3NxdWFyZXMYBSABKAESDQoFY291bnQYBiABKAEiewoLQ2xp",
+ "ZW50U3RhdHMSLgoJbGF0ZW5jaWVzGAEgASgLMhsuZ3JwYy50ZXN0aW5nLkhp",
+ "c3RvZ3JhbURhdGESFAoMdGltZV9lbGFwc2VkGAIgASgBEhEKCXRpbWVfdXNl",
+ "chgDIAEoARITCgt0aW1lX3N5c3RlbRgEIAEoAWIGcHJvdG8z"));
+ descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStats), new[]{ "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramParams), new[]{ "Resolution", "MaxPossible" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramData), new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStats), new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ServerStats : pb::IMessage<ServerStats> {
+ private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats());
+ public static pb::MessageParser<ServerStats> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[0]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ServerStats() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ServerStats(ServerStats other) : this() {
+ timeElapsed_ = other.timeElapsed_;
+ timeUser_ = other.timeUser_;
+ timeSystem_ = other.timeSystem_;
+ }
+
+ public ServerStats Clone() {
+ return new ServerStats(this);
+ }
+
+ public const int TimeElapsedFieldNumber = 1;
+ private double timeElapsed_;
+ public double TimeElapsed {
+ get { return timeElapsed_; }
+ set {
+ timeElapsed_ = value;
+ }
+ }
+
+ public const int TimeUserFieldNumber = 2;
+ private double timeUser_;
+ public double TimeUser {
+ get { return timeUser_; }
+ set {
+ timeUser_ = value;
+ }
+ }
+
+ public const int TimeSystemFieldNumber = 3;
+ private double timeSystem_;
+ public double TimeSystem {
+ get { return timeSystem_; }
+ set {
+ timeSystem_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ServerStats);
+ }
+
+ public bool Equals(ServerStats other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (TimeElapsed != other.TimeElapsed) return false;
+ if (TimeUser != other.TimeUser) return false;
+ if (TimeSystem != other.TimeSystem) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
+ if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
+ if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (TimeElapsed != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(TimeElapsed);
+ }
+ if (TimeUser != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(TimeUser);
+ }
+ if (TimeSystem != 0D) {
+ output.WriteRawTag(25);
+ output.WriteDouble(TimeSystem);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (TimeElapsed != 0D) {
+ size += 1 + 8;
+ }
+ if (TimeUser != 0D) {
+ size += 1 + 8;
+ }
+ if (TimeSystem != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(ServerStats other) {
+ if (other == null) {
+ return;
+ }
+ if (other.TimeElapsed != 0D) {
+ TimeElapsed = other.TimeElapsed;
+ }
+ if (other.TimeUser != 0D) {
+ TimeUser = other.TimeUser;
+ }
+ if (other.TimeSystem != 0D) {
+ TimeSystem = other.TimeSystem;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ TimeElapsed = input.ReadDouble();
+ break;
+ }
+ case 17: {
+ TimeUser = input.ReadDouble();
+ break;
+ }
+ case 25: {
+ TimeSystem = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
+ private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
+ public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[1]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public HistogramParams() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public HistogramParams(HistogramParams other) : this() {
+ resolution_ = other.resolution_;
+ maxPossible_ = other.maxPossible_;
+ }
+
+ public HistogramParams Clone() {
+ return new HistogramParams(this);
+ }
+
+ public const int ResolutionFieldNumber = 1;
+ private double resolution_;
+ public double Resolution {
+ get { return resolution_; }
+ set {
+ resolution_ = value;
+ }
+ }
+
+ public const int MaxPossibleFieldNumber = 2;
+ private double maxPossible_;
+ public double MaxPossible {
+ get { return maxPossible_; }
+ set {
+ maxPossible_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as HistogramParams);
+ }
+
+ public bool Equals(HistogramParams other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Resolution != other.Resolution) return false;
+ if (MaxPossible != other.MaxPossible) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Resolution != 0D) hash ^= Resolution.GetHashCode();
+ if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Resolution != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(Resolution);
+ }
+ if (MaxPossible != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(MaxPossible);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Resolution != 0D) {
+ size += 1 + 8;
+ }
+ if (MaxPossible != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(HistogramParams other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Resolution != 0D) {
+ Resolution = other.Resolution;
+ }
+ if (other.MaxPossible != 0D) {
+ MaxPossible = other.MaxPossible;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ Resolution = input.ReadDouble();
+ break;
+ }
+ case 17: {
+ MaxPossible = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HistogramData : pb::IMessage<HistogramData> {
+ private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
+ public static pb::MessageParser<HistogramData> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[2]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public HistogramData() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public HistogramData(HistogramData other) : this() {
+ bucket_ = other.bucket_.Clone();
+ minSeen_ = other.minSeen_;
+ maxSeen_ = other.maxSeen_;
+ sum_ = other.sum_;
+ sumOfSquares_ = other.sumOfSquares_;
+ count_ = other.count_;
+ }
+
+ public HistogramData Clone() {
+ return new HistogramData(this);
+ }
+
+ public const int BucketFieldNumber = 1;
+ private static readonly pb::FieldCodec<uint> _repeated_bucket_codec
+ = pb::FieldCodec.ForUInt32(10);
+ private readonly pbc::RepeatedField<uint> bucket_ = new pbc::RepeatedField<uint>();
+ public pbc::RepeatedField<uint> Bucket {
+ get { return bucket_; }
+ }
+
+ public const int MinSeenFieldNumber = 2;
+ private double minSeen_;
+ public double MinSeen {
+ get { return minSeen_; }
+ set {
+ minSeen_ = value;
+ }
+ }
+
+ public const int MaxSeenFieldNumber = 3;
+ private double maxSeen_;
+ public double MaxSeen {
+ get { return maxSeen_; }
+ set {
+ maxSeen_ = value;
+ }
+ }
+
+ public const int SumFieldNumber = 4;
+ private double sum_;
+ public double Sum {
+ get { return sum_; }
+ set {
+ sum_ = value;
+ }
+ }
+
+ public const int SumOfSquaresFieldNumber = 5;
+ private double sumOfSquares_;
+ public double SumOfSquares {
+ get { return sumOfSquares_; }
+ set {
+ sumOfSquares_ = value;
+ }
+ }
+
+ public const int CountFieldNumber = 6;
+ private double count_;
+ public double Count {
+ get { return count_; }
+ set {
+ count_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as HistogramData);
+ }
+
+ public bool Equals(HistogramData other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if(!bucket_.Equals(other.bucket_)) return false;
+ if (MinSeen != other.MinSeen) return false;
+ if (MaxSeen != other.MaxSeen) return false;
+ if (Sum != other.Sum) return false;
+ if (SumOfSquares != other.SumOfSquares) return false;
+ if (Count != other.Count) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ hash ^= bucket_.GetHashCode();
+ if (MinSeen != 0D) hash ^= MinSeen.GetHashCode();
+ if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode();
+ if (Sum != 0D) hash ^= Sum.GetHashCode();
+ if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode();
+ if (Count != 0D) hash ^= Count.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ bucket_.WriteTo(output, _repeated_bucket_codec);
+ if (MinSeen != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(MinSeen);
+ }
+ if (MaxSeen != 0D) {
+ output.WriteRawTag(25);
+ output.WriteDouble(MaxSeen);
+ }
+ if (Sum != 0D) {
+ output.WriteRawTag(33);
+ output.WriteDouble(Sum);
+ }
+ if (SumOfSquares != 0D) {
+ output.WriteRawTag(41);
+ output.WriteDouble(SumOfSquares);
+ }
+ if (Count != 0D) {
+ output.WriteRawTag(49);
+ output.WriteDouble(Count);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ size += bucket_.CalculateSize(_repeated_bucket_codec);
+ if (MinSeen != 0D) {
+ size += 1 + 8;
+ }
+ if (MaxSeen != 0D) {
+ size += 1 + 8;
+ }
+ if (Sum != 0D) {
+ size += 1 + 8;
+ }
+ if (SumOfSquares != 0D) {
+ size += 1 + 8;
+ }
+ if (Count != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(HistogramData other) {
+ if (other == null) {
+ return;
+ }
+ bucket_.Add(other.bucket_);
+ if (other.MinSeen != 0D) {
+ MinSeen = other.MinSeen;
+ }
+ if (other.MaxSeen != 0D) {
+ MaxSeen = other.MaxSeen;
+ }
+ if (other.Sum != 0D) {
+ Sum = other.Sum;
+ }
+ if (other.SumOfSquares != 0D) {
+ SumOfSquares = other.SumOfSquares;
+ }
+ if (other.Count != 0D) {
+ Count = other.Count;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10:
+ case 8: {
+ bucket_.AddEntriesFrom(input, _repeated_bucket_codec);
+ break;
+ }
+ case 17: {
+ MinSeen = input.ReadDouble();
+ break;
+ }
+ case 25: {
+ MaxSeen = input.ReadDouble();
+ break;
+ }
+ case 33: {
+ Sum = input.ReadDouble();
+ break;
+ }
+ case 41: {
+ SumOfSquares = input.ReadDouble();
+ break;
+ }
+ case 49: {
+ Count = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class ClientStats : pb::IMessage<ClientStats> {
+ private static readonly pb::MessageParser<ClientStats> _parser = new pb::MessageParser<ClientStats>(() => new ClientStats());
+ public static pb::MessageParser<ClientStats> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[3]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public ClientStats() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public ClientStats(ClientStats other) : this() {
+ Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
+ timeElapsed_ = other.timeElapsed_;
+ timeUser_ = other.timeUser_;
+ timeSystem_ = other.timeSystem_;
+ }
+
+ public ClientStats Clone() {
+ return new ClientStats(this);
+ }
+
+ public const int LatenciesFieldNumber = 1;
+ private global::Grpc.Testing.HistogramData latencies_;
+ public global::Grpc.Testing.HistogramData Latencies {
+ get { return latencies_; }
+ set {
+ latencies_ = value;
+ }
+ }
+
+ public const int TimeElapsedFieldNumber = 2;
+ private double timeElapsed_;
+ public double TimeElapsed {
+ get { return timeElapsed_; }
+ set {
+ timeElapsed_ = value;
+ }
+ }
+
+ public const int TimeUserFieldNumber = 3;
+ private double timeUser_;
+ public double TimeUser {
+ get { return timeUser_; }
+ set {
+ timeUser_ = value;
+ }
+ }
+
+ public const int TimeSystemFieldNumber = 4;
+ private double timeSystem_;
+ public double TimeSystem {
+ get { return timeSystem_; }
+ set {
+ timeSystem_ = value;
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as ClientStats);
+ }
+
+ public bool Equals(ClientStats other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(Latencies, other.Latencies)) return false;
+ if (TimeElapsed != other.TimeElapsed) return false;
+ if (TimeUser != other.TimeUser) return false;
+ if (TimeSystem != other.TimeSystem) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (latencies_ != null) hash ^= Latencies.GetHashCode();
+ if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
+ if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
+ if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (latencies_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(Latencies);
+ }
+ if (TimeElapsed != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(TimeElapsed);
+ }
+ if (TimeUser != 0D) {
+ output.WriteRawTag(25);
+ output.WriteDouble(TimeUser);
+ }
+ if (TimeSystem != 0D) {
+ output.WriteRawTag(33);
+ output.WriteDouble(TimeSystem);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (latencies_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
+ }
+ if (TimeElapsed != 0D) {
+ size += 1 + 8;
+ }
+ if (TimeUser != 0D) {
+ size += 1 + 8;
+ }
+ if (TimeSystem != 0D) {
+ size += 1 + 8;
+ }
+ return size;
+ }
+
+ public void MergeFrom(ClientStats other) {
+ if (other == null) {
+ return;
+ }
+ if (other.latencies_ != null) {
+ if (latencies_ == null) {
+ latencies_ = new global::Grpc.Testing.HistogramData();
+ }
+ Latencies.MergeFrom(other.Latencies);
+ }
+ if (other.TimeElapsed != 0D) {
+ TimeElapsed = other.TimeElapsed;
+ }
+ if (other.TimeUser != 0D) {
+ TimeUser = other.TimeUser;
+ }
+ if (other.TimeSystem != 0D) {
+ TimeSystem = other.TimeSystem;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ if (latencies_ == null) {
+ latencies_ = new global::Grpc.Testing.HistogramData();
+ }
+ input.ReadMessage(latencies_);
+ break;
+ }
+ case 17: {
+ TimeElapsed = input.ReadDouble();
+ break;
+ }
+ case 25: {
+ TimeUser = input.ReadDouble();
+ break;
+ }
+ case 33: {
+ TimeSystem = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
index c5bfcf08c0..5a1b4cf319 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
@@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
@@ -51,14 +52,20 @@ namespace Grpc.Testing
return Task.FromResult(new Empty());
}
- public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+ public async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
+ await EnsureEchoMetadataAsync(context);
+ EnsureEchoStatus(request.ResponseStatus, context);
+
var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) };
- return Task.FromResult(response);
+ return response;
}
public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
+ await EnsureEchoMetadataAsync(context);
+ EnsureEchoStatus(request.ResponseStatus, context);
+
foreach (var responseParam in request.ResponseParameters)
{
var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) };
@@ -68,6 +75,8 @@ namespace Grpc.Testing
public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
{
+ await EnsureEchoMetadataAsync(context);
+
int sum = 0;
await requestStream.ForEachAsync(async request =>
{
@@ -78,8 +87,11 @@ namespace Grpc.Testing
public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
+ await EnsureEchoMetadataAsync(context);
+
await requestStream.ForEachAsync(async request =>
{
+ EnsureEchoStatus(request.ResponseStatus, context);
foreach (var responseParam in request.ResponseParameters)
{
var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) };
@@ -97,5 +109,28 @@ namespace Grpc.Testing
{
return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
}
+
+ private static async Task EnsureEchoMetadataAsync(ServerCallContext context)
+ {
+ var echoInitialList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-initial").ToList();
+ if (echoInitialList.Any()) {
+ var entry = echoInitialList.Single();
+ await context.WriteResponseHeadersAsync(new Metadata { entry });
+ }
+
+ var echoTrailingList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ToList();
+ if (echoTrailingList.Any()) {
+ context.ResponseTrailers.Add(echoTrailingList.Single());
+ }
+ }
+
+ private static void EnsureEchoStatus(EchoStatus responseStatus, ServerCallContext context)
+ {
+ if (responseStatus != null)
+ {
+ var statusCode = (StatusCode)responseStatus.Code;
+ context.Status = new Status(statusCode, responseStatus.Message);
+ }
+ }
}
}
diff --git a/src/csharp/Grpc.Examples/proto/math.proto b/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
index 311e148c02..e44ae2a5ff 100644
--- a/src/csharp/Grpc.Examples/proto/math.proto
+++ b/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
@@ -1,3 +1,4 @@
+#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
@@ -28,53 +29,50 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-syntax = "proto3";
+#endregion
-package math;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
-message DivArgs {
- int64 dividend = 1;
- int64 divisor = 2;
-}
-
-message DivReply {
- int64 quotient = 1;
- int64 remainder = 2;
-}
-
-message FibArgs {
- int64 limit = 1;
-}
-
-message Num {
- int64 num = 1;
-}
-
-message FibReply {
- int64 count = 1;
-}
-
-service Math {
- // Div divides args.dividend by args.divisor and returns the quotient and
- // remainder.
- rpc Div (DivArgs) returns (DivReply) {
- }
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// Snapshottable wall clock stopwatch.
+ /// </summary>
+ public class WallClockStopwatch
+ {
+ long startTicks;
- // 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.
- rpc DivMany (stream DivArgs) returns (stream DivReply) {
- }
+ public WallClockStopwatch()
+ {
+ this.startTicks = DateTime.UtcNow.Ticks;
+ }
- // 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.
- rpc Fib (FibArgs) returns (stream Num) {
- }
+ public TimeSpan GetElapsedSnapshot(bool reset)
+ {
+ var utcNow = DateTime.UtcNow;
- // Sum sums a stream of numbers, returning the final result once the stream
- // is closed.
- rpc Sum (stream Num) returns (Num) {
- }
+ long oldStartTicks;
+ if (reset)
+ {
+ oldStartTicks = Interlocked.Exchange(ref this.startTicks, utcNow.Ticks);
+ }
+ else
+ {
+ oldStartTicks = this.startTicks;
+ }
+ return utcNow - new DateTime(oldStartTicks, DateTimeKind.Utc);
+ }
+ }
}
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
new file mode 100644
index 0000000000..bb2918bf46
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
@@ -0,0 +1,96 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.IntegrationTesting;
+
+namespace Grpc.Testing
+{
+ /// <summary>
+ /// Implementation of WorkerService server
+ /// </summary>
+ public class WorkerServiceImpl : WorkerService.IWorkerService
+ {
+ public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
+ {
+ Grpc.Core.Utils.Preconditions.CheckState(await requestStream.MoveNext());
+ var serverConfig = requestStream.Current.Setup;
+ var runner = ServerRunners.CreateStarted(serverConfig);
+
+ await responseStream.WriteAsync(new ServerStatus
+ {
+ Stats = runner.GetStats(false),
+ Port = runner.BoundPort,
+ Cores = 0, // TODO: set number of cores
+ });
+
+ while (await requestStream.MoveNext())
+ {
+ var reset = requestStream.Current.Mark.Reset;
+ await responseStream.WriteAsync(new ServerStatus
+ {
+ Stats = runner.GetStats(reset)
+ });
+ }
+ await runner.StopAsync();
+ }
+
+ public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
+ {
+ Grpc.Core.Utils.Preconditions.CheckState(await requestStream.MoveNext());
+ var clientConfig = requestStream.Current.Setup;
+ var runner = ClientRunners.CreateStarted(clientConfig);
+
+ await responseStream.WriteAsync(new ClientStatus
+ {
+ Stats = runner.GetStats(false)
+ });
+
+ while (await requestStream.MoveNext())
+ {
+ var reset = requestStream.Current.Mark.Reset;
+ await responseStream.WriteAsync(new ClientStatus
+ {
+ Stats = runner.GetStats(reset)
+ });
+ }
+ await runner.StopAsync();
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index bdb3dadf44..5c59af1b7d 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -11,6 +11,7 @@
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
+ <package id="Moq" version="4.2.1510.2205" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
index f19f29c6a2..8ff35e8c0d 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
+# Visual Studio 2012
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples", "Grpc.Examples\Grpc.Examples.csproj", "{7DC1433E-3225-42C7-B7EA-546D56E27A4B}"
@@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck", "Grpc.He
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck.Tests", "Grpc.HealthCheck.Tests\Grpc.HealthCheck.Tests.csproj", "{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -39,72 +41,78 @@ Global
ReleaseSigned|Any CPU = ReleaseSigned|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.Build.0 = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU
- {C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.Build.0 = Release|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|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
- {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.Build.0 = Release|Any CPU
- {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{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
+ {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
+ {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+ {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -112,6 +120,8 @@ Global
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index f879e074aa..4dbd9c3308 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -30,19 +30,19 @@
# Regenerates gRPC service stubs from proto files.
set +e
-cd $(dirname $0)
+cd $(dirname $0)/../..
-PROTOC=../../bins/opt/protobuf/protoc
-PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin
-EXAMPLES_DIR=Grpc.Examples
-INTEROP_DIR=Grpc.IntegrationTesting
-HEALTHCHECK_DIR=Grpc.HealthCheck
+PROTOC=bins/opt/protobuf/protoc
+PLUGIN=protoc-gen-grpc=bins/opt/grpc_csharp_plugin
+EXAMPLES_DIR=src/csharp/Grpc.Examples
+HEALTHCHECK_DIR=src/csharp/Grpc.HealthCheck
+TESTING_DIR=src/csharp/Grpc.IntegrationTesting
$PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
- -I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto
-
-$PROTOC --plugin=$PLUGIN --csharp_out=$INTEROP_DIR --grpc_out=$INTEROP_DIR \
- -I ../.. ../../test/proto/*.proto
+ -I src/proto/math src/proto/math/math.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \
- -I $HEALTHCHECK_DIR/proto $HEALTHCHECK_DIR/proto/health.proto
+ -I src/proto/grpc/health/v1alpha src/proto/grpc/health/v1alpha/health.proto
+
+$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
+ -I . test/proto/{empty,messages,test}.proto test/proto/benchmarks/*.proto
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
new file mode 100644
index 0000000000..4aa93668ad
--- /dev/null
+++ b/src/csharp/tests.json
@@ -0,0 +1,45 @@
+{
+ "assemblies": [
+ "Grpc.Core.Tests",
+ "Grpc.Examples.Tests",
+ "Grpc.HealthCheck.Tests",
+ "Grpc.IntegrationTesting"
+ ],
+ "tests": [
+ "Grpc.Core.Internal.Tests.AsyncCallTest",
+ "Grpc.Core.Internal.Tests.ChannelArgsSafeHandleTest",
+ "Grpc.Core.Internal.Tests.CompletionQueueEventTest",
+ "Grpc.Core.Internal.Tests.CompletionQueueSafeHandleTest",
+ "Grpc.Core.Internal.Tests.MetadataArraySafeHandleTest",
+ "Grpc.Core.Internal.Tests.TimespecTest",
+ "Grpc.Core.Tests.CallCredentialsTest",
+ "Grpc.Core.Tests.CallOptionsTest",
+ "Grpc.Core.Tests.ChannelCredentialsTest",
+ "Grpc.Core.Tests.ChannelOptionsTest",
+ "Grpc.Core.Tests.ChannelTest",
+ "Grpc.Core.Tests.ClientServerTest",
+ "Grpc.Core.Tests.CompressionTest",
+ "Grpc.Core.Tests.ContextPropagationTest",
+ "Grpc.Core.Tests.GrpcEnvironmentTest",
+ "Grpc.Core.Tests.MarshallingErrorsTest",
+ "Grpc.Core.Tests.MetadataTest",
+ "Grpc.Core.Tests.NUnitVersionTest",
+ "Grpc.Core.Tests.PerformanceTest",
+ "Grpc.Core.Tests.PInvokeTest",
+ "Grpc.Core.Tests.ResponseHeadersTest",
+ "Grpc.Core.Tests.SanityTest",
+ "Grpc.Core.Tests.ServerTest",
+ "Grpc.Core.Tests.ShutdownTest",
+ "Grpc.Core.Tests.TimeoutsTest",
+ "Grpc.Core.Tests.UserAgentStringTest",
+ "Math.Tests.MathClientServerTest",
+ "Grpc.HealthCheck.Tests.HealthClientServerTest",
+ "Grpc.HealthCheck.Tests.HealthServiceImplTest",
+ "Grpc.IntegrationTesting.HeaderInterceptorTest",
+ "Grpc.IntegrationTesting.HistogramTest",
+ "Grpc.IntegrationTesting.InteropClientServerTest",
+ "Grpc.IntegrationTesting.MetadataCredentialsTest",
+ "Grpc.IntegrationTesting.RunnerClientServerTest",
+ "Grpc.IntegrationTesting.SslCredentialsTest"
+ ]
+} \ No newline at end of file