syntax = "proto3";

package io.contract_testing.contractcase.grpc;

import "google/protobuf/struct.proto";
import "google/protobuf/wrappers.proto";

option java_package = "io.contract_testing.contractcase.grpc";

message ContractCaseConfig {
  message UsernamePassword {
    google.protobuf.StringValue username = 1;
    google.protobuf.StringValue password = 2;
  }

  google.protobuf.StringValue provider_name = 1;
  google.protobuf.StringValue consumer_name = 2;
  google.protobuf.StringValue log_level = 3;
  google.protobuf.StringValue contract_dir = 4;
  google.protobuf.StringValue contract_filename = 5;
  google.protobuf.StringValue publish = 6;
  google.protobuf.StringValue broker_ci_access_token = 7;
  google.protobuf.StringValue broker_base_url = 8;
  UsernamePassword broker_basic_auth = 9;

  google.protobuf.BoolValue print_results = 10;
  google.protobuf.BoolValue throw_on_fail = 11;

  repeated StateHandlerHandle state_handlers = 12;
  map<string, TriggerFunctionHandle> trigger_and_tests = 13;

  TriggerFunctionHandle trigger_and_test = 14;

  google.protobuf.StringValue base_url_under_test =
      15; // Long term, this will be moved

  map<string, string> mock_config = 16;

  google.protobuf.StringValue auto_version_from = 17;

  google.protobuf.StringValue changed_contracts = 18;

  map<string, string> advice_overrides = 19;

  // Note: if there are no contracts_to_write, the defaults
  // will be used. If the user tries to explicitly set 
  // an empty array, you should throw an error instead 
  // of sending an empty array
  repeated google.protobuf.StringValue contracts_to_write = 20;
}

// Indicates a successful response with no payload
message ResultSuccess {
}
message ResultSuccessHasMapPayload {
  // Always a map of Strings -> Strings
  google.protobuf.Struct map = 1;
}
message ResultSuccessHasAnyPayload {
  // Always a JSON serialised object
  google.protobuf.StringValue payload = 1;
}
// Indicates an exception was thrown
message ResultFailure {
  // Failure kind (See BoundaryFailureKindConstants)
  google.protobuf.StringValue kind = 1;
  // String message, human readable
  google.protobuf.StringValue message = 2;
  // Matching engine's location string. May be blank if not meaningful.
  google.protobuf.StringValue location = 3;
  // Error code for linking to documentation and programmatic wrappers.
  // If this is "UNDOCUMENTED" or blank, it should be ignored.
  google.protobuf.StringValue contract_case_error_code = 4;
  // Stack trace as a string (multiline, separated with \n)
  // If this is an empty string, there is no user-facing stack trace
  google.protobuf.StringValue user_facing_stack_trace = 5;
}

message BoundaryResult {
  oneof value {
    ResultSuccess success = 1;
    ResultSuccessHasMapPayload success_has_map = 2;
    ResultSuccessHasAnyPayload success_has_any = 3;
    ResultFailure failure = 4;
  }
}

message StateHandlerHandle {
  enum Stage {
    STAGE_SETUP_UNSPECIFIED = 0;
    STAGE_TEARDOWN = 1;
  }
  // The name of the state
  google.protobuf.StringValue handle = 1;
  // Whether this is a setup or a teardown handler
  Stage stage = 2;
}

// A reference to a trigger function that can be invoked
message TriggerFunctionHandle {
  google.protobuf.StringValue handle = 1;
}

// Requests from client / host

// From Host to Core, instructs the core to begin a contract definition
message BeginDefinitionRequest {
  ContractCaseConfig config = 1;
  repeated google.protobuf.StringValue caller_versions = 4;
}

// From Host to Core, instructs the core to run a particular example as part of
// contract definition
message RunInteractionRequest {
  google.protobuf.Struct example_definition = 2;
  ContractCaseConfig config = 3;
}

// From host to core, instructs the core to run a particular example, that we
// expect to fail. This is part of contract definition
message RunRejectingInteractionRequest {
  google.protobuf.Struct example_definition = 2;
  ContractCaseConfig config = 3;
}

