// Copyright 2017 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 "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "services/identity/identity_service.h"
#include "services/identity/public/cpp/account_state.h"
#include "services/identity/public/cpp/scope_set.h"
#include "services/identity/public/mojom/constants.mojom.h"
#include "services/identity/public/mojom/identity_manager.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace identity {
namespace {

#if defined(OS_CHROMEOS)
using SigninManagerForTest = FakeSigninManagerBase;
#else
using SigninManagerForTest = FakeSigninManager;
#endif  // OS_CHROMEOS

const char kTestGaiaId[] = "dummyId";
const char kTestEmail[] = "me@dummy.com";
const char kSecondaryTestGaiaId[] = "secondaryDummyId";
const char kSecondaryTestEmail[] = "metoo@dummy.com";
const char kTestRefreshToken[] = "dummy-refresh-token";
const char kTestAccessToken[] = "access_token";

class IdentityManagerImplTest : public testing::Test {
 public:
  IdentityManagerImplTest()
      : signin_client_(&pref_service_),
        token_service_(&pref_service_),
#if defined(OS_CHROMEOS)
        signin_manager_(&signin_client_, &account_tracker_),
#else
        signin_manager_(&signin_client_,
                        &token_service_,
                        &account_tracker_,
                        nullptr),
#endif
        service_(
            &account_tracker_,
            &signin_manager_,
            &token_service_,
            test_connector_factory_.RegisterInstance(mojom::kServiceName)) {
    AccountTrackerService::RegisterPrefs(pref_service_.registry());
    ProfileOAuth2TokenService::RegisterProfilePrefs(pref_service_.registry());
    SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
    SigninManagerBase::RegisterPrefs(pref_service_.registry());

    account_tracker_.Initialize(&pref_service_, base::FilePath());
  }

  void TearDown() override {
    // Shut down the SigninManager so that the IdentityManagerImpl doesn't end
    // up outliving it.
    signin_manager_.Shutdown();
  }

  void OnReceivedPrimaryAccountInfo(
      base::RepeatingClosure quit_closure,
      const base::Optional<AccountInfo>& account_info,
      const AccountState& account_state) {
    primary_account_info_ = account_info;
    primary_account_state_ = account_state;
    quit_closure.Run();
  }

  void OnPrimaryAccountAvailable(base::RepeatingClosure quit_closure,
                                 AccountInfo* caller_account_info,
                                 AccountState* caller_account_state,
                                 const AccountInfo& account_info,
                                 const AccountState& account_state) {
    *caller_account_info = account_info;
    *caller_account_state = account_state;
    quit_closure.Run();
  }

  void OnReceivedAccountInfoFromGaiaId(
      base::RepeatingClosure quit_closure,
      const base::Optional<AccountInfo>& account_info,
      const AccountState& account_state) {
    account_info_from_gaia_id_ = account_info;
    account_state_from_gaia_id_ = account_state;
    quit_closure.Run();
  }

  void OnGotAccounts(base::RepeatingClosure quit_closure,
                     std::vector<mojom::AccountPtr>* output,
                     std::vector<mojom::AccountPtr> accounts) {
    *output = std::move(accounts);
    quit_closure.Run();
  }

  void OnReceivedAccessToken(base::RepeatingClosure quit_closure,
                             const base::Optional<std::string>& access_token,
                             base::Time expiration_time,
                             const GoogleServiceAuthError& error) {
    access_token_ = access_token;
    access_token_error_ = error;
    quit_closure.Run();
  }

 protected:
  mojom::IdentityManager* GetIdentityManagerImpl() {
    if (!identity_manager_) {
      test_connector_factory_.GetDefaultConnector()->BindInterface(
          mojom::kServiceName, &identity_manager_);
    }
    return identity_manager_.get();
  }

  void ResetIdentityManagerImpl() { identity_manager_.reset(); }

  void FlushIdentityManagerImplForTesting() {
    GetIdentityManagerImpl();
    identity_manager_.FlushForTesting();
  }

  void SetIdentityManagerImplConnectionErrorHandler(
      base::RepeatingClosure handler) {
    GetIdentityManagerImpl();
    identity_manager_.set_connection_error_handler(handler);
  }

  base::test::ScopedTaskEnvironment task_environemnt_;

