//
//
// 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 <stddef.h>

#include <algorithm>
#include <vector>

#include "absl/log/log.h"
#include "absl/strings/str_format.h"
#include "gtest/gtest.h"

#include <grpc/grpc.h>
#include <grpc/impl/channel_arg_names.h>
#include <grpc/status.h>

#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/slice/slice.h"
#include "test/core/end2end/end2end_tests.h"

namespace grpc_core {
namespace {

const int kNumCalls = 8;
const int kClientBaseTag = 1000;
const int kServerStartBaseTag = 2000;
const int kServerRecvBaseTag = 3000;
const int kServerEndBaseTag = 4000;

template <typename F>
auto MakeVec(F init) {
  std::vector<decltype(init(0))> v;
  v.reserve(kNumCalls);
  for (int i = 0; i < kNumCalls; ++i) {
    v.push_back(init(i));
  }
  return v;
}

CORE_END2END_TEST(ResourceQuotaTest, ResourceQuota) {
  if (IsEventEngineListenerEnabled()) {
    GTEST_SKIP() << "Not with event engine listener";
  }

  grpc_resource_quota* resource_quota =
      grpc_resource_quota_create("test_server");
  grpc_resource_quota_resize(resource_quota, 1024 * 1024);
  InitServer(ChannelArgs().Set(
      GRPC_ARG_RESOURCE_QUOTA,
      ChannelArgs::Pointer(resource_quota, grpc_resource_quota_arg_vtable())));
  InitClient(ChannelArgs());
  // Create large request and response bodies. These are big enough to require
  // multiple round trips to deliver to the peer, and their exact contents of
  // will be verified on completion.
  auto requests = MakeVec([](int) { return RandomSlice(128 * 1024); });
  auto server_calls =
      MakeVec([this](int i) { return RequestCall(kServerRecvBaseTag + i); });
  IncomingMetadata server_metadata[kNumCalls];
  IncomingStatusOnClient server_status[kNumCalls];
  IncomingMessage client_message[kNumCalls];
  IncomingCloseOnServer client_close[kNumCalls];
  enum class SeenServerCall {
    kNotSeen = 0,
    kSeenWithSuccess,
    kSeenWithFailure
  };
  // Yep, this really initializes all the elements.
  SeenServerCall seen_server_call[kNumCalls] = {SeenServerCall::kNotSeen};
  auto client_calls =
      MakeVec([this, &requests, &server_metadata, &server_status](int i) {
        auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
        c.NewBatch(kClientBaseTag + i)
            .SendInitialMetadata({}, GRPC_INITIAL_METADATA_WAIT_FOR_READY)
            .SendMessage(requests[i].Ref())
            .SendCloseFromClient()
            .RecvInitialMetadata(server_metadata[i])
            .RecvStatusOnClient(server_status[i]);
        return c;
      });
  for (int i = 0; i < kNumCalls; i++) {
    Expect(kClientBaseTag + i, true);
    Expect(
        kServerRecvBaseTag + i,
        MaybePerformAction{[this, &seen_server_call, &server_calls,
                            &client_message, &client_close, i](bool success) {
          seen_server_call[i] = success ? SeenServerCall::kSeenWithSuccess
                                        : SeenServerCall::kSeenWithFailure;
          if (!success) return;
          server_calls[i]
              .NewBatch(kServerStartBaseTag + i)
              .RecvMessage(client_message[i])
              .SendInitialMetadata({});
          Expect(kServerStartBaseTag + i,
                 PerformAction{[&server_calls, &client_close, i](bool) {
                   server_calls[i]
                       .NewBatch(kServerEndBaseTag + i)
                       .RecvCloseOnServer(client_close[i])
                       .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
                 }});
          Expect(kServerEndBaseTag + i, true);
        }});
  }
  Step();

  int cancelled_calls_on_client = 0;
  int cancelled_calls_on_server = 0;
  int deadline_exceeded = 0;
  int unavailable = 0;
  for (int i = 0; i < kNumCalls; i++) {
    switch (server_status[i].status()) {
      case GRPC_STATUS_RESOURCE_EXHAUSTED:
        cancelled_calls_on_client++;
        break;
      case GRPC_STATUS_DEADLINE_EXCEEDED:
        deadline_exceeded++;
        break;
      case GRPC_STATUS_UNAVAILABLE:
        unavailable++;
        break;
      case GRPC_STATUS_OK:
        break;
      default:
        Crash(absl::StrFormat("Unexpected status code: %d",
                              server_status[i].status()));
    }
    if (seen_server_call[i] == SeenServerCall::kSeenWithSuccess &&
        client_close[i].was_cancelled()) {
      cancelled_calls_on_server++;
    }
  }
  LOG(INFO) << "Done. " << kNumCalls
            << " total calls: " << cancelled_calls_on_server
            << " cancelled at server, " << cancelled_calls_on_client
            << " cancelled at client, " << deadline_exceeded << " timed out, "
            << unavailable << " unavailable.";

  ShutdownServerAndNotify(0);
  Expect(0, PerformAction{[this](bool success) {
           EXPECT_TRUE(success);
           DestroyServer();
         }});
  for (size_t i = 0; i < kNumCalls; i++) {
    if (seen_server_call[i] == SeenServerCall::kNotSeen) {
      Expect(kServerRecvBaseTag + i, false);
    }
  }
  Step();
}

}  // namespace
}  // namespace grpc_core