// From host to core, instructs the core to strip the matchers from a given
// matcher / data object
message StripMatchersRequest {
  google.protobuf.Struct matcher_or_data = 2;
}

// From host to core, instructs the core to finish the current contract
// definition
message EndDefinitionRequest {
}

// From host to core, instructs the core to load a plugin
message LoadPluginRequest {
  repeated google.protobuf.StringValue module_names = 1;
  ContractCaseConfig config = 2;
  repeated google.protobuf.StringValue caller_versions = 3;
}

// Responses from server

// From Core to Host, instructs the host to run a given state handler
message RunStateHandlerRequest {
  StateHandlerHandle state_handler_handle = 1;
}

// From Core to Host, requests the host invoke one of the user-provided
// triggers.
message TriggerFunctionRequest {
  TriggerFunctionHandle trigger_function = 1;
  // This was the previous setupInfo
  // google.protobuf.Struct config = 2;
  reserved 2;
  // The current setup of this Interaction, provided by the mock executor
  SetupInfo setup = 3;
}

message CoreFunctionHandle {
  google.protobuf.StringValue handle = 1;
}

// Describes the setup of the currently executing Interaction
message SetupInfo {
  // The resolved values for the state variables
  map<string, google.protobuf.StringValue> state_variables = 1;
  // The values of any mock setup information
  map<string, google.protobuf.StringValue> mock = 2;
  // Callbacks handles for functions
  map<string, CoreFunctionHandle> functions = 3;
}

// From Core to Host, requests the host logs the given information
message LogRequest {
  /**
   * A `LogLevel`   google.protobuf.StringValue , either `error`, `warn`,
   * `debug`, `maintainerDebug` or `deepMaintainerDebug` Use this to
   * programmatically decide any colour formatting.. (although `none` is a
   * possible log level, this function will never be called with `none`).
   */
  google.protobuf.StringValue level = 1;
  /**
   * The timestamp generated by ContractCase, ready for printing. No extra
   * formatting is necessary
   */
  google.protobuf.StringValue timestamp = 2;
  /**
   * The version   google.protobuf.StringValue  for the current ContractCase
   * stack (at low log levels, this is just the core version)
   */
  google.protobuf.StringValue version = 3;
  /**
   * A rendered version of the LogLevel. Do not rely on this value
   * programmatically, use the `level` parameter instead.
   */
  google.protobuf.StringValue type_string = 4;
  /**
   * A   google.protobuf.StringValue  that represents the location that this log
   * came from
   */
  google.protobuf.StringValue location = 5;
  /**
   * The main message of this log line
   */
  google.protobuf.StringValue message = 6;
  /**
   * Any additional output to print on extra lines (you may want to indent this
   * when printing)
   */
  google.protobuf.StringValue additional = 7;
}

// From Core to Host, requests the host prints the given expected/actual error
message PrintMatchErrorRequest {
  /**
   * The red highlighted blob, eg "MATCHING ERROR" or "TRIGGER FUNCTION ERROR".
   * Could be any   google.protobuf.StringValue .
   */
  google.protobuf.StringValue kind = 1;
  /**
   * A summary of the error. Could be any   google.protobuf.StringValue .
   */
  google.protobuf.StringValue message = 2;
  /**
   * The location the error happened, for printing at the top of the error
   * message
   */
  google.protobuf.StringValue location = 3;
  /**
   * The tag line for the location the error happened, for printing after the
   * error message. This might have more information than the `location` above.
   */
  google.protobuf.StringValue location_tag = 4;
  /**
   * The machine-readable type for the cause of this error, for printing after
   * the error message to make it easy to search for.
   */
  google.protobuf.StringValue error_type_tag = 5;
  /**
   * A   google.protobuf.StringValue  representation of the expected data (may
   * contain newlines)
   */
  google.protobuf.StringValue expected = 6;
  /**
   * A   google.protobuf.StringValue  representation of the actual data received
   * (may contain newlines)
   */
  google.protobuf.StringValue actual = 7;
}