  mojom::IdentityManagerPtr identity_manager_;
  base::Optional<AccountInfo> primary_account_info_;
  AccountState primary_account_state_;
  base::Optional<AccountInfo> account_info_from_gaia_id_;
  AccountState account_state_from_gaia_id_;
  base::Optional<std::string> access_token_;
  GoogleServiceAuthError access_token_error_;

  AccountTrackerService* account_tracker() { return &account_tracker_; }
  SigninManagerBase* signin_manager() { return &signin_manager_; }
  FakeProfileOAuth2TokenService* token_service() { return &token_service_; }

 private:
  sync_preferences::TestingPrefServiceSyncable pref_service_;
  AccountTrackerService account_tracker_;
  TestSigninClient signin_client_;
  FakeProfileOAuth2TokenService token_service_;
  SigninManagerForTest signin_manager_;

  service_manager::TestConnectorFactory test_connector_factory_;
  IdentityService service_;

  DISALLOW_COPY_AND_ASSIGN(IdentityManagerImplTest);
};

// Tests that it is not possible to connect to the Identity Manager if
// initiated after SigninManager shutdown.
TEST_F(IdentityManagerImplTest, SigninManagerShutdownBeforeConnection) {
  AccountInfo sentinel;
  sentinel.account_id = "sentinel";
  primary_account_info_ = sentinel;

  // Ensure that the Identity Service has actually been created before
  // invoking SigninManagerBase::Shutdown(), since otherwise this test will
  // spin forever. Then reset the Identity Manager so that the next request
  // makes a fresh connection.
  FlushIdentityManagerImplForTesting();
  ResetIdentityManagerImpl();

  // Make a call to connect to the IdentityManagerImpl *after* SigninManager
  // shutdown; it should get notified of an error when the Identity Service
  // drops the connection.
  signin_manager()->Shutdown();
  base::RunLoop run_loop;
  SetIdentityManagerImplConnectionErrorHandler(run_loop.QuitClosure());

  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();

  // Verify that the callback to GetPrimaryAccountInfo() was not invoked.
  EXPECT_TRUE(primary_account_info_);
  EXPECT_EQ("sentinel", primary_account_info_->account_id);
}

// Tests that the Identity Manager destroys itself on SigninManager shutdown.
TEST_F(IdentityManagerImplTest, SigninManagerShutdownAfterConnection) {
  base::RunLoop run_loop;
  SetIdentityManagerImplConnectionErrorHandler(run_loop.QuitClosure());

  // Ensure that the IdentityManagerImpl instance has actually been created
  // before invoking SigninManagerBase::Shutdown(), since otherwise this test
  // will spin forever.
  FlushIdentityManagerImplForTesting();
  signin_manager()->Shutdown();
  run_loop.Run();
}

// Tests that the Identity Manager properly handles its own destruction in the
// case where there is an active consumer request (i.e., a pending callback from
// a Mojo call). In particular, this flow should not cause a DCHECK to fire in
// debug mode.
TEST_F(IdentityManagerImplTest, IdentityManagerImplShutdownWithActiveRequest) {
  base::RunLoop run_loop;
  SetIdentityManagerImplConnectionErrorHandler(run_loop.QuitClosure());

  // Call a method on the IdentityManagerImpl that will cause it to store a
  // pending callback. This callback will never be invoked, so just pass dummy
  // arguments to it.
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), base::RepeatingClosure(), nullptr, nullptr));

  // Ensure that the IdentityManagerImpl has received the above call before
  // invoking SigninManagerBase::Shutdown(), as otherwise this test is
  // pointless.
  FlushIdentityManagerImplForTesting();

  // This flow is what would cause a DCHECK to fire if IdentityManagerImpl is
  // not properly closing its binding on shutdown.
  signin_manager()->Shutdown();
  run_loop.Run();
}

// Check that the primary account info is null if not signed in.
TEST_F(IdentityManagerImplTest, GetPrimaryAccountInfoNotSignedIn) {
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_FALSE(primary_account_info_);
}

// Check that the primary account info has expected values if signed in without
// a refresh token available.
TEST_F(IdentityManagerImplTest, GetPrimaryAccountInfoSignedInNoRefreshToken) {
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_TRUE(primary_account_info_);
  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            primary_account_info_->account_id);
  EXPECT_EQ(kTestGaiaId, primary_account_info_->gaia);
  EXPECT_EQ(kTestEmail, primary_account_info_->email);
  EXPECT_FALSE(primary_account_state_.has_refresh_token);
  EXPECT_TRUE(primary_account_state_.is_primary_account);
}

