chromium/chromeos/ash/components/boca/babelorca/token_manager_impl_unittest.cc

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/boca/babelorca/token_manager_impl.h"

#include <memory>
#include <optional>
#include <utility>

#include "base/test/simple_test_clock.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "chromeos/ash/components/boca/babelorca/fakes/fake_token_fetcher.h"
#include "chromeos/ash/components/boca/babelorca/token_data_wrapper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash::babelorca {
namespace {

constexpr char kOAuthToken[] = "test-token";

TEST(TokenManagerImplTest, TokenInitiallyEmpty) {
  TokenManagerImpl token_manager(std::make_unique<FakeTokenFetcher>());

  EXPECT_THAT(token_manager.GetTokenString(), testing::IsNull());
  EXPECT_EQ(token_manager.GetFetchedVersion(), 0);
}

TEST(TokenManagerImplTest, RepsondOnFetchAndStoreToken) {
  auto token_fetcher = std::make_unique<FakeTokenFetcher>();
  auto* token_fetcher_ptr = token_fetcher.get();
  base::SimpleTestClock test_clock;
  test_clock.SetNow(base::Time::Now());
  TokenManagerImpl token_manager(std::move(token_fetcher), base::Seconds(5),
                                 &test_clock);
  base::test::TestFuture<bool> test_future;

  token_manager.ForceFetchToken(test_future.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::make_optional(
      TokenDataWrapper(kOAuthToken, test_clock.Now() + base::Seconds(10))));
  test_clock.Advance(base::Seconds(4));

  EXPECT_TRUE(test_future.Get());
  ASSERT_THAT(token_manager.GetTokenString(), testing::NotNull());
  EXPECT_THAT(*(token_manager.GetTokenString()), testing::StrEq(kOAuthToken));
  EXPECT_EQ(token_manager.GetFetchedVersion(), 1);
}

TEST(TokenManagerImplTest, ReturnNullIfTokenExpired) {
  auto token_fetcher = std::make_unique<FakeTokenFetcher>();
  auto* token_fetcher_ptr = token_fetcher.get();
  base::SimpleTestClock test_clock;
  test_clock.SetNow(base::Time::Now());
  TokenManagerImpl token_manager(std::move(token_fetcher), base::Seconds(5),
                                 &test_clock);
  base::test::TestFuture<bool> test_future;

  token_manager.ForceFetchToken(test_future.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::make_optional(
      TokenDataWrapper(kOAuthToken, test_clock.Now() + base::Seconds(10))));
  test_clock.Advance(base::Seconds(6));

  EXPECT_TRUE(test_future.Get());
  EXPECT_THAT(token_manager.GetTokenString(), testing::IsNull());
  EXPECT_EQ(token_manager.GetFetchedVersion(), 1);
}

TEST(TokenManagerImplTest, QueueRequestsUntilFetchIsComplete) {
  auto token_fetcher = std::make_unique<FakeTokenFetcher>();
  auto* token_fetcher_ptr = token_fetcher.get();
  base::SimpleTestClock test_clock;
  test_clock.SetNow(base::Time::Now());
  TokenManagerImpl token_manager(std::move(token_fetcher), base::Seconds(5),
                                 &test_clock);
  base::test::TestFuture<bool> test_future1;
  base::test::TestFuture<bool> test_future2;

  token_manager.ForceFetchToken(test_future1.GetCallback());
  token_manager.ForceFetchToken(test_future2.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::make_optional(
      TokenDataWrapper(kOAuthToken, test_clock.Now() + base::Seconds(10))));

  EXPECT_TRUE(test_future1.Get());
  EXPECT_TRUE(test_future2.Get());
  ASSERT_THAT(token_manager.GetTokenString(), testing::NotNull());
  EXPECT_THAT(*(token_manager.GetTokenString()), testing::StrEq(kOAuthToken));
  EXPECT_EQ(token_manager.GetFetchedVersion(), 1);
}

TEST(TokenManagerImplTest, RespondWithFalseOnFetchFailure) {
  auto token_fetcher = std::make_unique<FakeTokenFetcher>();
  auto* token_fetcher_ptr = token_fetcher.get();
  TokenManagerImpl token_manager(std::move(token_fetcher));
  base::test::TestFuture<bool> test_future;

  token_manager.ForceFetchToken(test_future.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::nullopt);

  EXPECT_FALSE(test_future.Get());
}

TEST(TokenManagerImplTest, IncrementVersionOnNewTokenFetch) {
  auto token_fetcher = std::make_unique<FakeTokenFetcher>();
  auto* token_fetcher_ptr = token_fetcher.get();
  base::SimpleTestClock test_clock;
  test_clock.SetNow(base::Time::Now());
  TokenManagerImpl token_manager(std::move(token_fetcher), base::Seconds(5),
                                 &test_clock);
  base::test::TestFuture<bool> test_future1;
  base::test::TestFuture<bool> test_future2;

  token_manager.ForceFetchToken(test_future1.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::make_optional(
      TokenDataWrapper(kOAuthToken, test_clock.Now() + base::Seconds(10))));
  token_manager.ForceFetchToken(test_future2.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::make_optional(
      TokenDataWrapper(kOAuthToken, test_clock.Now() + base::Seconds(10))));

  EXPECT_TRUE(test_future1.Get());
  EXPECT_TRUE(test_future2.Get());
  ASSERT_THAT(token_manager.GetTokenString(), testing::NotNull());
  EXPECT_THAT(*(token_manager.GetTokenString()), testing::StrEq(kOAuthToken));
  EXPECT_EQ(token_manager.GetFetchedVersion(), 2);
}

TEST(TokenManagerImplTest, DoesNotOverwriteTokenOnFailure) {
  auto token_fetcher = std::make_unique<FakeTokenFetcher>();
  auto* token_fetcher_ptr = token_fetcher.get();
  base::SimpleTestClock test_clock;
  test_clock.SetNow(base::Time::Now());
  TokenManagerImpl token_manager(std::move(token_fetcher), base::Seconds(5),
                                 &test_clock);
  base::test::TestFuture<bool> success_future;
  base::test::TestFuture<bool> fail_future;

  // Success.
  token_manager.ForceFetchToken(success_future.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::make_optional(
      TokenDataWrapper(kOAuthToken, test_clock.Now() + base::Seconds(10))));
  // Failure.
  token_manager.ForceFetchToken(fail_future.GetCallback());
  token_fetcher_ptr->RespondToFetchRequest(std::nullopt);

  EXPECT_TRUE(success_future.Get());
  EXPECT_FALSE(fail_future.Get());
  ASSERT_THAT(token_manager.GetTokenString(), testing::NotNull());
  EXPECT_THAT(*(token_manager.GetTokenString()), testing::StrEq(kOAuthToken));
  EXPECT_EQ(token_manager.GetFetchedVersion(), 1);
}

}  // namespace
}  // namespace ash::babelorca