// From Core to host, requests the host prints the following error message (used
// by test failures that aren't because of expected / actual expectations or
// configuration)
message PrintMessageErrorRequest {
  /**
   * The red highlighted blob, eg "MATCHING ERROR" or "TRIGGER FUNCTION ERROR".
   * Could be any   google.protobuf.StringValue .
   */
  google.protobuf.StringValue kind = 1;
  /**
   * A summary of the error. Could be any   google.protobuf.StringValue .
   */
  google.protobuf.StringValue message = 2;
  /**
   * The location the error happened, for printing at the top of the error
   * message
   */
  google.protobuf.StringValue location = 3;
  /**
   * The tag line for the location the error happened, for printing after the
   * error message. This might have more information than the `location` above.
   */
  google.protobuf.StringValue location_tag = 4;
  /**
   * The machine-readable type for the cause of this error, for printing after
   * the error message to make it easy to search for.
   */
  google.protobuf.StringValue error_type_tag = 5;
}

message PrintTestTitleRequest {
  /**
   * Either 'success' to indicate success, or 'failure' to indicate failure
   */
  google.protobuf.StringValue kind = 1;
  /**
   * An icon for the start of the line (usually a single character emoji, but
   * could be any   google.protobuf.StringValue )
   */
  google.protobuf.StringValue icon = 2;
  /**
   * The title to print (will not include newlines)
   */
  google.protobuf.StringValue title = 3;
  /**
   * Any additional text to print after the title (may include newlines)
   */
  google.protobuf.StringValue additional_text = 4;
}

// Used by both to indicate a response to an earlier message
// Responses share the ID of the requesting message
// This was probably a mistake - in a future version, we should
// expand the ID field so that it's "in response to"
//
// Most messages must be acknowledged with a response - this indicates the
// return of the previous message.
message ResultResponse {
  BoundaryResult result = 1;
}

// From the Host to the Core, requests that a verification session begins
message BeginVerificationRequest {
  // The configuration for this verification
  ContractCaseConfig config = 1;
  // Version strings of all ContractCase components for maintainer logs
  repeated google.protobuf.StringValue caller_versions = 4;
}

// From the Host to the Core, requests a list of the available contracts
message AvailableContractDefinitions {
}

// From the Host to the Core, instructs the core that the current verification
// session is now configured, and asks it to execute the verification.
// No longer implemented
// message RunVerification {
// Any configuration overrides for this verification
//  ContractCaseConfig config = 1;
// }

// Deprecated StartTestEvent: From the Core to the Host, 
// instructs the host that a new test is starting.
// This is useful for test frameworks reporting, and has no effect if it is
// acknowledged without taking any action.
// message StartTestEvent {
// The name of this test (human readable)
//  google.protobuf.StringValue test_name = 1;
// An ID for a callback to the test invoker when the core is ready
//  google.protobuf.StringValue invoker_id = 2;
// }

// A handle to a previously prepared test, used from the core to
// the host during verification, and sent back from the host to the core
// to run a previously prepared test.
message PreparedTestHandle {
  int32 contract_index = 2;
  int32 test_index = 3;
  google.protobuf.StringValue test_name = 4; 
}

// From the Host to the Core, tells the core to execute the test it was given
message InvokeTest {
  // Callback ID from the host language in a start test event
  // Used by the core to invoke a specific test
  oneof test {
    google.protobuf.StringValue invoker_id = 1;
    PreparedTestHandle prepared_test_handle = 2;
  }
}

// From the Host to the Core, tells the core to register a specific function
// that can be called back later by handle name.
message RegisterFunction {
  // The function handle / name
  google.protobuf.StringValue handle = 1;
}

// From the Core to the Host, to invoke a previously registered function.
message InvokeFunction {
  // The function handle / name to invoke
  google.protobuf.StringValue handle = 1;
  // The arguments for the function, as json strings
  repeated google.protobuf.StringValue arguments = 2;
}

