// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: src/proto/grpc/testing/echo_messages.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/echo_messages.proto</summary>
  public static partial class EchoMessagesReflection {

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

    static EchoMessagesReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CipzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VjaG9fbWVzc2FnZXMucHJvdG8S",
            "DGdycGMudGVzdGluZyIyCglEZWJ1Z0luZm8SFQoNc3RhY2tfZW50cmllcxgB",
            "IAMoCRIOCgZkZXRhaWwYAiABKAkiUAoLRXJyb3JTdGF0dXMSDAoEY29kZRgB",
            "IAEoBRIVCg1lcnJvcl9tZXNzYWdlGAIgASgJEhwKFGJpbmFyeV9lcnJvcl9k",
            "ZXRhaWxzGAMgASgJIskDCg1SZXF1ZXN0UGFyYW1zEhUKDWVjaG9fZGVhZGxp",
            "bmUYASABKAgSHgoWY2xpZW50X2NhbmNlbF9hZnRlcl91cxgCIAEoBRIeChZz",
            "ZXJ2ZXJfY2FuY2VsX2FmdGVyX3VzGAMgASgFEhUKDWVjaG9fbWV0YWRhdGEY",
            "BCABKAgSGgoSY2hlY2tfYXV0aF9jb250ZXh0GAUgASgIEh8KF3Jlc3BvbnNl",
            "X21lc3NhZ2VfbGVuZ3RoGAYgASgFEhEKCWVjaG9fcGVlchgHIAEoCBIgChhl",
            "eHBlY3RlZF9jbGllbnRfaWRlbnRpdHkYCCABKAkSHAoUc2tpcF9jYW5jZWxs",
            "ZWRfY2hlY2sYCSABKAgSKAogZXhwZWN0ZWRfdHJhbnNwb3J0X3NlY3VyaXR5",
            "X3R5cGUYCiABKAkSKwoKZGVidWdfaW5mbxgLIAEoCzIXLmdycGMudGVzdGlu",
            "Zy5EZWJ1Z0luZm8SEgoKc2VydmVyX2RpZRgMIAEoCBIcChRiaW5hcnlfZXJy",
            "b3JfZGV0YWlscxgNIAEoCRIxCg5leHBlY3RlZF9lcnJvchgOIAEoCzIZLmdy",
            "cGMudGVzdGluZy5FcnJvclN0YXR1cyJKCgtFY2hvUmVxdWVzdBIPCgdtZXNz",
            "YWdlGAEgASgJEioKBXBhcmFtGAIgASgLMhsuZ3JwYy50ZXN0aW5nLlJlcXVl",
            "c3RQYXJhbXMiRgoOUmVzcG9uc2VQYXJhbXMSGAoQcmVxdWVzdF9kZWFkbGlu",
            "ZRgBIAEoAxIMCgRob3N0GAIgASgJEgwKBHBlZXIYAyABKAkiTAoMRWNob1Jl",
            "c3BvbnNlEg8KB21lc3NhZ2UYASABKAkSKwoFcGFyYW0YAiABKAsyHC5ncnBj",
            "LnRlc3RpbmcuUmVzcG9uc2VQYXJhbXNiBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.DebugInfo), global::Grpc.Testing.DebugInfo.Parser, new[]{ "StackEntries", "Detail" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ErrorStatus), global::Grpc.Testing.ErrorStatus.Parser, new[]{ "Code", "ErrorMessage", "BinaryErrorDetails" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestParams), global::Grpc.Testing.RequestParams.Parser, new[]{ "EchoDeadline", "ClientCancelAfterUs", "ServerCancelAfterUs", "EchoMetadata", "CheckAuthContext", "ResponseMessageLength", "EchoPeer", "ExpectedClientIdentity", "SkipCancelledCheck", "ExpectedTransportSecurityType", "DebugInfo", "ServerDie", "BinaryErrorDetails", "ExpectedError" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoRequest), global::Grpc.Testing.EchoRequest.Parser, new[]{ "Message", "Param" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParams), global::Grpc.Testing.ResponseParams.Parser, new[]{ "RequestDeadline", "Host", "Peer" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoResponse), global::Grpc.Testing.EchoResponse.Parser, new[]{ "Message", "Param" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Messages
  /// <summary>
  /// Message to be echoed back serialized in trailer.
  /// </summary>
  public sealed partial class DebugInfo : pb::IMessage<DebugInfo> {
    private static readonly pb::MessageParser<DebugInfo> _parser = new pb::MessageParser<DebugInfo>(() => new DebugInfo());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<DebugInfo> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DebugInfo(DebugInfo other) : this() {
      stackEntries_ = other.stackEntries_.Clone();
      detail_ = other.detail_;
    }

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

    /// <summary>Field number for the "stack_entries" field.</summary>
    public const int StackEntriesFieldNumber = 1;
    private static readonly pb::FieldCodec<string> _repeated_stackEntries_codec
        = pb::FieldCodec.ForString(10);
    private readonly pbc::RepeatedField<string> stackEntries_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> StackEntries {
      get { return stackEntries_; }
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= stackEntries_.GetHashCode();
      if (Detail.Length != 0) hash ^= Detail.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) {
      stackEntries_.WriteTo(output, _repeated_stackEntries_codec);
      if (Detail.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Detail);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(DebugInfo other) {
      if (other == null) {
        return;
      }
      stackEntries_.Add(other.stackEntries_);
      if (other.Detail.Length != 0) {
        Detail = other.Detail;
      }
    }

    [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: {
            stackEntries_.AddEntriesFrom(input, _repeated_stackEntries_codec);
            break;
          }
          case 18: {
            Detail = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Error status client expects to see.
  /// </summary>
  public sealed partial class ErrorStatus : pb::IMessage<ErrorStatus> {
    private static readonly pb::MessageParser<ErrorStatus> _parser = new pb::MessageParser<ErrorStatus>(() => new ErrorStatus());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ErrorStatus> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorStatus(ErrorStatus other) : this() {
      code_ = other.code_;
      errorMessage_ = other.errorMessage_;
      binaryErrorDetails_ = other.binaryErrorDetails_;
    }

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

    /// <summary>Field number for the "code" field.</summary>
    public const int CodeFieldNumber = 1;
    private int code_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Code {
      get { return code_; }
      set {
        code_ = value;
      }
    }

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

    /// <summary>Field number for the "binary_error_details" field.</summary>
    public const int BinaryErrorDetailsFieldNumber = 3;
    private string binaryErrorDetails_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string BinaryErrorDetails {
      get { return binaryErrorDetails_; }
      set {
        binaryErrorDetails_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Code != 0) hash ^= Code.GetHashCode();
      if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
      if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.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 (Code != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(Code);
      }
      if (ErrorMessage.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(ErrorMessage);
      }
      if (BinaryErrorDetails.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(BinaryErrorDetails);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ErrorStatus other) {
      if (other == null) {
        return;
      }
      if (other.Code != 0) {
        Code = other.Code;
      }
      if (other.ErrorMessage.Length != 0) {
        ErrorMessage = other.ErrorMessage;
      }
      if (other.BinaryErrorDetails.Length != 0) {
        BinaryErrorDetails = other.BinaryErrorDetails;
      }
    }

    [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: {
            Code = input.ReadInt32();
            break;
          }
          case 18: {
            ErrorMessage = input.ReadString();
            break;
          }
          case 26: {
            BinaryErrorDetails = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public RequestParams(RequestParams other) : this() {
      echoDeadline_ = other.echoDeadline_;
      clientCancelAfterUs_ = other.clientCancelAfterUs_;
      serverCancelAfterUs_ = other.serverCancelAfterUs_;
      echoMetadata_ = other.echoMetadata_;
      checkAuthContext_ = other.checkAuthContext_;
      responseMessageLength_ = other.responseMessageLength_;
      echoPeer_ = other.echoPeer_;
      expectedClientIdentity_ = other.expectedClientIdentity_;
      skipCancelledCheck_ = other.skipCancelledCheck_;
      expectedTransportSecurityType_ = other.expectedTransportSecurityType_;
      DebugInfo = other.debugInfo_ != null ? other.DebugInfo.Clone() : null;
      serverDie_ = other.serverDie_;
      binaryErrorDetails_ = other.binaryErrorDetails_;
      ExpectedError = other.expectedError_ != null ? other.ExpectedError.Clone() : null;
    }

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

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

    /// <summary>Field number for the "client_cancel_after_us" field.</summary>
    public const int ClientCancelAfterUsFieldNumber = 2;
    private int clientCancelAfterUs_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ClientCancelAfterUs {
      get { return clientCancelAfterUs_; }
      set {
        clientCancelAfterUs_ = value;
      }
    }

    /// <summary>Field number for the "server_cancel_after_us" field.</summary>
    public const int ServerCancelAfterUsFieldNumber = 3;
    private int serverCancelAfterUs_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ServerCancelAfterUs {
      get { return serverCancelAfterUs_; }
      set {
        serverCancelAfterUs_ = value;
      }
    }

    /// <summary>Field number for the "echo_metadata" field.</summary>
    public const int EchoMetadataFieldNumber = 4;
    private bool echoMetadata_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool EchoMetadata {
      get { return echoMetadata_; }
      set {
        echoMetadata_ = value;
      }
    }

    /// <summary>Field number for the "check_auth_context" field.</summary>
    public const int CheckAuthContextFieldNumber = 5;
    private bool checkAuthContext_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool CheckAuthContext {
      get { return checkAuthContext_; }
      set {
        checkAuthContext_ = value;
      }
    }

    /// <summary>Field number for the "response_message_length" field.</summary>
    public const int ResponseMessageLengthFieldNumber = 6;
    private int responseMessageLength_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ResponseMessageLength {
      get { return responseMessageLength_; }
      set {
        responseMessageLength_ = value;
      }
    }

    /// <summary>Field number for the "echo_peer" field.</summary>
    public const int EchoPeerFieldNumber = 7;
    private bool echoPeer_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool EchoPeer {
      get { return echoPeer_; }
      set {
        echoPeer_ = value;
      }
    }

    /// <summary>Field number for the "expected_client_identity" field.</summary>
    public const int ExpectedClientIdentityFieldNumber = 8;
    private string expectedClientIdentity_ = "";
    /// <summary>
    /// will force check_auth_context.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ExpectedClientIdentity {
      get { return expectedClientIdentity_; }
      set {
        expectedClientIdentity_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "skip_cancelled_check" field.</summary>
    public const int SkipCancelledCheckFieldNumber = 9;
    private bool skipCancelledCheck_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool SkipCancelledCheck {
      get { return skipCancelledCheck_; }
      set {
        skipCancelledCheck_ = value;
      }
    }

    /// <summary>Field number for the "expected_transport_security_type" field.</summary>
    public const int ExpectedTransportSecurityTypeFieldNumber = 10;
    private string expectedTransportSecurityType_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ExpectedTransportSecurityType {
      get { return expectedTransportSecurityType_; }
      set {
        expectedTransportSecurityType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

    /// <summary>Field number for the "server_die" field.</summary>
    public const int ServerDieFieldNumber = 12;
    private bool serverDie_;
    /// <summary>
    /// Server should not see a request with this set.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool ServerDie {
      get { return serverDie_; }
      set {
        serverDie_ = value;
      }
    }

    /// <summary>Field number for the "binary_error_details" field.</summary>
    public const int BinaryErrorDetailsFieldNumber = 13;
    private string binaryErrorDetails_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string BinaryErrorDetails {
      get { return binaryErrorDetails_; }
      set {
        binaryErrorDetails_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "expected_error" field.</summary>
    public const int ExpectedErrorFieldNumber = 14;
    private global::Grpc.Testing.ErrorStatus expectedError_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ErrorStatus ExpectedError {
      get { return expectedError_; }
      set {
        expectedError_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(RequestParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (EchoDeadline != other.EchoDeadline) return false;
      if (ClientCancelAfterUs != other.ClientCancelAfterUs) return false;
      if (ServerCancelAfterUs != other.ServerCancelAfterUs) return false;
      if (EchoMetadata != other.EchoMetadata) return false;
      if (CheckAuthContext != other.CheckAuthContext) return false;
      if (ResponseMessageLength != other.ResponseMessageLength) return false;
      if (EchoPeer != other.EchoPeer) return false;
      if (ExpectedClientIdentity != other.ExpectedClientIdentity) return false;
      if (SkipCancelledCheck != other.SkipCancelledCheck) return false;
      if (ExpectedTransportSecurityType != other.ExpectedTransportSecurityType) return false;
      if (!object.Equals(DebugInfo, other.DebugInfo)) return false;
      if (ServerDie != other.ServerDie) return false;
      if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
      if (!object.Equals(ExpectedError, other.ExpectedError)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (EchoDeadline != false) hash ^= EchoDeadline.GetHashCode();
      if (ClientCancelAfterUs != 0) hash ^= ClientCancelAfterUs.GetHashCode();
      if (ServerCancelAfterUs != 0) hash ^= ServerCancelAfterUs.GetHashCode();
      if (EchoMetadata != false) hash ^= EchoMetadata.GetHashCode();
      if (CheckAuthContext != false) hash ^= CheckAuthContext.GetHashCode();
      if (ResponseMessageLength != 0) hash ^= ResponseMessageLength.GetHashCode();
      if (EchoPeer != false) hash ^= EchoPeer.GetHashCode();
      if (ExpectedClientIdentity.Length != 0) hash ^= ExpectedClientIdentity.GetHashCode();
      if (SkipCancelledCheck != false) hash ^= SkipCancelledCheck.GetHashCode();
      if (ExpectedTransportSecurityType.Length != 0) hash ^= ExpectedTransportSecurityType.GetHashCode();
      if (debugInfo_ != null) hash ^= DebugInfo.GetHashCode();
      if (ServerDie != false) hash ^= ServerDie.GetHashCode();
      if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
      if (expectedError_ != null) hash ^= ExpectedError.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 (EchoDeadline != false) {
        output.WriteRawTag(8);
        output.WriteBool(EchoDeadline);
      }
      if (ClientCancelAfterUs != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(ClientCancelAfterUs);
      }
      if (ServerCancelAfterUs != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(ServerCancelAfterUs);
      }
      if (EchoMetadata != false) {
        output.WriteRawTag(32);
        output.WriteBool(EchoMetadata);
      }
      if (CheckAuthContext != false) {
        output.WriteRawTag(40);
        output.WriteBool(CheckAuthContext);
      }
      if (ResponseMessageLength != 0) {
        output.WriteRawTag(48);
        output.WriteInt32(ResponseMessageLength);
      }
      if (EchoPeer != false) {
        output.WriteRawTag(56);
        output.WriteBool(EchoPeer);
      }
      if (ExpectedClientIdentity.Length != 0) {
        output.WriteRawTag(66);
        output.WriteString(ExpectedClientIdentity);
      }
      if (SkipCancelledCheck != false) {
        output.WriteRawTag(72);
        output.WriteBool(SkipCancelledCheck);
      }
      if (ExpectedTransportSecurityType.Length != 0) {
        output.WriteRawTag(82);
        output.WriteString(ExpectedTransportSecurityType);
      }
      if (debugInfo_ != null) {
        output.WriteRawTag(90);
        output.WriteMessage(DebugInfo);
      }
      if (ServerDie != false) {
        output.WriteRawTag(96);
        output.WriteBool(ServerDie);
      }
      if (BinaryErrorDetails.Length != 0) {
        output.WriteRawTag(106);
        output.WriteString(BinaryErrorDetails);
      }
      if (expectedError_ != null) {
        output.WriteRawTag(114);
        output.WriteMessage(ExpectedError);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (EchoDeadline != false) {
        size += 1 + 1;
      }
      if (ClientCancelAfterUs != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientCancelAfterUs);
      }
      if (ServerCancelAfterUs != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerCancelAfterUs);
      }
      if (EchoMetadata != false) {
        size += 1 + 1;
      }
      if (CheckAuthContext != false) {
        size += 1 + 1;
      }
      if (ResponseMessageLength != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseMessageLength);
      }
      if (EchoPeer != false) {
        size += 1 + 1;
      }
      if (ExpectedClientIdentity.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ExpectedClientIdentity);
      }
      if (SkipCancelledCheck != false) {
        size += 1 + 1;
      }
      if (ExpectedTransportSecurityType.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ExpectedTransportSecurityType);
      }
      if (debugInfo_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DebugInfo);
      }
      if (ServerDie != false) {
        size += 1 + 1;
      }
      if (BinaryErrorDetails.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails);
      }
      if (expectedError_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectedError);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(RequestParams other) {
      if (other == null) {
        return;
      }
      if (other.EchoDeadline != false) {
        EchoDeadline = other.EchoDeadline;
      }
      if (other.ClientCancelAfterUs != 0) {
        ClientCancelAfterUs = other.ClientCancelAfterUs;
      }
      if (other.ServerCancelAfterUs != 0) {
        ServerCancelAfterUs = other.ServerCancelAfterUs;
      }
      if (other.EchoMetadata != false) {
        EchoMetadata = other.EchoMetadata;
      }
      if (other.CheckAuthContext != false) {
        CheckAuthContext = other.CheckAuthContext;
      }
      if (other.ResponseMessageLength != 0) {
        ResponseMessageLength = other.ResponseMessageLength;
      }
      if (other.EchoPeer != false) {
        EchoPeer = other.EchoPeer;
      }
      if (other.ExpectedClientIdentity.Length != 0) {
        ExpectedClientIdentity = other.ExpectedClientIdentity;
      }
      if (other.SkipCancelledCheck != false) {
        SkipCancelledCheck = other.SkipCancelledCheck;
      }
      if (other.ExpectedTransportSecurityType.Length != 0) {
        ExpectedTransportSecurityType = other.ExpectedTransportSecurityType;
      }
      if (other.debugInfo_ != null) {
        if (debugInfo_ == null) {
          debugInfo_ = new global::Grpc.Testing.DebugInfo();
        }
        DebugInfo.MergeFrom(other.DebugInfo);
      }
      if (other.ServerDie != false) {
        ServerDie = other.ServerDie;
      }
      if (other.BinaryErrorDetails.Length != 0) {
        BinaryErrorDetails = other.BinaryErrorDetails;
      }
      if (other.expectedError_ != null) {
        if (expectedError_ == null) {
          expectedError_ = new global::Grpc.Testing.ErrorStatus();
        }
        ExpectedError.MergeFrom(other.ExpectedError);
      }
    }

    [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: {
            EchoDeadline = input.ReadBool();
            break;
          }
          case 16: {
            ClientCancelAfterUs = input.ReadInt32();
            break;
          }
          case 24: {
            ServerCancelAfterUs = input.ReadInt32();
            break;
          }
          case 32: {
            EchoMetadata = input.ReadBool();
            break;
          }
          case 40: {
            CheckAuthContext = input.ReadBool();
            break;
          }
          case 48: {
            ResponseMessageLength = input.ReadInt32();
            break;
          }
          case 56: {
            EchoPeer = input.ReadBool();
            break;
          }
          case 66: {
            ExpectedClientIdentity = input.ReadString();
            break;
          }
          case 72: {
            SkipCancelledCheck = input.ReadBool();
            break;
          }
          case 82: {
            ExpectedTransportSecurityType = input.ReadString();
            break;
          }
          case 90: {
            if (debugInfo_ == null) {
              debugInfo_ = new global::Grpc.Testing.DebugInfo();
            }
            input.ReadMessage(debugInfo_);
            break;
          }
          case 96: {
            ServerDie = input.ReadBool();
            break;
          }
          case 106: {
            BinaryErrorDetails = input.ReadString();
            break;
          }
          case 114: {
            if (expectedError_ == null) {
              expectedError_ = new global::Grpc.Testing.ErrorStatus();
            }
            input.ReadMessage(expectedError_);
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoRequest(EchoRequest other) : this() {
      message_ = other.message_;
      Param = other.param_ != null ? other.Param.Clone() : null;
    }

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

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

    /// <summary>Field number for the "param" field.</summary>
    public const int ParamFieldNumber = 2;
    private global::Grpc.Testing.RequestParams param_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.RequestParams Param {
      get { return param_; }
      set {
        param_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Message.Length != 0) hash ^= Message.GetHashCode();
      if (param_ != null) hash ^= Param.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 (Message.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Message);
      }
      if (param_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Param);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EchoRequest other) {
      if (other == null) {
        return;
      }
      if (other.Message.Length != 0) {
        Message = other.Message;
      }
      if (other.param_ != null) {
        if (param_ == null) {
          param_ = new global::Grpc.Testing.RequestParams();
        }
        Param.MergeFrom(other.Param);
      }
    }

    [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: {
            Message = input.ReadString();
            break;
          }
          case 18: {
            if (param_ == null) {
              param_ = new global::Grpc.Testing.RequestParams();
            }
            input.ReadMessage(param_);
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ResponseParams(ResponseParams other) : this() {
      requestDeadline_ = other.requestDeadline_;
      host_ = other.host_;
      peer_ = other.peer_;
    }

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

    /// <summary>Field number for the "request_deadline" field.</summary>
    public const int RequestDeadlineFieldNumber = 1;
    private long requestDeadline_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long RequestDeadline {
      get { return requestDeadline_; }
      set {
        requestDeadline_ = value;
      }
    }

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

    /// <summary>Field number for the "peer" field.</summary>
    public const int PeerFieldNumber = 3;
    private string peer_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Peer {
      get { return peer_; }
      set {
        peer_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (RequestDeadline != 0L) hash ^= RequestDeadline.GetHashCode();
      if (Host.Length != 0) hash ^= Host.GetHashCode();
      if (Peer.Length != 0) hash ^= Peer.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 (RequestDeadline != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(RequestDeadline);
      }
      if (Host.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Host);
      }
      if (Peer.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(Peer);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (RequestDeadline != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(RequestDeadline);
      }
      if (Host.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
      }
      if (Peer.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Peer);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ResponseParams other) {
      if (other == null) {
        return;
      }
      if (other.RequestDeadline != 0L) {
        RequestDeadline = other.RequestDeadline;
      }
      if (other.Host.Length != 0) {
        Host = other.Host;
      }
      if (other.Peer.Length != 0) {
        Peer = other.Peer;
      }
    }

    [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: {
            RequestDeadline = input.ReadInt64();
            break;
          }
          case 18: {
            Host = input.ReadString();
            break;
          }
          case 26: {
            Peer = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoResponse(EchoResponse other) : this() {
      message_ = other.message_;
      Param = other.param_ != null ? other.Param.Clone() : null;
    }

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

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

    /// <summary>Field number for the "param" field.</summary>
    public const int ParamFieldNumber = 2;
    private global::Grpc.Testing.ResponseParams param_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ResponseParams Param {
      get { return param_; }
      set {
        param_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Message.Length != 0) hash ^= Message.GetHashCode();
      if (param_ != null) hash ^= Param.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 (Message.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Message);
      }
      if (param_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Param);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EchoResponse other) {
      if (other == null) {
        return;
      }
      if (other.Message.Length != 0) {
        Message = other.Message;
      }
      if (other.param_ != null) {
        if (param_ == null) {
          param_ = new global::Grpc.Testing.ResponseParams();
        }
        Param.MergeFrom(other.Param);
      }
    }

    [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: {
            Message = input.ReadString();
            break;
          }
          case 18: {
            if (param_ == null) {
              param_ = new global::Grpc.Testing.ResponseParams();
            }
            input.ReadMessage(param_);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
