aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp/Grpc.IntegrationTesting
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp/Grpc.IntegrationTesting')
-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.csproj67
-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/Payloads.cs580
-rw-r--r--src/csharp/Grpc.IntegrationTesting/QpsWorker.cs108
-rw-r--r--src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs117
-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/WallClockStopwatch.cs78
-rw-r--r--src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs96
-rw-r--r--src/csharp/Grpc.IntegrationTesting/data/server1.pem28
19 files changed, 5131 insertions, 45 deletions
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..012de45524 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -38,55 +38,46 @@
<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="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">
@@ -104,6 +95,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/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/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..2b51526c88
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -0,0 +1,117 @@
+#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 attribute commented out to prevent running as part of the default test suite.
+ //[Test]
+ //[Category("Performance")]
+ 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/WallClockStopwatch.cs b/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
new file mode 100644
index 0000000000..e44ae2a5ff
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
@@ -0,0 +1,78 @@
+#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>
+ /// Snapshottable wall clock stopwatch.
+ /// </summary>
+ public class WallClockStopwatch
+ {
+ long startTicks;
+
+ public WallClockStopwatch()
+ {
+ this.startTicks = DateTime.UtcNow.Ticks;
+ }
+
+ public TimeSpan GetElapsedSnapshot(bool reset)
+ {
+ var utcNow = DateTime.UtcNow;
+
+ 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/data/server1.pem b/src/csharp/Grpc.IntegrationTesting/data/server1.pem
index 8e582e571f..f3d43fcc5b 100644
--- a/src/csharp/Grpc.IntegrationTesting/data/server1.pem
+++ b/src/csharp/Grpc.IntegrationTesting/data/server1.pem
@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
-----END CERTIFICATE-----