//
//
// Copyright 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.
//
//

#include "test/cpp/interop/http2_client.h"

#include <thread>

#include "absl/flags/flag.h"
#include "absl/strings/str_format.h"

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/test_config.h"

namespace grpc {
namespace testing {

namespace {
const int kLargeRequestSize = 271828;
const int kLargeResponseSize = 314159;
}  // namespace

Http2Client::ServiceStub::ServiceStub(const std::shared_ptr<Channel>& channel)
    : channel_(channel) {
  stub_ = TestService::NewStub(channel);
}

TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); }

Http2Client::Http2Client(const std::shared_ptr<Channel>& channel)
    : serviceStub_(channel),
      channel_(channel),
      defaultRequest_(BuildDefaultRequest()) {}

bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) {
  if (s.error_code() == expected_code) {
    return true;
  }

  grpc_core::Crash(absl::StrFormat(
      "Error status code: %d (expected: %d), message: %s", s.error_code(),
      expected_code, s.error_message().c_str()));
}

Status Http2Client::SendUnaryCall(SimpleResponse* response) {
  ClientContext context;
  return serviceStub_.Get()->UnaryCall(&context, defaultRequest_, response);
}

SimpleRequest Http2Client::BuildDefaultRequest() {
  SimpleRequest request;
  request.set_response_size(kLargeResponseSize);
  std::string payload(kLargeRequestSize, '\0');
  request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
  return request;
}

bool Http2Client::DoRstAfterHeader() {
  gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header");

  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
  GPR_ASSERT(!response.has_payload());  // no data should be received

  gpr_log(GPR_DEBUG, "Done testing reset stream after header");
  return true;
}

bool Http2Client::DoRstAfterData() {
  gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data");

  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
  // There is no guarantee that data would be received.

  gpr_log(GPR_DEBUG, "Done testing reset stream after data");
  return true;
}

bool Http2Client::DoRstDuringData() {
  gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data");

  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
  GPR_ASSERT(!response.has_payload());  // no data should be received

  gpr_log(GPR_DEBUG, "Done testing reset stream during data");
  return true;
}

bool Http2Client::DoGoaway() {
  gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway");
  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
  GPR_ASSERT(response.payload().body() ==
             std::string(kLargeResponseSize, '\0'));

  // Sleep for one second to give time for client to receive goaway frame.
  gpr_timespec sleep_time = gpr_time_add(
      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(1, GPR_TIMESPAN));
  gpr_sleep_until(sleep_time);

  response.Clear();
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
  GPR_ASSERT(response.payload().body() ==
             std::string(kLargeResponseSize, '\0'));
  gpr_log(GPR_DEBUG, "Done testing goaway");
  return true;
}

bool Http2Client::DoPing() {
  gpr_log(GPR_DEBUG, "Sending RPC and expecting ping");
  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
  GPR_ASSERT(response.payload().body() ==
             std::string(kLargeResponseSize, '\0'));
  gpr_log(GPR_DEBUG, "Done testing ping");
  return true;
}

void Http2Client::MaxStreamsWorker(
    const std::shared_ptr<grpc::Channel>& /*channel*/) {
  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
  GPR_ASSERT(response.payload().body() ==
             std::string(kLargeResponseSize, '\0'));
}

bool Http2Client::DoMaxStreams() {
  gpr_log(GPR_DEBUG, "Testing max streams");

  // Make an initial call on the channel to ensure the server's max streams
  // setting is received
  SimpleResponse response;
  AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
  GPR_ASSERT(response.payload().body() ==
             std::string(kLargeResponseSize, '\0'));

  std::vector<std::thread> test_threads;
  test_threads.reserve(10);
  for (int i = 0; i < 10; i++) {
    test_threads.emplace_back(
        std::thread(&Http2Client::MaxStreamsWorker, this, channel_));
  }

  for (auto it = test_threads.begin(); it != test_threads.end(); it++) {
    it->join();
  }

  gpr_log(GPR_DEBUG, "Done testing max streams");
  return true;
}

}  // namespace testing
}  // namespace grpc

ABSL_FLAG(int32_t, server_port, 0, "Server port.");
ABSL_FLAG(std::string, server_host, "localhost", "Server host to connect to");
ABSL_FLAG(std::string, test_case, "rst_after_header",
          "Configure different test cases. Valid options are:\n\n"
          "goaway\n"
          "max_streams\n"
          "ping\n"
          "rst_after_data\n"
          "rst_after_header\n"
          "rst_during_data\n");

int main(int argc, char** argv) {
  grpc::testing::InitTest(&argc, &argv, true);
  GPR_ASSERT(absl::GetFlag(FLAGS_server_port));
  const int host_port_buf_size = 1024;
  char host_port[host_port_buf_size];
  snprintf(host_port, host_port_buf_size, "%s:%d",
           absl::GetFlag(FLAGS_server_host).c_str(),
           absl::GetFlag(FLAGS_server_port));
  std::shared_ptr<grpc::Channel> channel =
      grpc::CreateTestChannel(host_port, grpc::testing::INSECURE);
  GPR_ASSERT(channel->WaitForConnected(gpr_time_add(
      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(300, GPR_TIMESPAN))));
  grpc::testing::Http2Client client(channel);
  gpr_log(GPR_INFO, "Testing case: %s", absl::GetFlag(FLAGS_test_case).c_str());
  int ret = 0;
  if (absl::GetFlag(FLAGS_test_case) == "rst_after_header") {
    client.DoRstAfterHeader();
  } else if (absl::GetFlag(FLAGS_test_case) == "rst_after_data") {
    client.DoRstAfterData();
  } else if (absl::GetFlag(FLAGS_test_case) == "rst_during_data") {
    client.DoRstDuringData();
  } else if (absl::GetFlag(FLAGS_test_case) == "goaway") {
    client.DoGoaway();
  } else if (absl::GetFlag(FLAGS_test_case) == "ping") {
    client.DoPing();
  } else if (absl::GetFlag(FLAGS_test_case) == "max_streams") {
    client.DoMaxStreams();
  } else {
    const char* testcases[] = {
        "goaway",         "max_streams",      "ping",
        "rst_after_data", "rst_after_header", "rst_during_data"};
    char* joined_testcases =
        gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", nullptr);

    gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s",
            absl::GetFlag(FLAGS_test_case).c_str(), joined_testcases);
    gpr_free(joined_testcases);
    ret = 1;
  }

  return ret;
}
