// 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>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  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",
            "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASJBCg1Vbmlmb3JtUGFy",
            "YW1zEhcKD2ludGVyYXJyaXZhbF9sbxgBIAEoARIXCg9pbnRlcmFycml2YWxf",
            "aGkYAiABKAEiKwoTRGV0ZXJtaW5pc3RpY1BhcmFtcxIUCgxvZmZlcmVkX2xv",
            "YWQYASABKAEiOAoMUGFyZXRvUGFyYW1zEhkKEWludGVyYXJyaXZhbF9iYXNl",
            "GAEgASgBEg0KBWFscGhhGAIgASgBIhIKEENsb3NlZExvb3BQYXJhbXMijgIK",
            "CkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5ncnBjLnRlc3Rp",
            "bmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiABKAsyGy5ncnBj",
            "LnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAEi4KB3VuaWZvcm0YAyABKAsyGy5n",
            "cnBjLnRlc3RpbmcuVW5pZm9ybVBhcmFtc0gAEjMKBmRldGVybRgEIAEoCzIh",
            "LmdycGMudGVzdGluZy5EZXRlcm1pbmlzdGljUGFyYW1zSAASLAoGcGFyZXRv",
            "GAUgASgLMhouZ3JwYy50ZXN0aW5nLlBhcmV0b1BhcmFtc0gAQgYKBGxvYWQi",
            "QwoOU2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2Vy",
            "dmVyX2hvc3Rfb3ZlcnJpZGUYAiABKAkirwMKDENsaWVudENvbmZpZxIWCg5z",
            "ZXJ2ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdy",
            "cGMudGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEo",
            "CzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGlu",
            "Z19ycGNzX3Blcl9jaGFubmVsGAQgASgFEhcKD2NsaWVudF9jaGFubmVscxgF",
            "IAEoBRIcChRhc3luY19jbGllbnRfdGhyZWFkcxgHIAEoBRInCghycGNfdHlw",
            "ZRgIIAEoDjIVLmdycGMudGVzdGluZy5ScGNUeXBlEi0KC2xvYWRfcGFyYW1z",
            "GAogASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9j",
            "b25maWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBo",
            "aXN0b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3Jh",
            "bVBhcmFtcyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBj",
            "LnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJo",
            "CgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNs",
            "aWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFy",
            "a0gAQgkKB2FyZ3R5cGUi9wEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlw",
            "ZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5",
            "X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIM",
            "CgRob3N0GAMgASgJEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVyX3Ro",
            "cmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2FkX2Nv",
            "bmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnImgKClNl",
            "cnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2VydmVy",
            "Q29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJrSABC",
            "CQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5n",
            "cnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVjb3Jl",
            "cxgDIAEoBSovCgpDbGllbnRUeXBlEg8KC1NZTkNfQ0xJRU5UEAASEAoMQVNZ",
            "TkNfQ0xJRU5UEAEqLwoKU2VydmVyVHlwZRIPCgtTWU5DX1NFUlZFUhAAEhAK",
            "DEFTWU5DX1NFUlZFUhABKiMKB1JwY1R5cGUSCQoFVU5BUlkQABINCglTVFJF",
            "QU1JTkcQAWIGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
          new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedCodeInfo[] {
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.UniformParams), global::Grpc.Testing.UniformParams.Parser, new[]{ "InterarrivalLo", "InterarrivalHi" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.DeterministicParams), global::Grpc.Testing.DeterministicParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ParetoParams), global::Grpc.Testing.ParetoParams.Parser, new[]{ "InterarrivalBase", "Alpha" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson", "Uniform", "Determ", "Pareto" }, new[]{ "Load" }, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Host", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  public enum ClientType {
    SYNC_CLIENT = 0,
    ASYNC_CLIENT = 1,
  }

  public enum ServerType {
    SYNC_SERVER = 0,
    ASYNC_SERVER = 1,
  }

  public enum RpcType {
    UNARY = 0,
    STREAMING = 1,
  }

  #endregion

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public PoissonParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public PoissonParams(PoissonParams other) : this() {
      offeredLoad_ = other.offeredLoad_;
    }

    public PoissonParams Clone() {
      return new PoissonParams(this);
    }

    /// <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>
    public double OfferedLoad {
      get { return offeredLoad_; }
      set {
        offeredLoad_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as PoissonParams);
    }

    public bool Equals(PoissonParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (OfferedLoad != other.OfferedLoad) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (OfferedLoad != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(OfferedLoad);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (OfferedLoad != 0D) {
        size += 1 + 8;
      }
      return size;
    }

    public void MergeFrom(PoissonParams other) {
      if (other == null) {
        return;
      }
      if (other.OfferedLoad != 0D) {
        OfferedLoad = other.OfferedLoad;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 9: {
            OfferedLoad = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public UniformParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public UniformParams(UniformParams other) : this() {
      interarrivalLo_ = other.interarrivalLo_;
      interarrivalHi_ = other.interarrivalHi_;
    }

    public UniformParams Clone() {
      return new UniformParams(this);
    }

    /// <summary>Field number for the "interarrival_lo" field.</summary>
    public const int InterarrivalLoFieldNumber = 1;
    private double interarrivalLo_;
    public double InterarrivalLo {
      get { return interarrivalLo_; }
      set {
        interarrivalLo_ = value;
      }
    }

    /// <summary>Field number for the "interarrival_hi" field.</summary>
    public const int InterarrivalHiFieldNumber = 2;
    private double interarrivalHi_;
    public double InterarrivalHi {
      get { return interarrivalHi_; }
      set {
        interarrivalHi_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as UniformParams);
    }

    public bool Equals(UniformParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (InterarrivalLo != other.InterarrivalLo) return false;
      if (InterarrivalHi != other.InterarrivalHi) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (InterarrivalLo != 0D) hash ^= InterarrivalLo.GetHashCode();
      if (InterarrivalHi != 0D) hash ^= InterarrivalHi.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (InterarrivalLo != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(InterarrivalLo);
      }
      if (InterarrivalHi != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(InterarrivalHi);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (InterarrivalLo != 0D) {
        size += 1 + 8;
      }
      if (InterarrivalHi != 0D) {
        size += 1 + 8;
      }
      return size;
    }

    public void MergeFrom(UniformParams other) {
      if (other == null) {
        return;
      }
      if (other.InterarrivalLo != 0D) {
        InterarrivalLo = other.InterarrivalLo;
      }
      if (other.InterarrivalHi != 0D) {
        InterarrivalHi = other.InterarrivalHi;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 9: {
            InterarrivalLo = input.ReadDouble();
            break;
          }
          case 17: {
            InterarrivalHi = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public DeterministicParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DeterministicParams(DeterministicParams other) : this() {
      offeredLoad_ = other.offeredLoad_;
    }

    public DeterministicParams Clone() {
      return new DeterministicParams(this);
    }

    /// <summary>Field number for the "offered_load" field.</summary>
    public const int OfferedLoadFieldNumber = 1;
    private double offeredLoad_;
    public double OfferedLoad {
      get { return offeredLoad_; }
      set {
        offeredLoad_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as DeterministicParams);
    }

    public bool Equals(DeterministicParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (OfferedLoad != other.OfferedLoad) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (OfferedLoad != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(OfferedLoad);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (OfferedLoad != 0D) {
        size += 1 + 8;
      }
      return size;
    }

    public void MergeFrom(DeterministicParams other) {
      if (other == null) {
        return;
      }
      if (other.OfferedLoad != 0D) {
        OfferedLoad = other.OfferedLoad;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 9: {
            OfferedLoad = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ParetoParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ParetoParams(ParetoParams other) : this() {
      interarrivalBase_ = other.interarrivalBase_;
      alpha_ = other.alpha_;
    }

    public ParetoParams Clone() {
      return new ParetoParams(this);
    }

    /// <summary>Field number for the "interarrival_base" field.</summary>
    public const int InterarrivalBaseFieldNumber = 1;
    private double interarrivalBase_;
    public double InterarrivalBase {
      get { return interarrivalBase_; }
      set {
        interarrivalBase_ = value;
      }
    }

    /// <summary>Field number for the "alpha" field.</summary>
    public const int AlphaFieldNumber = 2;
    private double alpha_;
    public double Alpha {
      get { return alpha_; }
      set {
        alpha_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as ParetoParams);
    }

    public bool Equals(ParetoParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (InterarrivalBase != other.InterarrivalBase) return false;
      if (Alpha != other.Alpha) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (InterarrivalBase != 0D) hash ^= InterarrivalBase.GetHashCode();
      if (Alpha != 0D) hash ^= Alpha.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (InterarrivalBase != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(InterarrivalBase);
      }
      if (Alpha != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(Alpha);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (InterarrivalBase != 0D) {
        size += 1 + 8;
      }
      if (Alpha != 0D) {
        size += 1 + 8;
      }
      return size;
    }

    public void MergeFrom(ParetoParams other) {
      if (other == null) {
        return;
      }
      if (other.InterarrivalBase != 0D) {
        InterarrivalBase = other.InterarrivalBase;
      }
      if (other.Alpha != 0D) {
        Alpha = other.Alpha;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 9: {
            InterarrivalBase = input.ReadDouble();
            break;
          }
          case 17: {
            Alpha = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ClosedLoopParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ClosedLoopParams(ClosedLoopParams other) : this() {
    }

    public ClosedLoopParams Clone() {
      return new ClosedLoopParams(this);
    }

    public override bool Equals(object other) {
      return Equals(other as ClosedLoopParams);
    }

    public bool Equals(ClosedLoopParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
    }

    public int CalculateSize() {
      int size = 0;
      return size;
    }

    public void MergeFrom(ClosedLoopParams other) {
      if (other == null) {
        return;
      }
    }

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

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public LoadParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public LoadParams(LoadParams other) : this() {
      switch (other.LoadCase) {
        case LoadOneofCase.ClosedLoop:
          ClosedLoop = other.ClosedLoop.Clone();
          break;
        case LoadOneofCase.Poisson:
          Poisson = other.Poisson.Clone();
          break;
        case LoadOneofCase.Uniform:
          Uniform = other.Uniform.Clone();
          break;
        case LoadOneofCase.Determ:
          Determ = other.Determ.Clone();
          break;
        case LoadOneofCase.Pareto:
          Pareto = other.Pareto.Clone();
          break;
      }

    }

    public LoadParams Clone() {
      return new LoadParams(this);
    }

    /// <summary>Field number for the "closed_loop" field.</summary>
    public const int ClosedLoopFieldNumber = 1;
    public global::Grpc.Testing.ClosedLoopParams ClosedLoop {
      get { return loadCase_ == LoadOneofCase.ClosedLoop ? (global::Grpc.Testing.ClosedLoopParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.ClosedLoop;
      }
    }

    /// <summary>Field number for the "poisson" field.</summary>
    public const int PoissonFieldNumber = 2;
    public global::Grpc.Testing.PoissonParams Poisson {
      get { return loadCase_ == LoadOneofCase.Poisson ? (global::Grpc.Testing.PoissonParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Poisson;
      }
    }

    /// <summary>Field number for the "uniform" field.</summary>
    public const int UniformFieldNumber = 3;
    public global::Grpc.Testing.UniformParams Uniform {
      get { return loadCase_ == LoadOneofCase.Uniform ? (global::Grpc.Testing.UniformParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Uniform;
      }
    }

    /// <summary>Field number for the "determ" field.</summary>
    public const int DetermFieldNumber = 4;
    public global::Grpc.Testing.DeterministicParams Determ {
      get { return loadCase_ == LoadOneofCase.Determ ? (global::Grpc.Testing.DeterministicParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Determ;
      }
    }

    /// <summary>Field number for the "pareto" field.</summary>
    public const int ParetoFieldNumber = 5;
    public global::Grpc.Testing.ParetoParams Pareto {
      get { return loadCase_ == LoadOneofCase.Pareto ? (global::Grpc.Testing.ParetoParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Pareto;
      }
    }

    private object load_;
    /// <summary>Enum of possible cases for the "load" oneof.</summary>
    public enum LoadOneofCase {
      None = 0,
      ClosedLoop = 1,
      Poisson = 2,
      Uniform = 3,
      Determ = 4,
      Pareto = 5,
    }
    private LoadOneofCase loadCase_ = LoadOneofCase.None;
    public LoadOneofCase LoadCase {
      get { return loadCase_; }
    }

    public void ClearLoad() {
      loadCase_ = LoadOneofCase.None;
      load_ = null;
    }

    public override bool Equals(object other) {
      return Equals(other as LoadParams);
    }

    public bool Equals(LoadParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
      if (!object.Equals(Poisson, other.Poisson)) return false;
      if (!object.Equals(Uniform, other.Uniform)) return false;
      if (!object.Equals(Determ, other.Determ)) return false;
      if (!object.Equals(Pareto, other.Pareto)) return false;
      if (LoadCase != other.LoadCase) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
      if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
      if (loadCase_ == LoadOneofCase.Uniform) hash ^= Uniform.GetHashCode();
      if (loadCase_ == LoadOneofCase.Determ) hash ^= Determ.GetHashCode();
      if (loadCase_ == LoadOneofCase.Pareto) hash ^= Pareto.GetHashCode();
      hash ^= (int) loadCase_;
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (loadCase_ == LoadOneofCase.ClosedLoop) {
        output.WriteRawTag(10);
        output.WriteMessage(ClosedLoop);
      }
      if (loadCase_ == LoadOneofCase.Poisson) {
        output.WriteRawTag(18);
        output.WriteMessage(Poisson);
      }
      if (loadCase_ == LoadOneofCase.Uniform) {
        output.WriteRawTag(26);
        output.WriteMessage(Uniform);
      }
      if (loadCase_ == LoadOneofCase.Determ) {
        output.WriteRawTag(34);
        output.WriteMessage(Determ);
      }
      if (loadCase_ == LoadOneofCase.Pareto) {
        output.WriteRawTag(42);
        output.WriteMessage(Pareto);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (loadCase_ == LoadOneofCase.ClosedLoop) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClosedLoop);
      }
      if (loadCase_ == LoadOneofCase.Poisson) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
      }
      if (loadCase_ == LoadOneofCase.Uniform) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Uniform);
      }
      if (loadCase_ == LoadOneofCase.Determ) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Determ);
      }
      if (loadCase_ == LoadOneofCase.Pareto) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Pareto);
      }
      return size;
    }

    public void MergeFrom(LoadParams other) {
      if (other == null) {
        return;
      }
      switch (other.LoadCase) {
        case LoadOneofCase.ClosedLoop:
          ClosedLoop = other.ClosedLoop;
          break;
        case LoadOneofCase.Poisson:
          Poisson = other.Poisson;
          break;
        case LoadOneofCase.Uniform:
          Uniform = other.Uniform;
          break;
        case LoadOneofCase.Determ:
          Determ = other.Determ;
          break;
        case LoadOneofCase.Pareto:
          Pareto = other.Pareto;
          break;
      }

    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams();
            if (loadCase_ == LoadOneofCase.ClosedLoop) {
              subBuilder.MergeFrom(ClosedLoop);
            }
            input.ReadMessage(subBuilder);
            ClosedLoop = subBuilder;
            break;
          }
          case 18: {
            global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams();
            if (loadCase_ == LoadOneofCase.Poisson) {
              subBuilder.MergeFrom(Poisson);
            }
            input.ReadMessage(subBuilder);
            Poisson = subBuilder;
            break;
          }
          case 26: {
            global::Grpc.Testing.UniformParams subBuilder = new global::Grpc.Testing.UniformParams();
            if (loadCase_ == LoadOneofCase.Uniform) {
              subBuilder.MergeFrom(Uniform);
            }
            input.ReadMessage(subBuilder);
            Uniform = subBuilder;
            break;
          }
          case 34: {
            global::Grpc.Testing.DeterministicParams subBuilder = new global::Grpc.Testing.DeterministicParams();
            if (loadCase_ == LoadOneofCase.Determ) {
              subBuilder.MergeFrom(Determ);
            }
            input.ReadMessage(subBuilder);
            Determ = subBuilder;
            break;
          }
          case 42: {
            global::Grpc.Testing.ParetoParams subBuilder = new global::Grpc.Testing.ParetoParams();
            if (loadCase_ == LoadOneofCase.Pareto) {
              subBuilder.MergeFrom(Pareto);
            }
            input.ReadMessage(subBuilder);
            Pareto = subBuilder;
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public SecurityParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    public SecurityParams(SecurityParams other) : this() {
      useTestCa_ = other.useTestCa_;
      serverHostOverride_ = other.serverHostOverride_;
    }

    public SecurityParams Clone() {
      return new SecurityParams(this);
    }

    /// <summary>Field number for the "use_test_ca" field.</summary>
    public const int UseTestCaFieldNumber = 1;
    private bool useTestCa_;
    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_ = "";
    public string ServerHostOverride {
      get { return serverHostOverride_; }
      set {
        serverHostOverride_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    public override bool Equals(object other) {
      return Equals(other as SecurityParams);
    }

    public bool Equals(SecurityParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (UseTestCa != other.UseTestCa) return false;
      if (ServerHostOverride != other.ServerHostOverride) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (UseTestCa != false) hash ^= UseTestCa.GetHashCode();
      if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (UseTestCa != false) {
        output.WriteRawTag(8);
        output.WriteBool(UseTestCa);
      }
      if (ServerHostOverride.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(ServerHostOverride);
      }
    }

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

    public void MergeFrom(SecurityParams other) {
      if (other == null) {
        return;
      }
      if (other.UseTestCa != false) {
        UseTestCa = other.UseTestCa;
      }
      if (other.ServerHostOverride.Length != 0) {
        ServerHostOverride = other.ServerHostOverride;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            UseTestCa = input.ReadBool();
            break;
          }
          case 18: {
            ServerHostOverride = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ClientConfig() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ClientConfig(ClientConfig other) : this() {
      serverTargets_ = other.serverTargets_.Clone();
      clientType_ = other.clientType_;
      SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
      outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_;
      clientChannels_ = other.clientChannels_;
      asyncClientThreads_ = other.asyncClientThreads_;
      rpcType_ = other.rpcType_;
      LoadParams = other.loadParams_ != null ? other.LoadParams.Clone() : null;
      PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
      HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
    }

    public ClientConfig Clone() {
      return new ClientConfig(this);
    }

    /// <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>
    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_ = global::Grpc.Testing.ClientType.SYNC_CLIENT;
    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_;
    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>
    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>
    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>
    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_ = global::Grpc.Testing.RpcType.UNARY;
    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>
    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_;
    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_;
    public global::Grpc.Testing.HistogramParams HistogramParams {
      get { return histogramParams_; }
      set {
        histogramParams_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as ClientConfig);
    }

    public bool Equals(ClientConfig other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!serverTargets_.Equals(other.serverTargets_)) return false;
      if (ClientType != other.ClientType) return false;
      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
      if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false;
      if (ClientChannels != other.ClientChannels) return false;
      if (AsyncClientThreads != other.AsyncClientThreads) return false;
      if (RpcType != other.RpcType) return false;
      if (!object.Equals(LoadParams, other.LoadParams)) return false;
      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
      if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      hash ^= serverTargets_.GetHashCode();
      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) hash ^= ClientType.GetHashCode();
      if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
      if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode();
      if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode();
      if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode();
      if (RpcType != global::Grpc.Testing.RpcType.UNARY) hash ^= RpcType.GetHashCode();
      if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
      if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      serverTargets_.WriteTo(output, _repeated_serverTargets_codec);
      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
        output.WriteRawTag(16);
        output.WriteEnum((int) ClientType);
      }
      if (securityParams_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(SecurityParams);
      }
      if (OutstandingRpcsPerChannel != 0) {
        output.WriteRawTag(32);
        output.WriteInt32(OutstandingRpcsPerChannel);
      }
      if (ClientChannels != 0) {
        output.WriteRawTag(40);
        output.WriteInt32(ClientChannels);
      }
      if (AsyncClientThreads != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(AsyncClientThreads);
      }
      if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
        output.WriteRawTag(64);
        output.WriteEnum((int) RpcType);
      }
      if (loadParams_ != null) {
        output.WriteRawTag(82);
        output.WriteMessage(LoadParams);
      }
      if (payloadConfig_ != null) {
        output.WriteRawTag(90);
        output.WriteMessage(PayloadConfig);
      }
      if (histogramParams_ != null) {
        output.WriteRawTag(98);
        output.WriteMessage(HistogramParams);
      }
    }

    public int CalculateSize() {
      int size = 0;
      size += serverTargets_.CalculateSize(_repeated_serverTargets_codec);
      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType);
      }
      if (securityParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
      }
      if (OutstandingRpcsPerChannel != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OutstandingRpcsPerChannel);
      }
      if (ClientChannels != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientChannels);
      }
      if (AsyncClientThreads != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads);
      }
      if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType);
      }
      if (loadParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(LoadParams);
      }
      if (payloadConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
      }
      if (histogramParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams);
      }
      return size;
    }

    public void MergeFrom(ClientConfig other) {
      if (other == null) {
        return;
      }
      serverTargets_.Add(other.serverTargets_);
      if (other.ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
        ClientType = other.ClientType;
      }
      if (other.securityParams_ != null) {
        if (securityParams_ == null) {
          securityParams_ = new global::Grpc.Testing.SecurityParams();
        }
        SecurityParams.MergeFrom(other.SecurityParams);
      }
      if (other.OutstandingRpcsPerChannel != 0) {
        OutstandingRpcsPerChannel = other.OutstandingRpcsPerChannel;
      }
      if (other.ClientChannels != 0) {
        ClientChannels = other.ClientChannels;
      }
      if (other.AsyncClientThreads != 0) {
        AsyncClientThreads = other.AsyncClientThreads;
      }
      if (other.RpcType != global::Grpc.Testing.RpcType.UNARY) {
        RpcType = other.RpcType;
      }
      if (other.loadParams_ != null) {
        if (loadParams_ == null) {
          loadParams_ = new global::Grpc.Testing.LoadParams();
        }
        LoadParams.MergeFrom(other.LoadParams);
      }
      if (other.payloadConfig_ != null) {
        if (payloadConfig_ == null) {
          payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
        }
        PayloadConfig.MergeFrom(other.PayloadConfig);
      }
      if (other.histogramParams_ != null) {
        if (histogramParams_ == null) {
          histogramParams_ = new global::Grpc.Testing.HistogramParams();
        }
        HistogramParams.MergeFrom(other.HistogramParams);
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec);
            break;
          }
          case 16: {
            clientType_ = (global::Grpc.Testing.ClientType) input.ReadEnum();
            break;
          }
          case 26: {
            if (securityParams_ == null) {
              securityParams_ = new global::Grpc.Testing.SecurityParams();
            }
            input.ReadMessage(securityParams_);
            break;
          }
          case 32: {
            OutstandingRpcsPerChannel = input.ReadInt32();
            break;
          }
          case 40: {
            ClientChannels = input.ReadInt32();
            break;
          }
          case 56: {
            AsyncClientThreads = input.ReadInt32();
            break;
          }
          case 64: {
            rpcType_ = (global::Grpc.Testing.RpcType) input.ReadEnum();
            break;
          }
          case 82: {
            if (loadParams_ == null) {
              loadParams_ = new global::Grpc.Testing.LoadParams();
            }
            input.ReadMessage(loadParams_);
            break;
          }
          case 90: {
            if (payloadConfig_ == null) {
              payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
            }
            input.ReadMessage(payloadConfig_);
            break;
          }
          case 98: {
            if (histogramParams_ == null) {
              histogramParams_ = new global::Grpc.Testing.HistogramParams();
            }
            input.ReadMessage(histogramParams_);
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ClientStatus() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ClientStatus(ClientStatus other) : this() {
      Stats = other.stats_ != null ? other.Stats.Clone() : null;
    }

    public ClientStatus Clone() {
      return new ClientStatus(this);
    }

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

    public override bool Equals(object other) {
      return Equals(other as ClientStatus);
    }

    public bool Equals(ClientStatus other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Stats, other.Stats)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (stats_ != null) hash ^= Stats.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (stats_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Stats);
      }
    }

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

    public void MergeFrom(ClientStatus other) {
      if (other == null) {
        return;
      }
      if (other.stats_ != null) {
        if (stats_ == null) {
          stats_ = new global::Grpc.Testing.ClientStats();
        }
        Stats.MergeFrom(other.Stats);
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            if (stats_ == null) {
              stats_ = new global::Grpc.Testing.ClientStats();
            }
            input.ReadMessage(stats_);
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public Mark() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Mark(Mark other) : this() {
      reset_ = other.reset_;
    }

    public Mark Clone() {
      return new Mark(this);
    }

    /// <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>
    public bool Reset {
      get { return reset_; }
      set {
        reset_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as Mark);
    }

    public bool Equals(Mark other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Reset != other.Reset) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Reset != false) hash ^= Reset.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Reset != false) {
        output.WriteRawTag(8);
        output.WriteBool(Reset);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Reset != false) {
        size += 1 + 1;
      }
      return size;
    }

    public void MergeFrom(Mark other) {
      if (other == null) {
        return;
      }
      if (other.Reset != false) {
        Reset = other.Reset;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            Reset = input.ReadBool();
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ClientArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ClientArgs(ClientArgs other) : this() {
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup.Clone();
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark.Clone();
          break;
      }

    }

    public ClientArgs Clone() {
      return new ClientArgs(this);
    }

    /// <summary>Field number for the "setup" field.</summary>
    public const int SetupFieldNumber = 1;
    public global::Grpc.Testing.ClientConfig Setup {
      get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ClientConfig) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
      }
    }

    /// <summary>Field number for the "mark" field.</summary>
    public const int MarkFieldNumber = 2;
    public global::Grpc.Testing.Mark Mark {
      get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
      }
    }

    private object argtype_;
    /// <summary>Enum of possible cases for the "argtype" oneof.</summary>
    public enum ArgtypeOneofCase {
      None = 0,
      Setup = 1,
      Mark = 2,
    }
    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
    public ArgtypeOneofCase ArgtypeCase {
      get { return argtypeCase_; }
    }

    public void ClearArgtype() {
      argtypeCase_ = ArgtypeOneofCase.None;
      argtype_ = null;
    }

    public override bool Equals(object other) {
      return Equals(other as ClientArgs);
    }

    public bool Equals(ClientArgs other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Setup, other.Setup)) return false;
      if (!object.Equals(Mark, other.Mark)) return false;
      if (ArgtypeCase != other.ArgtypeCase) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
      hash ^= (int) argtypeCase_;
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
        output.WriteRawTag(10);
        output.WriteMessage(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        output.WriteRawTag(18);
        output.WriteMessage(Mark);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
      }
      return size;
    }

    public void MergeFrom(ClientArgs other) {
      if (other == null) {
        return;
      }
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup;
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark;
          break;
      }

    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig();
            if (argtypeCase_ == ArgtypeOneofCase.Setup) {
              subBuilder.MergeFrom(Setup);
            }
            input.ReadMessage(subBuilder);
            Setup = subBuilder;
            break;
          }
          case 18: {
            global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
            if (argtypeCase_ == ArgtypeOneofCase.Mark) {
              subBuilder.MergeFrom(Mark);
            }
            input.ReadMessage(subBuilder);
            Mark = subBuilder;
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ServerConfig() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ServerConfig(ServerConfig other) : this() {
      serverType_ = other.serverType_;
      SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
      host_ = other.host_;
      port_ = other.port_;
      asyncServerThreads_ = other.asyncServerThreads_;
      coreLimit_ = other.coreLimit_;
      PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
    }

    public ServerConfig Clone() {
      return new ServerConfig(this);
    }

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

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

    /// <summary>Field number for the "host" field.</summary>
    public const int HostFieldNumber = 3;
    private string host_ = "";
    /// <summary>
    ///  Host on which to listen.
    /// </summary>
    public string Host {
      get { return host_; }
      set {
        host_ = pb::Preconditions.CheckNotNull(value, "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>
    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>
    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>
    ///  restrict core usage, currently unused
    /// </summary>
    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_;
    public global::Grpc.Testing.PayloadConfig PayloadConfig {
      get { return payloadConfig_; }
      set {
        payloadConfig_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as ServerConfig);
    }

    public bool Equals(ServerConfig other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ServerType != other.ServerType) return false;
      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
      if (Host != other.Host) return false;
      if (Port != other.Port) return false;
      if (AsyncServerThreads != other.AsyncServerThreads) return false;
      if (CoreLimit != other.CoreLimit) return false;
      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) hash ^= ServerType.GetHashCode();
      if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
      if (Host.Length != 0) hash ^= Host.GetHashCode();
      if (Port != 0) hash ^= Port.GetHashCode();
      if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode();
      if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
        output.WriteRawTag(8);
        output.WriteEnum((int) ServerType);
      }
      if (securityParams_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(SecurityParams);
      }
      if (Host.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(Host);
      }
      if (Port != 0) {
        output.WriteRawTag(32);
        output.WriteInt32(Port);
      }
      if (AsyncServerThreads != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(AsyncServerThreads);
      }
      if (CoreLimit != 0) {
        output.WriteRawTag(64);
        output.WriteInt32(CoreLimit);
      }
      if (payloadConfig_ != null) {
        output.WriteRawTag(74);
        output.WriteMessage(PayloadConfig);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType);
      }
      if (securityParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
      }
      if (Host.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
      }
      if (Port != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
      }
      if (AsyncServerThreads != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncServerThreads);
      }
      if (CoreLimit != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
      }
      if (payloadConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
      }
      return size;
    }

    public void MergeFrom(ServerConfig other) {
      if (other == null) {
        return;
      }
      if (other.ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
        ServerType = other.ServerType;
      }
      if (other.securityParams_ != null) {
        if (securityParams_ == null) {
          securityParams_ = new global::Grpc.Testing.SecurityParams();
        }
        SecurityParams.MergeFrom(other.SecurityParams);
      }
      if (other.Host.Length != 0) {
        Host = other.Host;
      }
      if (other.Port != 0) {
        Port = other.Port;
      }
      if (other.AsyncServerThreads != 0) {
        AsyncServerThreads = other.AsyncServerThreads;
      }
      if (other.CoreLimit != 0) {
        CoreLimit = other.CoreLimit;
      }
      if (other.payloadConfig_ != null) {
        if (payloadConfig_ == null) {
          payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
        }
        PayloadConfig.MergeFrom(other.PayloadConfig);
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum();
            break;
          }
          case 18: {
            if (securityParams_ == null) {
              securityParams_ = new global::Grpc.Testing.SecurityParams();
            }
            input.ReadMessage(securityParams_);
            break;
          }
          case 26: {
            Host = input.ReadString();
            break;
          }
          case 32: {
            Port = input.ReadInt32();
            break;
          }
          case 56: {
            AsyncServerThreads = input.ReadInt32();
            break;
          }
          case 64: {
            CoreLimit = input.ReadInt32();
            break;
          }
          case 74: {
            if (payloadConfig_ == null) {
              payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
            }
            input.ReadMessage(payloadConfig_);
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ServerArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ServerArgs(ServerArgs other) : this() {
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup.Clone();
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark.Clone();
          break;
      }

    }

    public ServerArgs Clone() {
      return new ServerArgs(this);
    }

    /// <summary>Field number for the "setup" field.</summary>
    public const int SetupFieldNumber = 1;
    public global::Grpc.Testing.ServerConfig Setup {
      get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ServerConfig) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
      }
    }

    /// <summary>Field number for the "mark" field.</summary>
    public const int MarkFieldNumber = 2;
    public global::Grpc.Testing.Mark Mark {
      get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
      }
    }

    private object argtype_;
    /// <summary>Enum of possible cases for the "argtype" oneof.</summary>
    public enum ArgtypeOneofCase {
      None = 0,
      Setup = 1,
      Mark = 2,
    }
    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
    public ArgtypeOneofCase ArgtypeCase {
      get { return argtypeCase_; }
    }

    public void ClearArgtype() {
      argtypeCase_ = ArgtypeOneofCase.None;
      argtype_ = null;
    }

    public override bool Equals(object other) {
      return Equals(other as ServerArgs);
    }

    public bool Equals(ServerArgs other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Setup, other.Setup)) return false;
      if (!object.Equals(Mark, other.Mark)) return false;
      if (ArgtypeCase != other.ArgtypeCase) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
      hash ^= (int) argtypeCase_;
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
        output.WriteRawTag(10);
        output.WriteMessage(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        output.WriteRawTag(18);
        output.WriteMessage(Mark);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
      }
      return size;
    }

    public void MergeFrom(ServerArgs other) {
      if (other == null) {
        return;
      }
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup;
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark;
          break;
      }

    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig();
            if (argtypeCase_ == ArgtypeOneofCase.Setup) {
              subBuilder.MergeFrom(Setup);
            }
            input.ReadMessage(subBuilder);
            Setup = subBuilder;
            break;
          }
          case 18: {
            global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
            if (argtypeCase_ == ArgtypeOneofCase.Mark) {
              subBuilder.MergeFrom(Mark);
            }
            input.ReadMessage(subBuilder);
            Mark = subBuilder;
            break;
          }
        }
      }
    }

  }

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

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

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ServerStatus() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ServerStatus(ServerStatus other) : this() {
      Stats = other.stats_ != null ? other.Stats.Clone() : null;
      port_ = other.port_;
      cores_ = other.cores_;
    }

    public ServerStatus Clone() {
      return new ServerStatus(this);
    }

    /// <summary>Field number for the "stats" field.</summary>
    public const int StatsFieldNumber = 1;
    private global::Grpc.Testing.ServerStats stats_;
    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>
    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 on the server. See gpr_cpu_num_cores.
    /// </summary>
    public int Cores {
      get { return cores_; }
      set {
        cores_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as ServerStatus);
    }

    public bool Equals(ServerStatus other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Stats, other.Stats)) return false;
      if (Port != other.Port) return false;
      if (Cores != other.Cores) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (stats_ != null) hash ^= Stats.GetHashCode();
      if (Port != 0) hash ^= Port.GetHashCode();
      if (Cores != 0) hash ^= Cores.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (stats_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Stats);
      }
      if (Port != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(Port);
      }
      if (Cores != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(Cores);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (stats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
      }
      if (Port != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
      }
      if (Cores != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
      }
      return size;
    }

    public void MergeFrom(ServerStatus other) {
      if (other == null) {
        return;
      }
      if (other.stats_ != null) {
        if (stats_ == null) {
          stats_ = new global::Grpc.Testing.ServerStats();
        }
        Stats.MergeFrom(other.Stats);
      }
      if (other.Port != 0) {
        Port = other.Port;
      }
      if (other.Cores != 0) {
        Cores = other.Cores;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            if (stats_ == null) {
              stats_ = new global::Grpc.Testing.ServerStats();
            }
            input.ReadMessage(stats_);
            break;
          }
          case 16: {
            Port = input.ReadInt32();
            break;
          }
          case 24: {
            Cores = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
