// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: src/proto/grpc/testing/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 {

  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/control.proto</summary>
  public static partial class ControlReflection {

    #region Descriptor
    /// <summary>File descriptor for src/proto/grpc/testing/control.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static ControlReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2NvbnRyb2wucHJvdG8SDGdycGMu",
            "dGVzdGluZxolc3JjL3Byb3RvL2dycGMvdGVzdGluZy9wYXlsb2Fkcy5wcm90",
            "bxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90byIlCg1Qb2lz",
            "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASISChBDbG9zZWRMb29w",
            "UGFyYW1zInsKCkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5n",
            "cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB",
            "KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiQwoO",
            "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
            "X2hvc3Rfb3ZlcnJpZGUYAiABKAkiTQoKQ2hhbm5lbEFyZxIMCgRuYW1lGAEg",
            "ASgJEhMKCXN0cl92YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoBUgA",
            "QgcKBXZhbHVlIqAECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY",
            "ASADKAkSLQoLY2xpZW50X3R5cGUYAiABKA4yGC5ncnBjLnRlc3RpbmcuQ2xp",
            "ZW50VHlwZRI1Cg9zZWN1cml0eV9wYXJhbXMYAyABKAsyHC5ncnBjLnRlc3Rp",
            "bmcuU2VjdXJpdHlQYXJhbXMSJAocb3V0c3RhbmRpbmdfcnBjc19wZXJfY2hh",
            "bm5lbBgEIAEoBRIXCg9jbGllbnRfY2hhbm5lbHMYBSABKAUSHAoUYXN5bmNf",
            "Y2xpZW50X3RocmVhZHMYByABKAUSJwoIcnBjX3R5cGUYCCABKA4yFS5ncnBj",
            "LnRlc3RpbmcuUnBjVHlwZRItCgtsb2FkX3BhcmFtcxgKIAEoCzIYLmdycGMu",
            "dGVzdGluZy5Mb2FkUGFyYW1zEjMKDnBheWxvYWRfY29uZmlnGAsgASgLMhsu",
            "Z3JwYy50ZXN0aW5nLlBheWxvYWRDb25maWcSNwoQaGlzdG9ncmFtX3BhcmFt",
            "cxgMIAEoCzIdLmdycGMudGVzdGluZy5IaXN0b2dyYW1QYXJhbXMSEQoJY29y",
            "ZV9saXN0GA0gAygFEhIKCmNvcmVfbGltaXQYDiABKAUSGAoQb3RoZXJfY2xp",
            "ZW50X2FwaRgPIAEoCRIuCgxjaGFubmVsX2FyZ3MYECADKAsyGC5ncnBjLnRl",
            "c3RpbmcuQ2hhbm5lbEFyZyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASAB",
            "KAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNl",
            "dBgBIAEoCCJoCgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50",
            "ZXN0aW5nLkNsaWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRl",
            "c3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUitAIKDFNlcnZlckNvbmZpZxItCgtz",
            "ZXJ2ZXJfdHlwZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUK",
            "D3NlY3VyaXR5X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0",
            "eVBhcmFtcxIMCgRwb3J0GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRz",
            "GAcgASgFEhIKCmNvcmVfbGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcY",
            "CSABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xp",
            "c3QYCiADKAUSGAoQb3RoZXJfc2VydmVyX2FwaRgLIAEoCRIcChNyZXNvdXJj",
            "ZV9xdW90YV9zaXplGOkHIAEoBSJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEg",
            "ASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiAB",
            "KAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVy",
            "U3RhdHVzEigKBXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0",
            "YXRzEgwKBHBvcnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVl",
            "c3QiHQoMQ29yZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEK",
            "CFNjZW5hcmlvEgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEo",
            "CzIaLmdycGMudGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMY",
            "AyABKAUSMQoNc2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5T",
            "ZXJ2ZXJDb25maWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3Nl",
            "Y29uZHMYBiABKAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bh",
            "d25fbG9jYWxfd29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglz",
            "Y2VuYXJpb3MYASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8i+AIKFVNj",
            "ZW5hcmlvUmVzdWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9z",
            "ZXJ2ZXJfY29yZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAES",
            "GAoQc2VydmVyX3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3Rp",
            "bWUYBSABKAESGAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5",
            "XzUwGAcgASgBEhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJ",
            "IAEoARISCgpsYXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgB",
            "EhgKEHNlcnZlcl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1",
            "ZXN0c19wZXJfc2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJf",
            "c2Vjb25kGA4gASgBIoMDCg5TY2VuYXJpb1Jlc3VsdBIoCghzY2VuYXJpbxgB",
            "IAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIuCglsYXRlbmNpZXMYAiAB",
            "KAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIvCgxjbGllbnRfc3Rh",
            "dHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMSLwoMc2VydmVy",
            "X3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEhQKDHNl",
            "cnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYgASgLMiMuZ3JwYy50ZXN0",
            "aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5jbGllbnRfc3VjY2VzcxgH",
            "IAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5Cg9yZXF1ZXN0X3Jlc3Vs",
            "dHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVzdFJlc3VsdENvdW50KkEK",
            "CkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQ",
            "ARIQCgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS",
            "VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW",
            "RVIQAhIQCgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAAS",
            "DQoJU1RSRUFNSU5HEAFiBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ResourceQuotaSize" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  public enum ClientType {
    /// <summary>
    /// Many languages support a basic distinction between using
    /// sync or async client, and this allows the specification
    /// </summary>
    [pbr::OriginalName("SYNC_CLIENT")] SyncClient = 0,
    [pbr::OriginalName("ASYNC_CLIENT")] AsyncClient = 1,
    /// <summary>
    /// used for some language-specific variants
    /// </summary>
    [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2,
  }

  public enum ServerType {
    [pbr::OriginalName("SYNC_SERVER")] SyncServer = 0,
    [pbr::OriginalName("ASYNC_SERVER")] AsyncServer = 1,
    [pbr::OriginalName("ASYNC_GENERIC_SERVER")] AsyncGenericServer = 2,
    /// <summary>
    /// used for some language-specific variants
    /// </summary>
    [pbr::OriginalName("OTHER_SERVER")] OtherServer = 3,
  }

  public enum RpcType {
    [pbr::OriginalName("UNARY")] Unary = 0,
    [pbr::OriginalName("STREAMING")] Streaming = 1,
  }

  #endregion

  #region Messages
  /// <summary>
  /// Parameters of poisson process distribution, which is a good representation
  /// of activity coming in from independent identical stationary sources.
  /// </summary>
  public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
    private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<PoissonParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public PoissonParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public PoissonParams(PoissonParams other) : this() {
      offeredLoad_ = other.offeredLoad_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public PoissonParams Clone() {
      return new PoissonParams(this);
    }

    /// <summary>Field number for the "offered_load" field.</summary>
    public const int OfferedLoadFieldNumber = 1;
    private double offeredLoad_;
    /// <summary>
    /// The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double OfferedLoad {
      get { return offeredLoad_; }
      set {
        offeredLoad_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as PoissonParams);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (OfferedLoad != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(OfferedLoad);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (OfferedLoad != 0D) {
        size += 1 + 8;
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(PoissonParams other) {
      if (other == null) {
        return;
      }
      if (other.OfferedLoad != 0D) {
        OfferedLoad = other.OfferedLoad;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  /// <summary>
  /// Once an RPC finishes, immediately start a new one.
  /// No configuration parameters needed.
  /// </summary>
  public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
    private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[1]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClosedLoopParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClosedLoopParams(ClosedLoopParams other) : this() {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClosedLoopParams Clone() {
      return new ClosedLoopParams(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ClosedLoopParams);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ClosedLoopParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClosedLoopParams other) {
      if (other == null) {
        return;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
        }
      }
    }

  }

  public sealed partial class LoadParams : pb::IMessage<LoadParams> {
    private static readonly pb::MessageParser<LoadParams> _parser = new pb::MessageParser<LoadParams>(() => new LoadParams());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<LoadParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[2]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LoadParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LoadParams(LoadParams other) : this() {
      switch (other.LoadCase) {
        case LoadOneofCase.ClosedLoop:
          ClosedLoop = other.ClosedLoop.Clone();
          break;
        case LoadOneofCase.Poisson:
          Poisson = other.Poisson.Clone();
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LoadParams Clone() {
      return new LoadParams(this);
    }

    /// <summary>Field number for the "closed_loop" field.</summary>
    public const int ClosedLoopFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }
    }

    /// <summary>Field number for the "poisson" field.</summary>
    public const int PoissonFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }
    }

    private object load_;
    /// <summary>Enum of possible cases for the "load" oneof.</summary>
    public enum LoadOneofCase {
      None = 0,
      ClosedLoop = 1,
      Poisson = 2,
    }
    private LoadOneofCase loadCase_ = LoadOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LoadOneofCase LoadCase {
      get { return loadCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearLoad() {
      loadCase_ = LoadOneofCase.None;
      load_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as LoadParams);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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 (LoadCase != other.LoadCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
      if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
      hash ^= (int) loadCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  /// <summary>
  /// presence of SecurityParams implies use of TLS
  /// </summary>
  public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
    private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[3]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public SecurityParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public SecurityParams(SecurityParams other) : this() {
      useTestCa_ = other.useTestCa_;
      serverHostOverride_ = other.serverHostOverride_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public SecurityParams Clone() {
      return new SecurityParams(this);
    }

    /// <summary>Field number for the "use_test_ca" field.</summary>
    public const int UseTestCaFieldNumber = 1;
    private bool useTestCa_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool UseTestCa {
      get { return useTestCa_; }
      set {
        useTestCa_ = value;
      }
    }

    /// <summary>Field number for the "server_host_override" field.</summary>
    public const int ServerHostOverrideFieldNumber = 2;
    private string serverHostOverride_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ServerHostOverride {
      get { return serverHostOverride_; }
      set {
        serverHostOverride_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as SecurityParams);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (UseTestCa != false) hash ^= UseTestCa.GetHashCode();
      if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (UseTestCa != false) {
        size += 1 + 1;
      }
      if (ServerHostOverride.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ServerHostOverride);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(SecurityParams other) {
      if (other == null) {
        return;
      }
      if (other.UseTestCa != false) {
        UseTestCa = other.UseTestCa;
      }
      if (other.ServerHostOverride.Length != 0) {
        ServerHostOverride = other.ServerHostOverride;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  public sealed partial class ChannelArg : pb::IMessage<ChannelArg> {
    private static readonly pb::MessageParser<ChannelArg> _parser = new pb::MessageParser<ChannelArg>(() => new ChannelArg());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ChannelArg> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ChannelArg() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ChannelArg(ChannelArg other) : this() {
      name_ = other.name_;
      switch (other.ValueCase) {
        case ValueOneofCase.StrValue:
          StrValue = other.StrValue;
          break;
        case ValueOneofCase.IntValue:
          IntValue = other.IntValue;
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ChannelArg Clone() {
      return new ChannelArg(this);
    }

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Name {
      get { return name_; }
      set {
        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "str_value" field.</summary>
    public const int StrValueFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string StrValue {
      get { return valueCase_ == ValueOneofCase.StrValue ? (string) value_ : ""; }
      set {
        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        valueCase_ = ValueOneofCase.StrValue;
      }
    }

    /// <summary>Field number for the "int_value" field.</summary>
    public const int IntValueFieldNumber = 3;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int IntValue {
      get { return valueCase_ == ValueOneofCase.IntValue ? (int) value_ : 0; }
      set {
        value_ = value;
        valueCase_ = ValueOneofCase.IntValue;
      }
    }

    private object value_;
    /// <summary>Enum of possible cases for the "value" oneof.</summary>
    public enum ValueOneofCase {
      None = 0,
      StrValue = 2,
      IntValue = 3,
    }
    private ValueOneofCase valueCase_ = ValueOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ValueOneofCase ValueCase {
      get { return valueCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearValue() {
      valueCase_ = ValueOneofCase.None;
      value_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ChannelArg);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ChannelArg other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if (StrValue != other.StrValue) return false;
      if (IntValue != other.IntValue) return false;
      if (ValueCase != other.ValueCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode();
      if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode();
      hash ^= (int) valueCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      if (valueCase_ == ValueOneofCase.StrValue) {
        output.WriteRawTag(18);
        output.WriteString(StrValue);
      }
      if (valueCase_ == ValueOneofCase.IntValue) {
        output.WriteRawTag(24);
        output.WriteInt32(IntValue);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (valueCase_ == ValueOneofCase.StrValue) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(StrValue);
      }
      if (valueCase_ == ValueOneofCase.IntValue) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ChannelArg other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      switch (other.ValueCase) {
        case ValueOneofCase.StrValue:
          StrValue = other.StrValue;
          break;
        case ValueOneofCase.IntValue:
          IntValue = other.IntValue;
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            StrValue = input.ReadString();
            break;
          }
          case 24: {
            IntValue = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  public sealed partial class ClientConfig : pb::IMessage<ClientConfig> {
    private static readonly pb::MessageParser<ClientConfig> _parser = new pb::MessageParser<ClientConfig>(() => new ClientConfig());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ClientConfig> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientConfig() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      coreList_ = other.coreList_.Clone();
      coreLimit_ = other.coreLimit_;
      otherClientApi_ = other.otherClientApi_;
      channelArgs_ = other.channelArgs_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientConfig Clone() {
      return new ClientConfig(this);
    }

    /// <summary>Field number for the "server_targets" field.</summary>
    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>();
    /// <summary>
    /// List of targets to connect to. At least one target needs to be specified.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> ServerTargets {
      get { return serverTargets_; }
    }

    /// <summary>Field number for the "client_type" field.</summary>
    public const int ClientTypeFieldNumber = 2;
    private global::Grpc.Testing.ClientType clientType_ = 0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientType ClientType {
      get { return clientType_; }
      set {
        clientType_ = value;
      }
    }

    /// <summary>Field number for the "security_params" field.</summary>
    public const int SecurityParamsFieldNumber = 3;
    private global::Grpc.Testing.SecurityParams securityParams_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.SecurityParams SecurityParams {
      get { return securityParams_; }
      set {
        securityParams_ = value;
      }
    }

    /// <summary>Field number for the "outstanding_rpcs_per_channel" field.</summary>
    public const int OutstandingRpcsPerChannelFieldNumber = 4;
    private int outstandingRpcsPerChannel_;
    /// <summary>
    /// How many concurrent RPCs to start for each channel.
    /// For synchronous client, use a separate thread for each outstanding RPC.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int OutstandingRpcsPerChannel {
      get { return outstandingRpcsPerChannel_; }
      set {
        outstandingRpcsPerChannel_ = value;
      }
    }

    /// <summary>Field number for the "client_channels" field.</summary>
    public const int ClientChannelsFieldNumber = 5;
    private int clientChannels_;
    /// <summary>
    /// Number of independent client channels to create.
    /// i-th channel will connect to server_target[i % server_targets.size()]
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ClientChannels {
      get { return clientChannels_; }
      set {
        clientChannels_ = value;
      }
    }

    /// <summary>Field number for the "async_client_threads" field.</summary>
    public const int AsyncClientThreadsFieldNumber = 7;
    private int asyncClientThreads_;
    /// <summary>
    /// Only for async client. Number of threads to use to start/manage RPCs.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int AsyncClientThreads {
      get { return asyncClientThreads_; }
      set {
        asyncClientThreads_ = value;
      }
    }

    /// <summary>Field number for the "rpc_type" field.</summary>
    public const int RpcTypeFieldNumber = 8;
    private global::Grpc.Testing.RpcType rpcType_ = 0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.RpcType RpcType {
      get { return rpcType_; }
      set {
        rpcType_ = value;
      }
    }

    /// <summary>Field number for the "load_params" field.</summary>
    public const int LoadParamsFieldNumber = 10;
    private global::Grpc.Testing.LoadParams loadParams_;
    /// <summary>
    /// The requested load for the entire client (aggregated over all the threads).
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.LoadParams LoadParams {
      get { return loadParams_; }
      set {
        loadParams_ = value;
      }
    }

    /// <summary>Field number for the "payload_config" field.</summary>
    public const int PayloadConfigFieldNumber = 11;
    private global::Grpc.Testing.PayloadConfig payloadConfig_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadConfig PayloadConfig {
      get { return payloadConfig_; }
      set {
        payloadConfig_ = value;
      }
    }

    /// <summary>Field number for the "histogram_params" field.</summary>
    public const int HistogramParamsFieldNumber = 12;
    private global::Grpc.Testing.HistogramParams histogramParams_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.HistogramParams HistogramParams {
      get { return histogramParams_; }
      set {
        histogramParams_ = value;
      }
    }

    /// <summary>Field number for the "core_list" field.</summary>
    public const int CoreListFieldNumber = 13;
    private static readonly pb::FieldCodec<int> _repeated_coreList_codec
        = pb::FieldCodec.ForInt32(106);
    private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
    /// <summary>
    /// Specify the cores we should run the client on, if desired
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> CoreList {
      get { return coreList_; }
    }

    /// <summary>Field number for the "core_limit" field.</summary>
    public const int CoreLimitFieldNumber = 14;
    private int coreLimit_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CoreLimit {
      get { return coreLimit_; }
      set {
        coreLimit_ = value;
      }
    }

    /// <summary>Field number for the "other_client_api" field.</summary>
    public const int OtherClientApiFieldNumber = 15;
    private string otherClientApi_ = "";
    /// <summary>
    /// If we use an OTHER_CLIENT client_type, this string gives more detail
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string OtherClientApi {
      get { return otherClientApi_; }
      set {
        otherClientApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "channel_args" field.</summary>
    public const int ChannelArgsFieldNumber = 16;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ChannelArg> _repeated_channelArgs_codec
        = pb::FieldCodec.ForMessage(130, global::Grpc.Testing.ChannelArg.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ChannelArg> channelArgs_ = new pbc::RepeatedField<global::Grpc.Testing.ChannelArg>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ChannelArg> ChannelArgs {
      get { return channelArgs_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ClientConfig);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      if(!coreList_.Equals(other.coreList_)) return false;
      if (CoreLimit != other.CoreLimit) return false;
      if (OtherClientApi != other.OtherClientApi) return false;
      if(!channelArgs_.Equals(other.channelArgs_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= serverTargets_.GetHashCode();
      if (ClientType != 0) 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 != 0) hash ^= RpcType.GetHashCode();
      if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
      if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
      hash ^= coreList_.GetHashCode();
      if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
      if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
      hash ^= channelArgs_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      serverTargets_.WriteTo(output, _repeated_serverTargets_codec);
      if (ClientType != 0) {
        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 != 0) {
        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);
      }
      coreList_.WriteTo(output, _repeated_coreList_codec);
      if (CoreLimit != 0) {
        output.WriteRawTag(112);
        output.WriteInt32(CoreLimit);
      }
      if (OtherClientApi.Length != 0) {
        output.WriteRawTag(122);
        output.WriteString(OtherClientApi);
      }
      channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += serverTargets_.CalculateSize(_repeated_serverTargets_codec);
      if (ClientType != 0) {
        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 != 0) {
        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);
      }
      size += coreList_.CalculateSize(_repeated_coreList_codec);
      if (CoreLimit != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
      }
      if (OtherClientApi.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
      }
      size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClientConfig other) {
      if (other == null) {
        return;
      }
      serverTargets_.Add(other.serverTargets_);
      if (other.ClientType != 0) {
        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 != 0) {
        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);
      }
      coreList_.Add(other.coreList_);
      if (other.CoreLimit != 0) {
        CoreLimit = other.CoreLimit;
      }
      if (other.OtherClientApi.Length != 0) {
        OtherClientApi = other.OtherClientApi;
      }
      channelArgs_.Add(other.channelArgs_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
          case 106:
          case 104: {
            coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
            break;
          }
          case 112: {
            CoreLimit = input.ReadInt32();
            break;
          }
          case 122: {
            OtherClientApi = input.ReadString();
            break;
          }
          case 130: {
            channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec);
            break;
          }
        }
      }
    }

  }

  public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
    private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ClientStatus> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientStatus() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientStatus(ClientStatus other) : this() {
      Stats = other.stats_ != null ? other.Stats.Clone() : null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientStatus Clone() {
      return new ClientStatus(this);
    }

    /// <summary>Field number for the "stats" field.</summary>
    public const int StatsFieldNumber = 1;
    private global::Grpc.Testing.ClientStats stats_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientStats Stats {
      get { return stats_; }
      set {
        stats_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ClientStatus);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (stats_ != null) hash ^= Stats.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (stats_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Stats);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (stats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  /// <summary>
  /// Request current stats
  /// </summary>
  public sealed partial class Mark : pb::IMessage<Mark> {
    private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Mark> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Mark() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Mark(Mark other) : this() {
      reset_ = other.reset_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Mark Clone() {
      return new Mark(this);
    }

    /// <summary>Field number for the "reset" field.</summary>
    public const int ResetFieldNumber = 1;
    private bool reset_;
    /// <summary>
    /// if true, the stats will be reset after taking their snapshot.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Reset {
      get { return reset_; }
      set {
        reset_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as Mark);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Reset != false) hash ^= Reset.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Reset != false) {
        output.WriteRawTag(8);
        output.WriteBool(Reset);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Reset != false) {
        size += 1 + 1;
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Mark other) {
      if (other == null) {
        return;
      }
      if (other.Reset != false) {
        Reset = other.Reset;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  public sealed partial class ClientArgs : pb::IMessage<ClientArgs> {
    private static readonly pb::MessageParser<ClientArgs> _parser = new pb::MessageParser<ClientArgs>(() => new ClientArgs());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ClientArgs> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientArgs(ClientArgs other) : this() {
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup.Clone();
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark.Clone();
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientArgs Clone() {
      return new ClientArgs(this);
    }

    /// <summary>Field number for the "setup" field.</summary>
    public const int SetupFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }
    }

    /// <summary>Field number for the "mark" field.</summary>
    public const int MarkFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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_;
    /// <summary>Enum of possible cases for the "argtype" oneof.</summary>
    public enum ArgtypeOneofCase {
      None = 0,
      Setup = 1,
      Mark = 2,
    }
    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ArgtypeOneofCase ArgtypeCase {
      get { return argtypeCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearArgtype() {
      argtypeCase_ = ArgtypeOneofCase.None;
      argtype_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ClientArgs);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      if (ArgtypeCase != other.ArgtypeCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
      hash ^= (int) argtypeCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  public sealed partial class ServerConfig : pb::IMessage<ServerConfig> {
    private static readonly pb::MessageParser<ServerConfig> _parser = new pb::MessageParser<ServerConfig>(() => new ServerConfig());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServerConfig> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerConfig() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerConfig(ServerConfig other) : this() {
      serverType_ = other.serverType_;
      SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
      port_ = other.port_;
      asyncServerThreads_ = other.asyncServerThreads_;
      coreLimit_ = other.coreLimit_;
      PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
      coreList_ = other.coreList_.Clone();
      otherServerApi_ = other.otherServerApi_;
      resourceQuotaSize_ = other.resourceQuotaSize_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerConfig Clone() {
      return new ServerConfig(this);
    }

    /// <summary>Field number for the "server_type" field.</summary>
    public const int ServerTypeFieldNumber = 1;
    private global::Grpc.Testing.ServerType serverType_ = 0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerType ServerType {
      get { return serverType_; }
      set {
        serverType_ = value;
      }
    }

    /// <summary>Field number for the "security_params" field.</summary>
    public const int SecurityParamsFieldNumber = 2;
    private global::Grpc.Testing.SecurityParams securityParams_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.SecurityParams SecurityParams {
      get { return securityParams_; }
      set {
        securityParams_ = value;
      }
    }

    /// <summary>Field number for the "port" field.</summary>
    public const int PortFieldNumber = 4;
    private int port_;
    /// <summary>
    /// Port on which to listen. Zero means pick unused port.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Port {
      get { return port_; }
      set {
        port_ = value;
      }
    }

    /// <summary>Field number for the "async_server_threads" field.</summary>
    public const int AsyncServerThreadsFieldNumber = 7;
    private int asyncServerThreads_;
    /// <summary>
    /// Only for async server. Number of threads used to serve the requests.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int AsyncServerThreads {
      get { return asyncServerThreads_; }
      set {
        asyncServerThreads_ = value;
      }
    }

    /// <summary>Field number for the "core_limit" field.</summary>
    public const int CoreLimitFieldNumber = 8;
    private int coreLimit_;
    /// <summary>
    /// Specify the number of cores to limit server to, if desired
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CoreLimit {
      get { return coreLimit_; }
      set {
        coreLimit_ = value;
      }
    }

    /// <summary>Field number for the "payload_config" field.</summary>
    public const int PayloadConfigFieldNumber = 9;
    private global::Grpc.Testing.PayloadConfig payloadConfig_;
    /// <summary>
    /// payload config, used in generic server.
    /// Note this must NOT be used in proto (non-generic) servers. For proto servers,
    /// 'response sizes' must be configured from the 'response_size' field of the
    /// 'SimpleRequest' objects in RPC requests.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadConfig PayloadConfig {
      get { return payloadConfig_; }
      set {
        payloadConfig_ = value;
      }
    }

    /// <summary>Field number for the "core_list" field.</summary>
    public const int CoreListFieldNumber = 10;
    private static readonly pb::FieldCodec<int> _repeated_coreList_codec
        = pb::FieldCodec.ForInt32(82);
    private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
    /// <summary>
    /// Specify the cores we should run the server on, if desired
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> CoreList {
      get { return coreList_; }
    }

    /// <summary>Field number for the "other_server_api" field.</summary>
    public const int OtherServerApiFieldNumber = 11;
    private string otherServerApi_ = "";
    /// <summary>
    /// If we use an OTHER_SERVER client_type, this string gives more detail
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string OtherServerApi {
      get { return otherServerApi_; }
      set {
        otherServerApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "resource_quota_size" field.</summary>
    public const int ResourceQuotaSizeFieldNumber = 1001;
    private int resourceQuotaSize_;
    /// <summary>
    /// Buffer pool size (no buffer pool specified if unset)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ResourceQuotaSize {
      get { return resourceQuotaSize_; }
      set {
        resourceQuotaSize_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ServerConfig);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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 (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;
      if(!coreList_.Equals(other.coreList_)) return false;
      if (OtherServerApi != other.OtherServerApi) return false;
      if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ServerType != 0) hash ^= ServerType.GetHashCode();
      if (securityParams_ != null) hash ^= SecurityParams.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();
      hash ^= coreList_.GetHashCode();
      if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
      if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (ServerType != 0) {
        output.WriteRawTag(8);
        output.WriteEnum((int) ServerType);
      }
      if (securityParams_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(SecurityParams);
      }
      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);
      }
      coreList_.WriteTo(output, _repeated_coreList_codec);
      if (OtherServerApi.Length != 0) {
        output.WriteRawTag(90);
        output.WriteString(OtherServerApi);
      }
      if (ResourceQuotaSize != 0) {
        output.WriteRawTag(200, 62);
        output.WriteInt32(ResourceQuotaSize);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ServerType != 0) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType);
      }
      if (securityParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
      }
      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);
      }
      size += coreList_.CalculateSize(_repeated_coreList_codec);
      if (OtherServerApi.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
      }
      if (ResourceQuotaSize != 0) {
        size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerConfig other) {
      if (other == null) {
        return;
      }
      if (other.ServerType != 0) {
        ServerType = other.ServerType;
      }
      if (other.securityParams_ != null) {
        if (securityParams_ == null) {
          securityParams_ = new global::Grpc.Testing.SecurityParams();
        }
        SecurityParams.MergeFrom(other.SecurityParams);
      }
      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);
      }
      coreList_.Add(other.coreList_);
      if (other.OtherServerApi.Length != 0) {
        OtherServerApi = other.OtherServerApi;
      }
      if (other.ResourceQuotaSize != 0) {
        ResourceQuotaSize = other.ResourceQuotaSize;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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 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;
          }
          case 82:
          case 80: {
            coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
            break;
          }
          case 90: {
            OtherServerApi = input.ReadString();
            break;
          }
          case 8008: {
            ResourceQuotaSize = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  public sealed partial class ServerArgs : pb::IMessage<ServerArgs> {
    private static readonly pb::MessageParser<ServerArgs> _parser = new pb::MessageParser<ServerArgs>(() => new ServerArgs());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServerArgs> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerArgs(ServerArgs other) : this() {
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup.Clone();
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark.Clone();
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerArgs Clone() {
      return new ServerArgs(this);
    }

    /// <summary>Field number for the "setup" field.</summary>
    public const int SetupFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }
    }

    /// <summary>Field number for the "mark" field.</summary>
    public const int MarkFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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_;
    /// <summary>Enum of possible cases for the "argtype" oneof.</summary>
    public enum ArgtypeOneofCase {
      None = 0,
      Setup = 1,
      Mark = 2,
    }
    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ArgtypeOneofCase ArgtypeCase {
      get { return argtypeCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearArgtype() {
      argtypeCase_ = ArgtypeOneofCase.None;
      argtype_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ServerArgs);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      if (ArgtypeCase != other.ArgtypeCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
      hash ^= (int) argtypeCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  public sealed partial class ServerStatus : pb::IMessage<ServerStatus> {
    private static readonly pb::MessageParser<ServerStatus> _parser = new pb::MessageParser<ServerStatus>(() => new ServerStatus());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServerStatus> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerStatus() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerStatus(ServerStatus other) : this() {
      Stats = other.stats_ != null ? other.Stats.Clone() : null;
      port_ = other.port_;
      cores_ = other.cores_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerStatus Clone() {
      return new ServerStatus(this);
    }

    /// <summary>Field number for the "stats" field.</summary>
    public const int StatsFieldNumber = 1;
    private global::Grpc.Testing.ServerStats stats_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerStats Stats {
      get { return stats_; }
      set {
        stats_ = value;
      }
    }

    /// <summary>Field number for the "port" field.</summary>
    public const int PortFieldNumber = 2;
    private int port_;
    /// <summary>
    /// the port bound by the server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Port {
      get { return port_; }
      set {
        port_ = value;
      }
    }

    /// <summary>Field number for the "cores" field.</summary>
    public const int CoresFieldNumber = 3;
    private int cores_;
    /// <summary>
    /// Number of cores available to the server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Cores {
      get { return cores_; }
      set {
        cores_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ServerStatus);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    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;
          }
        }
      }
    }

  }

  public sealed partial class CoreRequest : pb::IMessage<CoreRequest> {
    private static readonly pb::MessageParser<CoreRequest> _parser = new pb::MessageParser<CoreRequest>(() => new CoreRequest());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<CoreRequest> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreRequest(CoreRequest other) : this() {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreRequest Clone() {
      return new CoreRequest(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as CoreRequest);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(CoreRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(CoreRequest other) {
      if (other == null) {
        return;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
        }
      }
    }

  }

  public sealed partial class CoreResponse : pb::IMessage<CoreResponse> {
    private static readonly pb::MessageParser<CoreResponse> _parser = new pb::MessageParser<CoreResponse>(() => new CoreResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<CoreResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreResponse(CoreResponse other) : this() {
      cores_ = other.cores_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreResponse Clone() {
      return new CoreResponse(this);
    }

    /// <summary>Field number for the "cores" field.</summary>
    public const int CoresFieldNumber = 1;
    private int cores_;
    /// <summary>
    /// Number of cores available on the server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Cores {
      get { return cores_; }
      set {
        cores_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as CoreResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(CoreResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Cores != other.Cores) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Cores != 0) hash ^= Cores.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Cores != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(Cores);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Cores != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(CoreResponse other) {
      if (other == null) {
        return;
      }
      if (other.Cores != 0) {
        Cores = other.Cores;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            Cores = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  public sealed partial class Void : pb::IMessage<Void> {
    private static readonly pb::MessageParser<Void> _parser = new pb::MessageParser<Void>(() => new Void());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Void> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Void() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Void(Void other) : this() {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Void Clone() {
      return new Void(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as Void);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(Void other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Void other) {
      if (other == null) {
        return;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
        }
      }
    }

  }

  /// <summary>
  /// A single performance scenario: input to qps_json_driver
  /// </summary>
  public sealed partial class Scenario : pb::IMessage<Scenario> {
    private static readonly pb::MessageParser<Scenario> _parser = new pb::MessageParser<Scenario>(() => new Scenario());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Scenario> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenario() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenario(Scenario other) : this() {
      name_ = other.name_;
      ClientConfig = other.clientConfig_ != null ? other.ClientConfig.Clone() : null;
      numClients_ = other.numClients_;
      ServerConfig = other.serverConfig_ != null ? other.ServerConfig.Clone() : null;
      numServers_ = other.numServers_;
      warmupSeconds_ = other.warmupSeconds_;
      benchmarkSeconds_ = other.benchmarkSeconds_;
      spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenario Clone() {
      return new Scenario(this);
    }

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    /// Human readable name for this scenario
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Name {
      get { return name_; }
      set {
        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "client_config" field.</summary>
    public const int ClientConfigFieldNumber = 2;
    private global::Grpc.Testing.ClientConfig clientConfig_;
    /// <summary>
    /// Client configuration
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientConfig ClientConfig {
      get { return clientConfig_; }
      set {
        clientConfig_ = value;
      }
    }

    /// <summary>Field number for the "num_clients" field.</summary>
    public const int NumClientsFieldNumber = 3;
    private int numClients_;
    /// <summary>
    /// Number of clients to start for the test
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int NumClients {
      get { return numClients_; }
      set {
        numClients_ = value;
      }
    }

    /// <summary>Field number for the "server_config" field.</summary>
    public const int ServerConfigFieldNumber = 4;
    private global::Grpc.Testing.ServerConfig serverConfig_;
    /// <summary>
    /// Server configuration
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerConfig ServerConfig {
      get { return serverConfig_; }
      set {
        serverConfig_ = value;
      }
    }

    /// <summary>Field number for the "num_servers" field.</summary>
    public const int NumServersFieldNumber = 5;
    private int numServers_;
    /// <summary>
    /// Number of servers to start for the test
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int NumServers {
      get { return numServers_; }
      set {
        numServers_ = value;
      }
    }

    /// <summary>Field number for the "warmup_seconds" field.</summary>
    public const int WarmupSecondsFieldNumber = 6;
    private int warmupSeconds_;
    /// <summary>
    /// Warmup period, in seconds
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int WarmupSeconds {
      get { return warmupSeconds_; }
      set {
        warmupSeconds_ = value;
      }
    }

    /// <summary>Field number for the "benchmark_seconds" field.</summary>
    public const int BenchmarkSecondsFieldNumber = 7;
    private int benchmarkSeconds_;
    /// <summary>
    /// Benchmark time, in seconds
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int BenchmarkSeconds {
      get { return benchmarkSeconds_; }
      set {
        benchmarkSeconds_ = value;
      }
    }

    /// <summary>Field number for the "spawn_local_worker_count" field.</summary>
    public const int SpawnLocalWorkerCountFieldNumber = 8;
    private int spawnLocalWorkerCount_;
    /// <summary>
    /// Number of workers to spawn locally (usually zero)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int SpawnLocalWorkerCount {
      get { return spawnLocalWorkerCount_; }
      set {
        spawnLocalWorkerCount_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as Scenario);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(Scenario other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if (!object.Equals(ClientConfig, other.ClientConfig)) return false;
      if (NumClients != other.NumClients) return false;
      if (!object.Equals(ServerConfig, other.ServerConfig)) return false;
      if (NumServers != other.NumServers) return false;
      if (WarmupSeconds != other.WarmupSeconds) return false;
      if (BenchmarkSeconds != other.BenchmarkSeconds) return false;
      if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (clientConfig_ != null) hash ^= ClientConfig.GetHashCode();
      if (NumClients != 0) hash ^= NumClients.GetHashCode();
      if (serverConfig_ != null) hash ^= ServerConfig.GetHashCode();
      if (NumServers != 0) hash ^= NumServers.GetHashCode();
      if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode();
      if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode();
      if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      if (clientConfig_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(ClientConfig);
      }
      if (NumClients != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(NumClients);
      }
      if (serverConfig_ != null) {
        output.WriteRawTag(34);
        output.WriteMessage(ServerConfig);
      }
      if (NumServers != 0) {
        output.WriteRawTag(40);
        output.WriteInt32(NumServers);
      }
      if (WarmupSeconds != 0) {
        output.WriteRawTag(48);
        output.WriteInt32(WarmupSeconds);
      }
      if (BenchmarkSeconds != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(BenchmarkSeconds);
      }
      if (SpawnLocalWorkerCount != 0) {
        output.WriteRawTag(64);
        output.WriteInt32(SpawnLocalWorkerCount);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (clientConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClientConfig);
      }
      if (NumClients != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumClients);
      }
      if (serverConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ServerConfig);
      }
      if (NumServers != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumServers);
      }
      if (WarmupSeconds != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(WarmupSeconds);
      }
      if (BenchmarkSeconds != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(BenchmarkSeconds);
      }
      if (SpawnLocalWorkerCount != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Scenario other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      if (other.clientConfig_ != null) {
        if (clientConfig_ == null) {
          clientConfig_ = new global::Grpc.Testing.ClientConfig();
        }
        ClientConfig.MergeFrom(other.ClientConfig);
      }
      if (other.NumClients != 0) {
        NumClients = other.NumClients;
      }
      if (other.serverConfig_ != null) {
        if (serverConfig_ == null) {
          serverConfig_ = new global::Grpc.Testing.ServerConfig();
        }
        ServerConfig.MergeFrom(other.ServerConfig);
      }
      if (other.NumServers != 0) {
        NumServers = other.NumServers;
      }
      if (other.WarmupSeconds != 0) {
        WarmupSeconds = other.WarmupSeconds;
      }
      if (other.BenchmarkSeconds != 0) {
        BenchmarkSeconds = other.BenchmarkSeconds;
      }
      if (other.SpawnLocalWorkerCount != 0) {
        SpawnLocalWorkerCount = other.SpawnLocalWorkerCount;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            if (clientConfig_ == null) {
              clientConfig_ = new global::Grpc.Testing.ClientConfig();
            }
            input.ReadMessage(clientConfig_);
            break;
          }
          case 24: {
            NumClients = input.ReadInt32();
            break;
          }
          case 34: {
            if (serverConfig_ == null) {
              serverConfig_ = new global::Grpc.Testing.ServerConfig();
            }
            input.ReadMessage(serverConfig_);
            break;
          }
          case 40: {
            NumServers = input.ReadInt32();
            break;
          }
          case 48: {
            WarmupSeconds = input.ReadInt32();
            break;
          }
          case 56: {
            BenchmarkSeconds = input.ReadInt32();
            break;
          }
          case 64: {
            SpawnLocalWorkerCount = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// A set of scenarios to be run with qps_json_driver
  /// </summary>
  public sealed partial class Scenarios : pb::IMessage<Scenarios> {
    private static readonly pb::MessageParser<Scenarios> _parser = new pb::MessageParser<Scenarios>(() => new Scenarios());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Scenarios> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenarios() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenarios(Scenarios other) : this() {
      scenarios_ = other.scenarios_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenarios Clone() {
      return new Scenarios(this);
    }

    /// <summary>Field number for the "scenarios" field.</summary>
    public const int Scenarios_FieldNumber = 1;
    private static readonly pb::FieldCodec<global::Grpc.Testing.Scenario> _repeated_scenarios_codec
        = pb::FieldCodec.ForMessage(10, global::Grpc.Testing.Scenario.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.Scenario> scenarios_ = new pbc::RepeatedField<global::Grpc.Testing.Scenario>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.Scenario> Scenarios_ {
      get { return scenarios_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as Scenarios);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(Scenarios other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!scenarios_.Equals(other.scenarios_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= scenarios_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      scenarios_.WriteTo(output, _repeated_scenarios_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += scenarios_.CalculateSize(_repeated_scenarios_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Scenarios other) {
      if (other == null) {
        return;
      }
      scenarios_.Add(other.scenarios_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Basic summary that can be computed from ClientStats and ServerStats
  /// once the scenario has finished.
  /// </summary>
  public sealed partial class ScenarioResultSummary : pb::IMessage<ScenarioResultSummary> {
    private static readonly pb::MessageParser<ScenarioResultSummary> _parser = new pb::MessageParser<ScenarioResultSummary>(() => new ScenarioResultSummary());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ScenarioResultSummary> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResultSummary() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResultSummary(ScenarioResultSummary other) : this() {
      qps_ = other.qps_;
      qpsPerServerCore_ = other.qpsPerServerCore_;
      serverSystemTime_ = other.serverSystemTime_;
      serverUserTime_ = other.serverUserTime_;
      clientSystemTime_ = other.clientSystemTime_;
      clientUserTime_ = other.clientUserTime_;
      latency50_ = other.latency50_;
      latency90_ = other.latency90_;
      latency95_ = other.latency95_;
      latency99_ = other.latency99_;
      latency999_ = other.latency999_;
      serverCpuUsage_ = other.serverCpuUsage_;
      successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_;
      failedRequestsPerSecond_ = other.failedRequestsPerSecond_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResultSummary Clone() {
      return new ScenarioResultSummary(this);
    }

    /// <summary>Field number for the "qps" field.</summary>
    public const int QpsFieldNumber = 1;
    private double qps_;
    /// <summary>
    /// Total number of operations per second over all clients.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Qps {
      get { return qps_; }
      set {
        qps_ = value;
      }
    }

    /// <summary>Field number for the "qps_per_server_core" field.</summary>
    public const int QpsPerServerCoreFieldNumber = 2;
    private double qpsPerServerCore_;
    /// <summary>
    /// QPS per one server core.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double QpsPerServerCore {
      get { return qpsPerServerCore_; }
      set {
        qpsPerServerCore_ = value;
      }
    }

    /// <summary>Field number for the "server_system_time" field.</summary>
    public const int ServerSystemTimeFieldNumber = 3;
    private double serverSystemTime_;
    /// <summary>
    /// server load based on system_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerSystemTime {
      get { return serverSystemTime_; }
      set {
        serverSystemTime_ = value;
      }
    }

    /// <summary>Field number for the "server_user_time" field.</summary>
    public const int ServerUserTimeFieldNumber = 4;
    private double serverUserTime_;
    /// <summary>
    /// server load based on user_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerUserTime {
      get { return serverUserTime_; }
      set {
        serverUserTime_ = value;
      }
    }

    /// <summary>Field number for the "client_system_time" field.</summary>
    public const int ClientSystemTimeFieldNumber = 5;
    private double clientSystemTime_;
    /// <summary>
    /// client load based on system_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ClientSystemTime {
      get { return clientSystemTime_; }
      set {
        clientSystemTime_ = value;
      }
    }

    /// <summary>Field number for the "client_user_time" field.</summary>
    public const int ClientUserTimeFieldNumber = 6;
    private double clientUserTime_;
    /// <summary>
    /// client load based on user_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ClientUserTime {
      get { return clientUserTime_; }
      set {
        clientUserTime_ = value;
      }
    }

    /// <summary>Field number for the "latency_50" field.</summary>
    public const int Latency50FieldNumber = 7;
    private double latency50_;
    /// <summary>
    /// X% latency percentiles (in nanoseconds)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency50 {
      get { return latency50_; }
      set {
        latency50_ = value;
      }
    }

    /// <summary>Field number for the "latency_90" field.</summary>
    public const int Latency90FieldNumber = 8;
    private double latency90_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency90 {
      get { return latency90_; }
      set {
        latency90_ = value;
      }
    }

    /// <summary>Field number for the "latency_95" field.</summary>
    public const int Latency95FieldNumber = 9;
    private double latency95_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency95 {
      get { return latency95_; }
      set {
        latency95_ = value;
      }
    }

    /// <summary>Field number for the "latency_99" field.</summary>
    public const int Latency99FieldNumber = 10;
    private double latency99_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency99 {
      get { return latency99_; }
      set {
        latency99_ = value;
      }
    }

    /// <summary>Field number for the "latency_999" field.</summary>
    public const int Latency999FieldNumber = 11;
    private double latency999_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency999 {
      get { return latency999_; }
      set {
        latency999_ = value;
      }
    }

    /// <summary>Field number for the "server_cpu_usage" field.</summary>
    public const int ServerCpuUsageFieldNumber = 12;
    private double serverCpuUsage_;
    /// <summary>
    /// server cpu usage percentage
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerCpuUsage {
      get { return serverCpuUsage_; }
      set {
        serverCpuUsage_ = value;
      }
    }

    /// <summary>Field number for the "successful_requests_per_second" field.</summary>
    public const int SuccessfulRequestsPerSecondFieldNumber = 13;
    private double successfulRequestsPerSecond_;
    /// <summary>
    /// Number of requests that succeeded/failed
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double SuccessfulRequestsPerSecond {
      get { return successfulRequestsPerSecond_; }
      set {
        successfulRequestsPerSecond_ = value;
      }
    }

    /// <summary>Field number for the "failed_requests_per_second" field.</summary>
    public const int FailedRequestsPerSecondFieldNumber = 14;
    private double failedRequestsPerSecond_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double FailedRequestsPerSecond {
      get { return failedRequestsPerSecond_; }
      set {
        failedRequestsPerSecond_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ScenarioResultSummary);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ScenarioResultSummary other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Qps != other.Qps) return false;
      if (QpsPerServerCore != other.QpsPerServerCore) return false;
      if (ServerSystemTime != other.ServerSystemTime) return false;
      if (ServerUserTime != other.ServerUserTime) return false;
      if (ClientSystemTime != other.ClientSystemTime) return false;
      if (ClientUserTime != other.ClientUserTime) return false;
      if (Latency50 != other.Latency50) return false;
      if (Latency90 != other.Latency90) return false;
      if (Latency95 != other.Latency95) return false;
      if (Latency99 != other.Latency99) return false;
      if (Latency999 != other.Latency999) return false;
      if (ServerCpuUsage != other.ServerCpuUsage) return false;
      if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
      if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Qps != 0D) hash ^= Qps.GetHashCode();
      if (QpsPerServerCore != 0D) hash ^= QpsPerServerCore.GetHashCode();
      if (ServerSystemTime != 0D) hash ^= ServerSystemTime.GetHashCode();
      if (ServerUserTime != 0D) hash ^= ServerUserTime.GetHashCode();
      if (ClientSystemTime != 0D) hash ^= ClientSystemTime.GetHashCode();
      if (ClientUserTime != 0D) hash ^= ClientUserTime.GetHashCode();
      if (Latency50 != 0D) hash ^= Latency50.GetHashCode();
      if (Latency90 != 0D) hash ^= Latency90.GetHashCode();
      if (Latency95 != 0D) hash ^= Latency95.GetHashCode();
      if (Latency99 != 0D) hash ^= Latency99.GetHashCode();
      if (Latency999 != 0D) hash ^= Latency999.GetHashCode();
      if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
      if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
      if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Qps != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(Qps);
      }
      if (QpsPerServerCore != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(QpsPerServerCore);
      }
      if (ServerSystemTime != 0D) {
        output.WriteRawTag(25);
        output.WriteDouble(ServerSystemTime);
      }
      if (ServerUserTime != 0D) {
        output.WriteRawTag(33);
        output.WriteDouble(ServerUserTime);
      }
      if (ClientSystemTime != 0D) {
        output.WriteRawTag(41);
        output.WriteDouble(ClientSystemTime);
      }
      if (ClientUserTime != 0D) {
        output.WriteRawTag(49);
        output.WriteDouble(ClientUserTime);
      }
      if (Latency50 != 0D) {
        output.WriteRawTag(57);
        output.WriteDouble(Latency50);
      }
      if (Latency90 != 0D) {
        output.WriteRawTag(65);
        output.WriteDouble(Latency90);
      }
      if (Latency95 != 0D) {
        output.WriteRawTag(73);
        output.WriteDouble(Latency95);
      }
      if (Latency99 != 0D) {
        output.WriteRawTag(81);
        output.WriteDouble(Latency99);
      }
      if (Latency999 != 0D) {
        output.WriteRawTag(89);
        output.WriteDouble(Latency999);
      }
      if (ServerCpuUsage != 0D) {
        output.WriteRawTag(97);
        output.WriteDouble(ServerCpuUsage);
      }
      if (SuccessfulRequestsPerSecond != 0D) {
        output.WriteRawTag(105);
        output.WriteDouble(SuccessfulRequestsPerSecond);
      }
      if (FailedRequestsPerSecond != 0D) {
        output.WriteRawTag(113);
        output.WriteDouble(FailedRequestsPerSecond);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Qps != 0D) {
        size += 1 + 8;
      }
      if (QpsPerServerCore != 0D) {
        size += 1 + 8;
      }
      if (ServerSystemTime != 0D) {
        size += 1 + 8;
      }
      if (ServerUserTime != 0D) {
        size += 1 + 8;
      }
      if (ClientSystemTime != 0D) {
        size += 1 + 8;
      }
      if (ClientUserTime != 0D) {
        size += 1 + 8;
      }
      if (Latency50 != 0D) {
        size += 1 + 8;
      }
      if (Latency90 != 0D) {
        size += 1 + 8;
      }
      if (Latency95 != 0D) {
        size += 1 + 8;
      }
      if (Latency99 != 0D) {
        size += 1 + 8;
      }
      if (Latency999 != 0D) {
        size += 1 + 8;
      }
      if (ServerCpuUsage != 0D) {
        size += 1 + 8;
      }
      if (SuccessfulRequestsPerSecond != 0D) {
        size += 1 + 8;
      }
      if (FailedRequestsPerSecond != 0D) {
        size += 1 + 8;
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ScenarioResultSummary other) {
      if (other == null) {
        return;
      }
      if (other.Qps != 0D) {
        Qps = other.Qps;
      }
      if (other.QpsPerServerCore != 0D) {
        QpsPerServerCore = other.QpsPerServerCore;
      }
      if (other.ServerSystemTime != 0D) {
        ServerSystemTime = other.ServerSystemTime;
      }
      if (other.ServerUserTime != 0D) {
        ServerUserTime = other.ServerUserTime;
      }
      if (other.ClientSystemTime != 0D) {
        ClientSystemTime = other.ClientSystemTime;
      }
      if (other.ClientUserTime != 0D) {
        ClientUserTime = other.ClientUserTime;
      }
      if (other.Latency50 != 0D) {
        Latency50 = other.Latency50;
      }
      if (other.Latency90 != 0D) {
        Latency90 = other.Latency90;
      }
      if (other.Latency95 != 0D) {
        Latency95 = other.Latency95;
      }
      if (other.Latency99 != 0D) {
        Latency99 = other.Latency99;
      }
      if (other.Latency999 != 0D) {
        Latency999 = other.Latency999;
      }
      if (other.ServerCpuUsage != 0D) {
        ServerCpuUsage = other.ServerCpuUsage;
      }
      if (other.SuccessfulRequestsPerSecond != 0D) {
        SuccessfulRequestsPerSecond = other.SuccessfulRequestsPerSecond;
      }
      if (other.FailedRequestsPerSecond != 0D) {
        FailedRequestsPerSecond = other.FailedRequestsPerSecond;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 9: {
            Qps = input.ReadDouble();
            break;
          }
          case 17: {
            QpsPerServerCore = input.ReadDouble();
            break;
          }
          case 25: {
            ServerSystemTime = input.ReadDouble();
            break;
          }
          case 33: {
            ServerUserTime = input.ReadDouble();
            break;
          }
          case 41: {
            ClientSystemTime = input.ReadDouble();
            break;
          }
          case 49: {
            ClientUserTime = input.ReadDouble();
            break;
          }
          case 57: {
            Latency50 = input.ReadDouble();
            break;
          }
          case 65: {
            Latency90 = input.ReadDouble();
            break;
          }
          case 73: {
            Latency95 = input.ReadDouble();
            break;
          }
          case 81: {
            Latency99 = input.ReadDouble();
            break;
          }
          case 89: {
            Latency999 = input.ReadDouble();
            break;
          }
          case 97: {
            ServerCpuUsage = input.ReadDouble();
            break;
          }
          case 105: {
            SuccessfulRequestsPerSecond = input.ReadDouble();
            break;
          }
          case 113: {
            FailedRequestsPerSecond = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Results of a single benchmark scenario.
  /// </summary>
  public sealed partial class ScenarioResult : pb::IMessage<ScenarioResult> {
    private static readonly pb::MessageParser<ScenarioResult> _parser = new pb::MessageParser<ScenarioResult>(() => new ScenarioResult());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ScenarioResult> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[18]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResult() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResult(ScenarioResult other) : this() {
      Scenario = other.scenario_ != null ? other.Scenario.Clone() : null;
      Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
      clientStats_ = other.clientStats_.Clone();
      serverStats_ = other.serverStats_.Clone();
      serverCores_ = other.serverCores_.Clone();
      Summary = other.summary_ != null ? other.Summary.Clone() : null;
      clientSuccess_ = other.clientSuccess_.Clone();
      serverSuccess_ = other.serverSuccess_.Clone();
      requestResults_ = other.requestResults_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResult Clone() {
      return new ScenarioResult(this);
    }

    /// <summary>Field number for the "scenario" field.</summary>
    public const int ScenarioFieldNumber = 1;
    private global::Grpc.Testing.Scenario scenario_;
    /// <summary>
    /// Inputs used to run the scenario.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Scenario Scenario {
      get { return scenario_; }
      set {
        scenario_ = value;
      }
    }

    /// <summary>Field number for the "latencies" field.</summary>
    public const int LatenciesFieldNumber = 2;
    private global::Grpc.Testing.HistogramData latencies_;
    /// <summary>
    /// Histograms from all clients merged into one histogram.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.HistogramData Latencies {
      get { return latencies_; }
      set {
        latencies_ = value;
      }
    }

    /// <summary>Field number for the "client_stats" field.</summary>
    public const int ClientStatsFieldNumber = 3;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ClientStats> _repeated_clientStats_codec
        = pb::FieldCodec.ForMessage(26, global::Grpc.Testing.ClientStats.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ClientStats> clientStats_ = new pbc::RepeatedField<global::Grpc.Testing.ClientStats>();
    /// <summary>
    /// Client stats for each client
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ClientStats> ClientStats {
      get { return clientStats_; }
    }

    /// <summary>Field number for the "server_stats" field.</summary>
    public const int ServerStatsFieldNumber = 4;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ServerStats> _repeated_serverStats_codec
        = pb::FieldCodec.ForMessage(34, global::Grpc.Testing.ServerStats.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ServerStats> serverStats_ = new pbc::RepeatedField<global::Grpc.Testing.ServerStats>();
    /// <summary>
    /// Server stats for each server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ServerStats> ServerStats {
      get { return serverStats_; }
    }

    /// <summary>Field number for the "server_cores" field.</summary>
    public const int ServerCoresFieldNumber = 5;
    private static readonly pb::FieldCodec<int> _repeated_serverCores_codec
        = pb::FieldCodec.ForInt32(42);
    private readonly pbc::RepeatedField<int> serverCores_ = new pbc::RepeatedField<int>();
    /// <summary>
    /// Number of cores available to each server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> ServerCores {
      get { return serverCores_; }
    }

    /// <summary>Field number for the "summary" field.</summary>
    public const int SummaryFieldNumber = 6;
    private global::Grpc.Testing.ScenarioResultSummary summary_;
    /// <summary>
    /// An after-the-fact computed summary
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ScenarioResultSummary Summary {
      get { return summary_; }
      set {
        summary_ = value;
      }
    }

    /// <summary>Field number for the "client_success" field.</summary>
    public const int ClientSuccessFieldNumber = 7;
    private static readonly pb::FieldCodec<bool> _repeated_clientSuccess_codec
        = pb::FieldCodec.ForBool(58);
    private readonly pbc::RepeatedField<bool> clientSuccess_ = new pbc::RepeatedField<bool>();
    /// <summary>
    /// Information on success or failure of each worker
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<bool> ClientSuccess {
      get { return clientSuccess_; }
    }

    /// <summary>Field number for the "server_success" field.</summary>
    public const int ServerSuccessFieldNumber = 8;
    private static readonly pb::FieldCodec<bool> _repeated_serverSuccess_codec
        = pb::FieldCodec.ForBool(66);
    private readonly pbc::RepeatedField<bool> serverSuccess_ = new pbc::RepeatedField<bool>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<bool> ServerSuccess {
      get { return serverSuccess_; }
    }

    /// <summary>Field number for the "request_results" field.</summary>
    public const int RequestResultsFieldNumber = 9;
    private static readonly pb::FieldCodec<global::Grpc.Testing.RequestResultCount> _repeated_requestResults_codec
        = pb::FieldCodec.ForMessage(74, global::Grpc.Testing.RequestResultCount.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> requestResults_ = new pbc::RepeatedField<global::Grpc.Testing.RequestResultCount>();
    /// <summary>
    /// Number of failed requests (one row per status code seen)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> RequestResults {
      get { return requestResults_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ScenarioResult);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ScenarioResult other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Scenario, other.Scenario)) return false;
      if (!object.Equals(Latencies, other.Latencies)) return false;
      if(!clientStats_.Equals(other.clientStats_)) return false;
      if(!serverStats_.Equals(other.serverStats_)) return false;
      if(!serverCores_.Equals(other.serverCores_)) return false;
      if (!object.Equals(Summary, other.Summary)) return false;
      if(!clientSuccess_.Equals(other.clientSuccess_)) return false;
      if(!serverSuccess_.Equals(other.serverSuccess_)) return false;
      if(!requestResults_.Equals(other.requestResults_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (scenario_ != null) hash ^= Scenario.GetHashCode();
      if (latencies_ != null) hash ^= Latencies.GetHashCode();
      hash ^= clientStats_.GetHashCode();
      hash ^= serverStats_.GetHashCode();
      hash ^= serverCores_.GetHashCode();
      if (summary_ != null) hash ^= Summary.GetHashCode();
      hash ^= clientSuccess_.GetHashCode();
      hash ^= serverSuccess_.GetHashCode();
      hash ^= requestResults_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (scenario_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Scenario);
      }
      if (latencies_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Latencies);
      }
      clientStats_.WriteTo(output, _repeated_clientStats_codec);
      serverStats_.WriteTo(output, _repeated_serverStats_codec);
      serverCores_.WriteTo(output, _repeated_serverCores_codec);
      if (summary_ != null) {
        output.WriteRawTag(50);
        output.WriteMessage(Summary);
      }
      clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec);
      serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec);
      requestResults_.WriteTo(output, _repeated_requestResults_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (scenario_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Scenario);
      }
      if (latencies_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
      }
      size += clientStats_.CalculateSize(_repeated_clientStats_codec);
      size += serverStats_.CalculateSize(_repeated_serverStats_codec);
      size += serverCores_.CalculateSize(_repeated_serverCores_codec);
      if (summary_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Summary);
      }
      size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec);
      size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec);
      size += requestResults_.CalculateSize(_repeated_requestResults_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ScenarioResult other) {
      if (other == null) {
        return;
      }
      if (other.scenario_ != null) {
        if (scenario_ == null) {
          scenario_ = new global::Grpc.Testing.Scenario();
        }
        Scenario.MergeFrom(other.Scenario);
      }
      if (other.latencies_ != null) {
        if (latencies_ == null) {
          latencies_ = new global::Grpc.Testing.HistogramData();
        }
        Latencies.MergeFrom(other.Latencies);
      }
      clientStats_.Add(other.clientStats_);
      serverStats_.Add(other.serverStats_);
      serverCores_.Add(other.serverCores_);
      if (other.summary_ != null) {
        if (summary_ == null) {
          summary_ = new global::Grpc.Testing.ScenarioResultSummary();
        }
        Summary.MergeFrom(other.Summary);
      }
      clientSuccess_.Add(other.clientSuccess_);
      serverSuccess_.Add(other.serverSuccess_);
      requestResults_.Add(other.requestResults_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            if (scenario_ == null) {
              scenario_ = new global::Grpc.Testing.Scenario();
            }
            input.ReadMessage(scenario_);
            break;
          }
          case 18: {
            if (latencies_ == null) {
              latencies_ = new global::Grpc.Testing.HistogramData();
            }
            input.ReadMessage(latencies_);
            break;
          }
          case 26: {
            clientStats_.AddEntriesFrom(input, _repeated_clientStats_codec);
            break;
          }
          case 34: {
            serverStats_.AddEntriesFrom(input, _repeated_serverStats_codec);
            break;
          }
          case 42:
          case 40: {
            serverCores_.AddEntriesFrom(input, _repeated_serverCores_codec);
            break;
          }
          case 50: {
            if (summary_ == null) {
              summary_ = new global::Grpc.Testing.ScenarioResultSummary();
            }
            input.ReadMessage(summary_);
            break;
          }
          case 58:
          case 56: {
            clientSuccess_.AddEntriesFrom(input, _repeated_clientSuccess_codec);
            break;
          }
          case 66:
          case 64: {
            serverSuccess_.AddEntriesFrom(input, _repeated_serverSuccess_codec);
            break;
          }
          case 74: {
            requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