// Check that the primary account info has expected values if signed in with a
// refresh token available.
TEST_F(IdentityManagerImplTest, GetPrimaryAccountInfoSignedInRefreshToken) {
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_TRUE(primary_account_info_);
  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            primary_account_info_->account_id);
  EXPECT_EQ(kTestGaiaId, primary_account_info_->gaia);
  EXPECT_EQ(kTestEmail, primary_account_info_->email);
  EXPECT_TRUE(primary_account_state_.has_refresh_token);
  EXPECT_TRUE(primary_account_state_.is_primary_account);
}

// Check that GetPrimaryAccountWhenAvailable() returns immediately in the
// case where the primary account is available when the call is received.
TEST_F(IdentityManagerImplTest, GetPrimaryAccountWhenAvailableSignedIn) {
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);

  AccountInfo account_info;
  AccountState account_state;
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop.QuitClosure(),
      base::Unretained(&account_info), base::Unretained(&account_state)));
  run_loop.Run();

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info.account_id);
  EXPECT_EQ(kTestGaiaId, account_info.gaia);
  EXPECT_EQ(kTestEmail, account_info.email);
  EXPECT_TRUE(account_state.has_refresh_token);
  EXPECT_TRUE(account_state.is_primary_account);
}

// Check that GetPrimaryAccountWhenAvailable() returns the expected account
// info in the case where the primary account is made available *after* the
// call is received.
TEST_F(IdentityManagerImplTest, GetPrimaryAccountWhenAvailableSignInLater) {
  AccountInfo account_info;
  AccountState account_state;

  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop.QuitClosure(),
      base::Unretained(&account_info), base::Unretained(&account_state)));

  // Verify that the primary account info is not currently available (this also
  // serves to ensure that the preceding call has been received by the Identity
  // Manager before proceeding).
  base::RunLoop run_loop2;
  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop2.QuitClosure()));
  run_loop2.Run();
  EXPECT_FALSE(primary_account_info_);

  // Make the primary account available and check that the callback is invoked
  // as expected.
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
  run_loop.Run();

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info.account_id);
  EXPECT_EQ(kTestGaiaId, account_info.gaia);
  EXPECT_EQ(kTestEmail, account_info.email);
  EXPECT_TRUE(account_state.has_refresh_token);
  EXPECT_TRUE(account_state.is_primary_account);
}

// Check that GetPrimaryAccountWhenAvailable() returns the expected account
// info in the case where signin is done before the call is received but the
// refresh token is made available only *after* the call is received.
TEST_F(IdentityManagerImplTest,
       GetPrimaryAccountWhenAvailableTokenAvailableLater) {
  AccountInfo account_info;
  AccountState account_state;

  // Sign in, but don't set the refresh token yet.
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop.QuitClosure(),
      base::Unretained(&account_info), base::Unretained(&account_state)));

  // Verify that the primary account info is present, but that the primary
  // account is not yet considered available (this also
  // serves to ensure that the preceding call has been received by the Identity
  // Manager before proceeding).
  base::RunLoop run_loop2;
  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop2.QuitClosure()));
  run_loop2.Run();

  EXPECT_TRUE(primary_account_info_);
  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            primary_account_info_->account_id);
  EXPECT_TRUE(account_info.account_id.empty());

  // Set the refresh token and check that the callback is invoked as expected
  // (i.e., the primary account is now considered available).
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
  run_loop.Run();

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info.account_id);
  EXPECT_EQ(kTestGaiaId, account_info.gaia);
  EXPECT_EQ(kTestEmail, account_info.email);
  EXPECT_TRUE(account_state.has_refresh_token);
  EXPECT_TRUE(account_state.is_primary_account);
}

