
// Copyright 2015-2016 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses.

syntax = "proto3";

import "src/proto/grpc/testing/empty.proto";
import "src/proto/grpc/testing/messages.proto";

package grpc.testing;

option java_package = "io.grpc.testing.integration";

// A simple service to test the various types of RPCs and experiment with
// performance with various types of payload.
service TestService {
  // One empty request followed by one empty response.
  rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty);

  // One request followed by one response.
  rpc UnaryCall(SimpleRequest) returns (SimpleResponse);

  // One request followed by one response. Response has cache control
  // headers set such that a caching HTTP proxy (such as GFE) can
  // satisfy subsequent requests.
  rpc CacheableUnaryCall(SimpleRequest) returns (SimpleResponse);

  // One request followed by a sequence of responses (streamed download).
  // The server returns the payload with client desired type and sizes.
  rpc StreamingOutputCall(StreamingOutputCallRequest)
      returns (stream StreamingOutputCallResponse);

  // A sequence of requests followed by one response (streamed upload).
  // The server returns the aggregated size of client payload as the result.
  rpc StreamingInputCall(stream StreamingInputCallRequest)
      returns (StreamingInputCallResponse);

  // A sequence of requests with each request served by the server immediately.
  // As one request could lead to multiple responses, this interface
  // demonstrates the idea of full duplexing.
  rpc FullDuplexCall(stream StreamingOutputCallRequest)
      returns (stream StreamingOutputCallResponse);

  // A sequence of requests followed by a sequence of responses.
  // The server buffers all the client requests and then serves them in order. A
  // stream of responses are returned to the client when the server starts with
  // first request.
  rpc HalfDuplexCall(stream StreamingOutputCallRequest)
      returns (stream StreamingOutputCallResponse);

  // The test server will not implement this method. It will be used
  // to test the behavior when clients call unimplemented methods.
  rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty);
}

// A simple service NOT implemented at servers so clients can test for
// that case.
service UnimplementedService {
  // A call that no server should implement
  rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty);
}

// A service used to control reconnect server.
service ReconnectService {
  rpc Start(grpc.testing.ReconnectParams) returns (grpc.testing.Empty);
  rpc Stop(grpc.testing.Empty) returns (grpc.testing.ReconnectInfo);
}

// A service used to obtain stats for verifying LB behavior.
service LoadBalancerStatsService {
  // Gets the backend distribution for RPCs sent by a test client.
  rpc GetClientStats(LoadBalancerStatsRequest)
      returns (LoadBalancerStatsResponse) {}

  // Gets the accumulated stats for RPCs sent by a test client.
  rpc GetClientAccumulatedStats(LoadBalancerAccumulatedStatsRequest)
      returns (LoadBalancerAccumulatedStatsResponse) {}
}

// Hook service. Used to keep Kubernetes from shutting the pod down.
service HookService {
  // Sends a request that will "hang" until the return status is set by a call
  // to a SetReturnStatus
  rpc Hook(grpc.testing.Empty) returns (grpc.testing.Empty);
  // Sets a return status for pending and upcoming calls to Hook
  rpc SetReturnStatus(SetReturnStatusRequest) returns (grpc.testing.Empty);
  // Clears the return status. Incoming calls to Hook will "hang"
  rpc ClearReturnStatus(grpc.testing.Empty) returns (grpc.testing.Empty);
}

// A service to remotely control health status of an xDS test server.
service XdsUpdateHealthService {
  rpc SetServing(grpc.testing.Empty) returns (grpc.testing.Empty);
  rpc SetNotServing(grpc.testing.Empty) returns (grpc.testing.Empty);
  rpc SendHookRequest(HookRequest) returns (HookResponse);
}

// A service to dynamically update the configuration of an xDS test client.
service XdsUpdateClientConfigureService {
  // Update the tes client's configuration.
  rpc Configure(ClientConfigureRequest) returns (ClientConfigureResponse);
}
