// Copyright (c) 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/blind_sign_auth/cached_blind_sign_auth.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "quiche/blind_sign_auth/blind_sign_auth_interface.h"
#include "quiche/blind_sign_auth/test_tools/mock_blind_sign_auth_interface.h"
#include "quiche/common/platform/api/quiche_mutex.h"
#include "quiche/common/platform/api/quiche_test.h"
#include "quiche/common/test_tools/quiche_test_utils.h"

namespace quiche {
namespace test {
namespace {

using ::testing::_;
using ::testing::InvokeArgument;
using ::testing::Unused;

class CachedBlindSignAuthTest : public QuicheTest {
 protected:
  void SetUp() override {
    cached_blind_sign_auth_ =
        std::make_unique<CachedBlindSignAuth>(&mock_blind_sign_auth_interface_);
  }

  void TearDown() override {
    fake_tokens_.clear();
    cached_blind_sign_auth_.reset();
  }

 public:
  std::vector<BlindSignToken> MakeFakeTokens(int num_tokens) {
    std::vector<BlindSignToken> fake_tokens;
    for (int i = 0; i < kBlindSignAuthRequestMaxTokens; i++) {
      fake_tokens.push_back(BlindSignToken{absl::StrCat("token:", i),
                                           absl::Now() + absl::Hours(1)});
    }
    return fake_tokens;
  }

  std::vector<BlindSignToken> MakeExpiredTokens(int num_tokens) {
    std::vector<BlindSignToken> fake_tokens;
    for (int i = 0; i < kBlindSignAuthRequestMaxTokens; i++) {
      fake_tokens.push_back(BlindSignToken{absl::StrCat("token:", i),
                                           absl::Now() - absl::Hours(1)});
    }
    return fake_tokens;
  }

  MockBlindSignAuthInterface mock_blind_sign_auth_interface_;
  std::unique_ptr<CachedBlindSignAuth> cached_blind_sign_auth_;
  std::optional<std::string> oauth_token_ = "oauth_token";
  std::vector<BlindSignToken> fake_tokens_;
};

TEST_F(CachedBlindSignAuthTest, TestGetTokensOneCallSuccessful) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(1)
      .WillOnce(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeFakeTokens(num_tokens);
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = 5;
  QuicheNotification done;
  SignedTokenCallback callback =
      [num_tokens, &done](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        for (int i = 0; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token, absl::StrCat("token:", i));
        }
        done.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA, std::move(callback));
  done.WaitForNotification();
}

TEST_F(CachedBlindSignAuthTest, TestGetTokensMultipleRemoteCallsSuccessful) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(2)
      .WillRepeatedly(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeFakeTokens(num_tokens);
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = kBlindSignAuthRequestMaxTokens - 1;
  QuicheNotification first;
  SignedTokenCallback first_callback =
      [num_tokens, &first](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        for (int i = 0; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token, absl::StrCat("token:", i));
        }
        first.Notify();
      };

  cached_blind_sign_auth_->GetTokens(
      oauth_token_, num_tokens, ProxyLayer::kProxyA, std::move(first_callback));
  first.WaitForNotification();

  QuicheNotification second;
  SignedTokenCallback second_callback =
      [num_tokens, &second](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        EXPECT_EQ(tokens->at(0).token,
                  absl::StrCat("token:", kBlindSignAuthRequestMaxTokens - 1));
        for (int i = 1; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token, absl::StrCat("token:", i - 1));
        }
        second.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA,
                                     std::move(second_callback));
  second.WaitForNotification();
}

TEST_F(CachedBlindSignAuthTest, TestGetTokensSecondRequestFilledFromCache) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(1)
      .WillOnce(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeFakeTokens(num_tokens);
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = kBlindSignAuthRequestMaxTokens / 2;
  QuicheNotification first;
  SignedTokenCallback first_callback =
      [num_tokens, &first](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        for (int i = 0; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token, absl::StrCat("token:", i));
        }
        first.Notify();
      };

  cached_blind_sign_auth_->GetTokens(
      oauth_token_, num_tokens, ProxyLayer::kProxyA, std::move(first_callback));
  first.WaitForNotification();

  QuicheNotification second;
  SignedTokenCallback second_callback =
      [num_tokens, &second](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        for (int i = 0; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token,
                    absl::StrCat("token:", i + num_tokens));
        }
        second.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA,
                                     std::move(second_callback));
  second.WaitForNotification();
}