// Check that GetPrimaryAccountWhenAvailable() returns the expected account info
// in the case where the token is available before the call is received but the
// account is made authenticated only *after* the call is received. This test is
// relevant only on non-ChromeOS platforms, as the flow being tested here is not
// possible on ChromeOS.
#if !defined(OS_CHROMEOS)
TEST_F(IdentityManagerImplTest,
       GetPrimaryAccountWhenAvailableAuthenticationAvailableLater) {
  AccountInfo account_info;
  AccountState account_state;

  // Set the refresh token, but don't sign in yet.
  std::string account_id_to_use =
      account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(account_id_to_use, kTestRefreshToken);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop.QuitClosure(),
      base::Unretained(&account_info), base::Unretained(&account_state)));

  // Verify that the account is present and has a refresh token, but that the
  // primary account is not yet considered available (this also serves to ensure
  // that the preceding call has been received by the Identity Manager before
  // proceeding).
  base::RunLoop run_loop2;
  GetIdentityManagerImpl()->GetAccountInfoFromGaiaId(
      kTestGaiaId,
      base::BindRepeating(
          &IdentityManagerImplTest::OnReceivedAccountInfoFromGaiaId,
          base::Unretained(this), run_loop2.QuitClosure()));
  run_loop2.Run();

  EXPECT_TRUE(account_info_from_gaia_id_);
  EXPECT_EQ(account_id_to_use, account_info_from_gaia_id_->account_id);
  EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia);
  EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email);
  EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token);
  EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account);

  EXPECT_TRUE(account_info.account_id.empty());

  // Sign the user in and check that the callback is invoked as expected (i.e.,
  // the primary account is now considered available). Note that it is necessary
  // to call SignIn() here to ensure that GoogleSigninSucceeded() is fired by
  // the fake signin manager.
  static_cast<FakeSigninManager*>(signin_manager())
      ->SignIn(kTestGaiaId, kTestEmail, "password");

  run_loop.Run();

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info.account_id);
  EXPECT_EQ(kTestGaiaId, account_info.gaia);
  EXPECT_EQ(kTestEmail, account_info.email);
  EXPECT_TRUE(account_state.has_refresh_token);
  EXPECT_TRUE(account_state.is_primary_account);
}
#endif

// Check that GetPrimaryAccountWhenAvailable() returns the expected account
// info to all callers in the case where the primary account is made available
// after multiple overlapping calls have been received.
TEST_F(IdentityManagerImplTest,
       GetPrimaryAccountWhenAvailableOverlappingCalls) {
  AccountInfo account_info1;
  AccountState account_state1;
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop.QuitClosure(),
      base::Unretained(&account_info1), base::Unretained(&account_state1)));

  AccountInfo account_info2;
  AccountState account_state2;
  base::RunLoop run_loop2;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop2.QuitClosure(),
      base::Unretained(&account_info2), base::Unretained(&account_state2)));

  // Verify that the primary account info is not currently available (this also
  // serves to ensure that the preceding call has been received by the Identity
  // Manager before proceeding).
  base::RunLoop run_loop3;
  GetIdentityManagerImpl()->GetPrimaryAccountInfo(base::BindRepeating(
      &IdentityManagerImplTest::OnReceivedPrimaryAccountInfo,
      base::Unretained(this), run_loop3.QuitClosure()));
  run_loop3.Run();
  EXPECT_FALSE(primary_account_info_);

  // Make the primary account available and check that the callbacks are invoked
  // as expected.
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
  run_loop.Run();
  run_loop2.Run();

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info1.account_id);
  EXPECT_EQ(kTestGaiaId, account_info1.gaia);
  EXPECT_EQ(kTestEmail, account_info1.email);
  EXPECT_TRUE(account_state1.has_refresh_token);
  EXPECT_TRUE(account_state1.is_primary_account);

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info2.account_id);
  EXPECT_EQ(kTestGaiaId, account_info2.gaia);
  EXPECT_EQ(kTestEmail, account_info2.email);
  EXPECT_TRUE(account_state2.has_refresh_token);
  EXPECT_TRUE(account_state2.is_primary_account);
}

