diff options
author | vjpai <vpai@google.com> | 2015-11-30 15:53:49 -0800 |
---|---|---|
committer | vjpai <vpai@google.com> | 2015-11-30 15:53:49 -0800 |
commit | 594f0c43e0cceea10ca897759aa2912b7fa9e37f (patch) | |
tree | 6d944754be07f05bd88b8f2cdd2c957c181813dc /src/csharp/Grpc.IntegrationTesting | |
parent | b6df94ad220b9e48d306150184848db614cc3506 (diff) | |
parent | 73081d15824a5aa876ee048f5a29aeba1bc4bd16 (diff) |
Merge branch 'master' into bbuf
Diffstat (limited to 'src/csharp/Grpc.IntegrationTesting')
18 files changed, 5117 insertions, 31 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(); + } + } +} |