TEST_F(CachedBlindSignAuthTest, TestGetTokensThirdRequestRefillsCache) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(2)
      .WillRepeatedly(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeFakeTokens(num_tokens);
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = kBlindSignAuthRequestMaxTokens / 2;
  QuicheNotification first;
  SignedTokenCallback first_callback =
      [num_tokens, &first](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        for (int i = 0; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token, absl::StrCat("token:", i));
        }
        first.Notify();
      };

  cached_blind_sign_auth_->GetTokens(
      oauth_token_, num_tokens, ProxyLayer::kProxyA, std::move(first_callback));
  first.WaitForNotification();

  QuicheNotification second;
  SignedTokenCallback second_callback =
      [num_tokens, &second](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(num_tokens, tokens->size());
        for (int i = 0; i < num_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token,
                    absl::StrCat("token:", i + num_tokens));
        }
        second.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA,
                                     std::move(second_callback));
  second.WaitForNotification();

  QuicheNotification third;
  int third_request_tokens = 10;
  SignedTokenCallback third_callback =
      [third_request_tokens,
       &third](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(third_request_tokens, tokens->size());
        for (int i = 0; i < third_request_tokens; i++) {
          EXPECT_EQ(tokens->at(i).token, absl::StrCat("token:", i));
        }
        third.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, third_request_tokens,
                                     ProxyLayer::kProxyA,
                                     std::move(third_callback));
  third.WaitForNotification();
}

TEST_F(CachedBlindSignAuthTest, TestGetTokensRequestTooLarge) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(0);

  int num_tokens = kBlindSignAuthRequestMaxTokens + 1;
  SignedTokenCallback callback =
      [](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(), absl::StatusCode::kInvalidArgument);
        EXPECT_THAT(
            tokens.status().message(),
            absl::StrFormat("Number of tokens requested exceeds maximum: %d",
                            kBlindSignAuthRequestMaxTokens));
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA, std::move(callback));
}

TEST_F(CachedBlindSignAuthTest, TestGetTokensRequestNegative) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(0);

  int num_tokens = -1;
  SignedTokenCallback callback =
      [num_tokens](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(), absl::StatusCode::kInvalidArgument);
        EXPECT_THAT(tokens.status().message(),
                    absl::StrFormat("Negative number of tokens requested: %d",
                                    num_tokens));
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA, std::move(callback));
}

TEST_F(CachedBlindSignAuthTest, TestHandleGetTokensResponseErrorHandling) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(2)
      .WillOnce(
          [](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            std::move(callback)(absl::InternalError("AuthAndSign failed"));
          })
      .WillOnce(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeFakeTokens(num_tokens);
            fake_tokens_.pop_back();
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = kBlindSignAuthRequestMaxTokens;
  QuicheNotification first;
  SignedTokenCallback first_callback =
      [&first](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(), absl::StatusCode::kInternal);
        EXPECT_THAT(tokens.status().message(), "AuthAndSign failed");
        first.Notify();
      };

  cached_blind_sign_auth_->GetTokens(
      oauth_token_, num_tokens, ProxyLayer::kProxyA, std::move(first_callback));
  first.WaitForNotification();

  QuicheNotification second;
  SignedTokenCallback second_callback =
      [&second](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(),
                    absl::StatusCode::kResourceExhausted);
        second.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA,
                                     std::move(second_callback));
  second.WaitForNotification();
}

TEST_F(CachedBlindSignAuthTest, TestGetTokensZeroTokensRequested) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(0);

  int num_tokens = 0;
  SignedTokenCallback callback =
      [](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        QUICHE_EXPECT_OK(tokens);
        EXPECT_EQ(tokens->size(), 0);
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA, std::move(callback));
}

TEST_F(CachedBlindSignAuthTest, TestExpiredTokensArePruned) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(1)
      .WillOnce(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeExpiredTokens(num_tokens);
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = kBlindSignAuthRequestMaxTokens;
  QuicheNotification first;
  SignedTokenCallback first_callback =
      [&first](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(),
                    absl::StatusCode::kResourceExhausted);
        first.Notify();
      };

  cached_blind_sign_auth_->GetTokens(
      oauth_token_, num_tokens, ProxyLayer::kProxyA, std::move(first_callback));
  first.WaitForNotification();
}

TEST_F(CachedBlindSignAuthTest, TestClearCacheRemovesTokens) {
  EXPECT_CALL(mock_blind_sign_auth_interface_,
              GetTokens(oauth_token_, kBlindSignAuthRequestMaxTokens, _, _))
      .Times(2)
      .WillRepeatedly(
          [this](Unused, int num_tokens, Unused, SignedTokenCallback callback) {
            fake_tokens_ = MakeExpiredTokens(num_tokens);
            std::move(callback)(absl::MakeSpan(fake_tokens_));
          });

  int num_tokens = kBlindSignAuthRequestMaxTokens / 2;
  QuicheNotification first;
  SignedTokenCallback first_callback =
      [&first](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(),
                    absl::StatusCode::kResourceExhausted);
        first.Notify();
      };

  cached_blind_sign_auth_->GetTokens(
      oauth_token_, num_tokens, ProxyLayer::kProxyA, std::move(first_callback));
  first.WaitForNotification();

  cached_blind_sign_auth_->ClearCache();

  QuicheNotification second;
  SignedTokenCallback second_callback =
      [&second](absl::StatusOr<absl::Span<BlindSignToken>> tokens) {
        EXPECT_THAT(tokens.status().code(),
                    absl::StatusCode::kResourceExhausted);
        second.Notify();
      };

  cached_blind_sign_auth_->GetTokens(oauth_token_, num_tokens,
                                     ProxyLayer::kProxyA,
                                     std::move(second_callback));
  second.WaitForNotification();
}

}  // namespace
}  // namespace test
}  // namespace quiche