// From the Host to the Core, read the contract files, and prepare a list of
// tests that can be executed later. This exists because test runners
// generally want to decide when the tests run.
message PrepareVerificationTests {
  // Any configuration overrides for this verification
  ContractCaseConfig config = 1;
}

// From the Host to the Core, tells the core that the
// host has finished running one or more verifications
message EndVerificationRequest {
  // The indices of the contracts that were verified
  repeated int32 contract_indices = 1;
}

// Messages on the stream during contract definition.
message DefinitionRequest {
  google.protobuf.StringValue id = 1;
  oneof kind {
    // Host language wants to begin a definition
    BeginDefinitionRequest begin_definition = 2;
    // Host language wants to run an example that returns success
    RunInteractionRequest run_interaction = 3;
    // Host language wants to run an example that returns a failure
    RunRejectingInteractionRequest run_rejecting_interaction = 4;
    // Host language wants to strip the matchers from a defintion
    StripMatchersRequest strip_matchers = 5;
    // Host language has finished the definition
    EndDefinitionRequest end_definition = 6;
    // Host is responding to a core call
    ResultResponse result_response = 7;
    // Host wants to load a plugin
    LoadPluginRequest load_plugin = 8;
    // Host wants to register a function that the Core can call
    RegisterFunction register_function = 9;
    // Host wants to invoke an arbitrary function on the core,
    // learned about via SetupInfo
    InvokeFunction invoke_function = 11;
  }
}

// Messages in the stream during contract verification
message VerificationRequest {
  // Host language wants to run a verification. 
  // Alternative to prepare verification tests
  // No longer implemented
  // RunVerification run_verification = 4;
  reserved 4;
  google.protobuf.StringValue id = 1;
  oneof kind {
    // Host language wants to start a verification session
    // Used to do initial setup by the core - must be called before
    // run_verification or prepare verification tests
    BeginVerificationRequest begin_verification = 2;
    // Host language wants to know what contracts are available
    AvailableContractDefinitions available_contract_definitions = 3;

    // Host is responding to a core call
    ResultResponse result_response = 5;
    // Host wants to load a plugin
    LoadPluginRequest load_plugin = 6;
    // Callback for the Host when the Core asked it invoke a specific test
    InvokeTest invoke_test = 9;
    // Host wants to register a function that the Core can call
    RegisterFunction register_function = 10;
    // Host wants to invoke an arbitrary function on the core,
    // learned about via SetupInfo
    InvokeFunction invoke_function = 11;
    // Host language wants to run a verification. 
    // Alternative to prepare verification tests
    PrepareVerificationTests prepare_verification_tests = 12;
    // Host language wants to finish running a verification.
    // Call this after you've run all verifications prepared
    // with prepare_verification_tests
    EndVerificationRequest end_verification = 13;
  }
}

message ContractResponse {
  // Field 9: Invoking tests (verification only)
  // Removed after 0.27.0, as the core 
  // no longer controls verification
  // execution
  // StartTestEvent start_test_event = 9;
  reserved 9;
  google.protobuf.StringValue id = 1;
  oneof kind {
    // Run a state handler
    RunStateHandlerRequest run_state_handler = 2;
    // Request to log a line
    LogRequest log_request = 3;
    // Request to print a matching error (has a diff)
    PrintMatchErrorRequest print_match_error_request = 4;
    // Request to print an error from a test that just has a message
    PrintMessageErrorRequest print_message_error_request = 5;
    // Request to print a test title
    PrintTestTitleRequest print_test_title_request = 6;
    // Request to trigger a trigger function
    TriggerFunctionRequest trigger_function_request = 7;
    // Answering client driven RPC calls
    ResultResponse result_response = 8;


    // Core wants to invoke an arbitrary function on the host,
    // registered earlier by RegisterFunction
    InvokeFunction invoke_function = 10;
  }
}

service ContractCase {
  rpc ContractDefinition(stream DefinitionRequest)
      returns (stream ContractResponse) {}

  rpc ContractVerification(stream VerificationRequest)
      returns (stream ContractResponse) {}
}