// Check that GetPrimaryAccountWhenAvailable() doesn't return the account as
// available if the refresh token has an auth error.
TEST_F(IdentityManagerImplTest,
       GetPrimaryAccountWhenAvailableRefreshTokenHasAuthError) {
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
  token_service()->UpdateAuthErrorForTesting(
      signin_manager()->GetAuthenticatedAccountId(),
      GoogleServiceAuthError(
          GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));

  AccountInfo account_info;
  AccountState account_state;
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating(
      &IdentityManagerImplTest::OnPrimaryAccountAvailable,
      base::Unretained(this), run_loop.QuitClosure(),
      base::Unretained(&account_info), base::Unretained(&account_state)));

  // Flush the Identity Manager and check that the callback didn't fire.
  FlushIdentityManagerImplForTesting();
  EXPECT_TRUE(account_info.account_id.empty());

  // Clear the auth error, update credentials, and check that the callback
  // fires.
  token_service()->UpdateAuthErrorForTesting(
      signin_manager()->GetAuthenticatedAccountId(), GoogleServiceAuthError());
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
  run_loop.Run();

  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            account_info.account_id);
  EXPECT_EQ(kTestGaiaId, account_info.gaia);
  EXPECT_EQ(kTestEmail, account_info.email);
  EXPECT_TRUE(account_state.has_refresh_token);
  EXPECT_TRUE(account_state.is_primary_account);
}

// Check that the account info for a given GAIA ID is null if that GAIA ID is
// unknown.
TEST_F(IdentityManagerImplTest, GetAccountInfoForUnknownGaiaID) {
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccountInfoFromGaiaId(
      kTestGaiaId,
      base::BindRepeating(
          &IdentityManagerImplTest::OnReceivedAccountInfoFromGaiaId,
          base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_FALSE(account_info_from_gaia_id_);
}

// Check that the account info for a given GAIA ID has expected values if that
// GAIA ID is known and there is no refresh token available for it.
TEST_F(IdentityManagerImplTest, GetAccountInfoForKnownGaiaIdNoRefreshToken) {
  std::string account_id =
      account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccountInfoFromGaiaId(
      kTestGaiaId,
      base::BindRepeating(
          &IdentityManagerImplTest::OnReceivedAccountInfoFromGaiaId,
          base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_TRUE(account_info_from_gaia_id_);
  EXPECT_EQ(account_id, account_info_from_gaia_id_->account_id);
  EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia);
  EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email);
  EXPECT_FALSE(account_state_from_gaia_id_.has_refresh_token);
  EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account);
}

// Check that the account info for a given GAIA ID has expected values if that
// GAIA ID is known and has a refresh token available.
TEST_F(IdentityManagerImplTest, GetAccountInfoForKnownGaiaIdRefreshToken) {
  std::string account_id =
      account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(account_id, kTestRefreshToken);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccountInfoFromGaiaId(
      kTestGaiaId,
      base::BindRepeating(
          &IdentityManagerImplTest::OnReceivedAccountInfoFromGaiaId,
          base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_TRUE(account_info_from_gaia_id_);
  EXPECT_EQ(account_id, account_info_from_gaia_id_->account_id);
  EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia);
  EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email);
  EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token);
  EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account);
}

// Check the implementation of GetAccounts() when there are no accounts.
TEST_F(IdentityManagerImplTest, GetAccountsNoAccount) {
  token_service()->LoadCredentials("dummy");

  std::vector<mojom::AccountPtr> accounts;

  // Check that an empty list is returned when there are no accounts.
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccounts(base::BindRepeating(
      &IdentityManagerImplTest::OnGotAccounts, base::Unretained(this),
      run_loop.QuitClosure(), &accounts));
  run_loop.Run();
  EXPECT_EQ(0u, accounts.size());
}

// Check the implementation of GetAccounts() when there is a single account,
// which is the primary account.
TEST_F(IdentityManagerImplTest, GetAccountsPrimaryAccount) {
  token_service()->LoadCredentials("dummy");
  std::vector<mojom::AccountPtr> accounts;

  // Add a primary account.
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);

  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccounts(base::BindRepeating(
      &IdentityManagerImplTest::OnGotAccounts, base::Unretained(this),
      run_loop.QuitClosure(), &accounts));
  run_loop.Run();

  // Verify that |accounts| contains the primary account.
  EXPECT_EQ(1u, accounts.size());
  const mojom::AccountPtr& primary_account = accounts[0];
  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            primary_account->info.account_id);
  EXPECT_EQ(kTestGaiaId, primary_account->info.gaia);
  EXPECT_EQ(kTestEmail, primary_account->info.email);
  EXPECT_TRUE(primary_account->state.has_refresh_token);
  EXPECT_TRUE(primary_account->state.is_primary_account);
}

// Check the implementation of GetAccounts() when there are multiple accounts,
// in particular that ProfileOAuth2TokenService is the source of truth for
// whether an account is present.
TEST_F(IdentityManagerImplTest, GetAccountsMultipleAccounts) {
  token_service()->LoadCredentials("dummy");
  std::vector<mojom::AccountPtr> accounts;

  // Add a primary account.
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  token_service()->UpdateCredentials(
      signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);

  // Add a secondary account with AccountTrackerService, but don't yet make
  // ProfileOAuth2TokenService aware of it.
  std::string secondary_account_id = account_tracker()->SeedAccountInfo(
      kSecondaryTestGaiaId, kSecondaryTestEmail);
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccounts(base::BindRepeating(
      &IdentityManagerImplTest::OnGotAccounts, base::Unretained(this),
      run_loop.QuitClosure(), &accounts));
  run_loop.Run();

  // Verify that |accounts| contains only the primary account at this time.
  EXPECT_EQ(1u, accounts.size());
  const mojom::AccountPtr& primary_account = accounts[0];
  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            primary_account->info.account_id);
  EXPECT_EQ(kTestGaiaId, primary_account->info.gaia);
  EXPECT_EQ(kTestEmail, primary_account->info.email);
  EXPECT_TRUE(primary_account->state.has_refresh_token);
  EXPECT_TRUE(primary_account->state.is_primary_account);

  // Make PO2TS aware of the secondary account.
  token_service()->UpdateCredentials(secondary_account_id, kTestRefreshToken);
  base::RunLoop run_loop2;
  GetIdentityManagerImpl()->GetAccounts(base::BindRepeating(
      &IdentityManagerImplTest::OnGotAccounts, base::Unretained(this),
      run_loop2.QuitClosure(), &accounts));
  run_loop2.Run();

  // Verify that |accounts| contains both accounts, with the primary account
  // being first and having the same information as previously.
  EXPECT_EQ(2u, accounts.size());
  const mojom::AccountPtr& primary_account_redux = accounts[0];
  EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
            primary_account_redux->info.account_id);
  EXPECT_EQ(kTestGaiaId, primary_account_redux->info.gaia);
  EXPECT_EQ(kTestEmail, primary_account_redux->info.email);
  EXPECT_TRUE(primary_account_redux->state.has_refresh_token);
  EXPECT_TRUE(primary_account_redux->state.is_primary_account);

  const mojom::AccountPtr& secondary_account = accounts[1];
  EXPECT_EQ(secondary_account_id, secondary_account->info.account_id);
  EXPECT_EQ(kSecondaryTestGaiaId, secondary_account->info.gaia);
  EXPECT_EQ(kSecondaryTestEmail, secondary_account->info.email);
  EXPECT_TRUE(secondary_account->state.has_refresh_token);
  EXPECT_FALSE(secondary_account->state.is_primary_account);
}

// Check that the expected error is received if requesting an access token when
// not signed in.
TEST_F(IdentityManagerImplTest, GetAccessTokenNotSignedIn) {
  base::RunLoop run_loop;
  GetIdentityManagerImpl()->GetAccessToken(
      kTestGaiaId, ScopeSet(), "dummy_consumer",
      base::BindRepeating(&IdentityManagerImplTest::OnReceivedAccessToken,
                          base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_FALSE(access_token_);
  EXPECT_EQ(GoogleServiceAuthError::State::USER_NOT_SIGNED_UP,
            access_token_error_.state());
}

// Check that the expected access token is received if requesting an access
// token when signed in.
TEST_F(IdentityManagerImplTest, GetAccessTokenSignedIn) {
  signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
  token_service()->UpdateCredentials(account_id, kTestRefreshToken);
  token_service()->set_auto_post_fetch_response_on_message_loop(true);
  base::RunLoop run_loop;

  GetIdentityManagerImpl()->GetAccessToken(
      account_id, ScopeSet(), "dummy_consumer",
      base::BindRepeating(&IdentityManagerImplTest::OnReceivedAccessToken,
                          base::Unretained(this), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_TRUE(access_token_);
  EXPECT_EQ(kTestAccessToken, access_token_.value());
  EXPECT_EQ(GoogleServiceAuthError::State::NONE, access_token_error_.state());
}

}  // namespace
}  // namespace identity
