// Copyright (c) 2012 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 "components/browser_sync/profile_sync_service.h"

#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/values.h"
#include "components/browser_sync/browser_sync_switches.h"
#include "components/browser_sync/profile_sync_test_util.h"
#include "components/signin/core/browser/account_info.h"
#include "components/sync/base/pref_names.h"
#include "components/sync/device_info/local_device_info_provider.h"
#include "components/sync/driver/configure_context.h"
#include "components/sync/driver/fake_data_type_controller.h"
#include "components/sync/driver/sync_api_component_factory_mock.h"
#include "components/sync/driver/sync_client_mock.h"
#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/driver/sync_service_observer.h"
#include "components/sync/driver/sync_token_status.h"
#include "components/sync/driver/sync_util.h"
#include "components/sync/engine/fake_sync_engine.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/version_info/version_info_values.h"
#include "services/identity/public/cpp/identity_test_environment.h"
#include "services/identity/public/cpp/primary_account_mutator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;
using testing::ByMove;
using testing::Return;

namespace browser_sync {

namespace {

class FakeDataTypeManager : public syncer::DataTypeManager {
 public:
  using ConfigureCalled =
      base::RepeatingCallback<void(syncer::ConfigureReason)>;

  explicit FakeDataTypeManager(const ConfigureCalled& configure_called)
      : configure_called_(configure_called), state_(STOPPED) {}

  ~FakeDataTypeManager() override {}

  void Configure(syncer::ModelTypeSet desired_types,
                 const syncer::ConfigureContext& context) override {
    state_ = CONFIGURED;
    DCHECK(!configure_called_.is_null());
    configure_called_.Run(context.reason);
  }

  void ReenableType(syncer::ModelType type) override {}
  void ReadyForStartChanged(syncer::ModelType type) override {}
  void ResetDataTypeErrors() override {}
  void PurgeForMigration(syncer::ModelTypeSet undesired_types) override {}
  void Stop(syncer::ShutdownReason reason) override {}
  syncer::ModelTypeSet GetActiveDataTypes() const override {
    return syncer::ModelTypeSet();
  }
  bool IsNigoriEnabled() const override { return true; }
  State state() const override { return state_; }

 private:
  ConfigureCalled configure_called_;
  State state_;
};

ACTION_P(ReturnNewFakeDataTypeManager, configure_called) {
  return std::make_unique<FakeDataTypeManager>(configure_called);
}

class TestSyncServiceObserver : public syncer::SyncServiceObserver {
 public:
  TestSyncServiceObserver()
      : setup_in_progress_(false), auth_error_(GoogleServiceAuthError()) {}

  void OnStateChanged(syncer::SyncService* sync) override {
    setup_in_progress_ = sync->IsSetupInProgress();
    auth_error_ = sync->GetAuthError();
  }

  bool setup_in_progress() const { return setup_in_progress_; }
  GoogleServiceAuthError auth_error() const { return auth_error_; }

 private:
  bool setup_in_progress_;
  GoogleServiceAuthError auth_error_;
};

// A variant of the FakeSyncEngine that won't automatically call back when asked
// to initialize. Allows us to test things that could happen while backend init
// is in progress.
class FakeSyncEngineNoReturn : public syncer::FakeSyncEngine {
  void Initialize(InitParams params) override {}
};

// FakeSyncEngine that stores the SyncCredentials passed into Initialize(), and
// optionally also whether InvalidateCredentials was called.
class FakeSyncEngineCollectCredentials : public syncer::FakeSyncEngine {
 public:
  explicit FakeSyncEngineCollectCredentials(
      syncer::SyncCredentials* init_credentials,
      const base::RepeatingClosure& invalidate_credentials_callback)
      : init_credentials_(init_credentials),
        invalidate_credentials_callback_(invalidate_credentials_callback) {}

  void Initialize(InitParams params) override {
    *init_credentials_ = params.credentials;
    syncer::FakeSyncEngine::Initialize(std::move(params));
  }

  void InvalidateCredentials() override {
    if (invalidate_credentials_callback_) {
      invalidate_credentials_callback_.Run();
    }
    syncer::FakeSyncEngine::InvalidateCredentials();
  }

 private:
  syncer::SyncCredentials* init_credentials_;
  base::RepeatingClosure invalidate_credentials_callback_;
};

ACTION(ReturnNewFakeSyncEngine) {
  return std::make_unique<syncer::FakeSyncEngine>();
}

ACTION(ReturnNewFakeSyncEngineNoReturn) {
  return std::make_unique<FakeSyncEngineNoReturn>();
}

// A test harness that uses a real ProfileSyncService and in most cases a
// FakeSyncEngine.
//
// This is useful if we want to test the ProfileSyncService and don't care about
// testing the SyncEngine.
class ProfileSyncServiceTest : public ::testing::Test {
 protected:
  ProfileSyncServiceTest() {}
  ~ProfileSyncServiceTest() override {}

  void SetUp() override {
    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kSyncDeferredStartupTimeoutSeconds, "0");
  }

  void TearDown() override {
    // Kill the service before the profile.
    ShutdownAndDeleteService();
  }

  void SignIn() {
    identity_test_env()->MakePrimaryAccountAvailable("test_user@gmail.com");
  }

  void CreateService(ProfileSyncService::StartBehavior behavior) {
    DCHECK(!service_);

    syncer::DataTypeController::TypeVector controllers;
    controllers.push_back(
        std::make_unique<syncer::FakeDataTypeController>(syncer::BOOKMARKS));

    std::unique_ptr<syncer::SyncClientMock> sync_client =
        profile_sync_service_bundle_.CreateSyncClientMock();
    ON_CALL(*sync_client, CreateDataTypeControllers(_))
        .WillByDefault(Return(ByMove(std::move(controllers))));

    service_ = std::make_unique<ProfileSyncService>(
        profile_sync_service_bundle_.CreateBasicInitParams(
            behavior, std::move(sync_client)));

    ON_CALL(*component_factory(), CreateSyncEngine(_, _, _))
        .WillByDefault(ReturnNewFakeSyncEngine());
    ON_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
        .WillByDefault(
            ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
  }

  void CreateServiceWithLocalSyncBackend() {
    DCHECK(!service_);

    syncer::DataTypeController::TypeVector controllers;
    controllers.push_back(
        std::make_unique<syncer::FakeDataTypeController>(syncer::BOOKMARKS));

    std::unique_ptr<syncer::SyncClientMock> sync_client =
        profile_sync_service_bundle_.CreateSyncClientMock();
    ON_CALL(*sync_client, CreateDataTypeControllers(_))
        .WillByDefault(Return(ByMove(std::move(controllers))));

    ProfileSyncService::InitParams init_params =
        profile_sync_service_bundle_.CreateBasicInitParams(
            ProfileSyncService::AUTO_START, std::move(sync_client));

    prefs()->SetBoolean(syncer::prefs::kEnableLocalSyncBackend, true);
    init_params.identity_manager = nullptr;

    service_ = std::make_unique<ProfileSyncService>(std::move(init_params));

    ON_CALL(*component_factory(), CreateSyncEngine(_, _, _))
        .WillByDefault(ReturnNewFakeSyncEngine());
    ON_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
        .WillByDefault(
            ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
  }

  void ShutdownAndDeleteService() {
    if (service_)
      service_->Shutdown();
    service_.reset();
  }

  void InitializeForNthSync() {
    // Set first sync time before initialize to simulate a complete sync setup.
    syncer::SyncPrefs sync_prefs(prefs());
    sync_prefs.SetLastSyncedTime(base::Time::Now());
    sync_prefs.SetSyncRequested(true);
    sync_prefs.SetDataTypesConfiguration(/*keep_everything_synced=*/true,
                                         syncer::UserTypes(),
                                         syncer::UserSelectableTypes());
    sync_prefs.SetFirstSetupComplete();
    service_->Initialize();
  }

  void InitializeForFirstSync() { service_->Initialize(); }

  void TriggerPassphraseRequired() {
    service_->GetEncryptionObserverForTest()->OnPassphraseRequired(
        syncer::REASON_DECRYPTION,
        syncer::KeyDerivationParams::CreateForPbkdf2(),
        sync_pb::EncryptedData());
  }

  void TriggerDataTypeStartRequest() {
    service_->OnDataTypeRequestsSyncStartup(syncer::BOOKMARKS);
  }

  void OnConfigureCalled(syncer::ConfigureReason configure_reason) {
    syncer::DataTypeManager::ConfigureResult result;
    result.status = syncer::DataTypeManager::OK;
    service()->OnConfigureDone(result);
  }

  FakeDataTypeManager::ConfigureCalled GetDefaultConfigureCalledCallback() {
    return base::Bind(&ProfileSyncServiceTest::OnConfigureCalled,
                      base::Unretained(this));
  }

  FakeDataTypeManager::ConfigureCalled GetRecordingConfigureCalledCallback(
      syncer::ConfigureReason* reason_dest) {
    return base::BindLambdaForTesting(
        [reason_dest](syncer::ConfigureReason reason) {
          *reason_dest = reason;
        });
  }

  invalidation::ProfileIdentityProvider* identity_provider() {
    return profile_sync_service_bundle_.identity_provider();
  }

  identity::IdentityManager* identity_manager() {
    return profile_sync_service_bundle_.identity_manager();
  }

  identity::IdentityTestEnvironment* identity_test_env() {
    return profile_sync_service_bundle_.identity_test_env();
  }

  ProfileSyncService* service() { return service_.get(); }

  sync_preferences::TestingPrefServiceSyncable* prefs() {
    return profile_sync_service_bundle_.pref_service();
  }

  syncer::SyncApiComponentFactoryMock* component_factory() {
    return profile_sync_service_bundle_.component_factory();
  }

  const syncer::LocalDeviceInfoProvider* local_device_info_provider() {
    return profile_sync_service_bundle_.device_info_sync_service()
        ->GetLocalDeviceInfoProvider();
  }

 private:
  base::test::ScopedTaskEnvironment scoped_task_environment_;
  ProfileSyncServiceBundle profile_sync_service_bundle_;
  std::unique_ptr<ProfileSyncService> service_;
};

// Verify that the server URLs are sane.
TEST_F(ProfileSyncServiceTest, InitialState) {
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();
  const std::string& url = service()->sync_service_url().spec();
  EXPECT_TRUE(url == syncer::internal::kSyncServerUrl ||
              url == syncer::internal::kSyncDevServerUrl);
}

TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(ReturnNewFakeSyncEngine());
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .WillOnce(
          ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
  InitializeForNthSync();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
}

TEST_F(ProfileSyncServiceTest, SuccessfulLocalBackendInitialization) {
  CreateServiceWithLocalSyncBackend();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(ReturnNewFakeSyncEngine());
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .WillOnce(
          ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
  InitializeForNthSync();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
}

// Verify that an initialization where first setup is not complete does not
// start up Sync-the-feature.
TEST_F(ProfileSyncServiceTest, NeedsConfirmation) {
  SignIn();
  CreateService(ProfileSyncService::MANUAL_START);

  syncer::SyncPrefs sync_prefs(prefs());
  base::Time now = base::Time::Now();
  sync_prefs.SetLastSyncedTime(now);
  sync_prefs.SetSyncRequested(true);
  sync_prefs.SetDataTypesConfiguration(/*keep_everything_synced=*/true,
                                       syncer::UserTypes(),
                                       syncer::UserSelectableTypes());
  service()->Initialize();

  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());

  // Sync should immediately start up in transport mode.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_FALSE(service()->IsSyncFeatureActive());
  EXPECT_FALSE(service()->IsSyncFeatureEnabled());

  // The last sync time shouldn't be cleared.
  // TODO(zea): figure out a way to check that the directory itself wasn't
  // cleared.
  EXPECT_EQ(now, sync_prefs.GetLastSyncedTime());
}

// Verify that the SetSetupInProgress function call updates state
// and notifies observers.
TEST_F(ProfileSyncServiceTest, SetupInProgress) {
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForFirstSync();

  TestSyncServiceObserver observer;
  service()->AddObserver(&observer);

  auto sync_blocker = service()->GetSetupInProgressHandle();
  EXPECT_TRUE(observer.setup_in_progress());
  sync_blocker.reset();
  EXPECT_FALSE(observer.setup_in_progress());

  service()->RemoveObserver(&observer);
}

// Verify that disable by enterprise policy works.
TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) {
  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(true));
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());
}

// This test exercises sign-in after startup, which isn't supported on ChromeOS.
#if !defined(OS_CHROMEOS)
TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInitThenPolicyRemoved) {
  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(true));
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY |
                syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());

  // Remove the policy. Now only missing sign-in is preventing startup.
  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(false));
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());

  // Once we mark first setup complete again (it was cleared by the policy) and
  // sign in, sync starts up.
  service()->GetUserSettings()->SetFirstSetupComplete();
  SignIn();
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
}
#endif  // !defined(OS_CHROMEOS)

// Verify that disable by enterprise policy works even after the backend has
// been initialized.
TEST_F(ProfileSyncServiceTest, DisabledByPolicyAfterInit) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();

  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(true));

  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());
}

// Exercises the ProfileSyncService's code paths related to getting shut down
// before the backend initialize call returns.
TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
  CreateService(ProfileSyncService::AUTO_START);
  ON_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillByDefault(ReturnNewFakeSyncEngineNoReturn());

  SignIn();
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::INITIALIZING,
            service()->GetTransportState());

  ShutdownAndDeleteService();
}

// Test SetSyncRequested(false) before we've initialized the backend.
TEST_F(ProfileSyncServiceTest, EarlyRequestStop) {
  CreateService(ProfileSyncService::AUTO_START);
  // Set up a fake sync engine that will not immediately finish initialization.
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(ReturnNewFakeSyncEngineNoReturn());
  SignIn();
  InitializeForNthSync();

  ASSERT_EQ(syncer::SyncService::TransportState::INITIALIZING,
            service()->GetTransportState());

  // Request stop. This should immediately restart the service in standalone
  // transport mode.
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(ReturnNewFakeSyncEngine());
  service()->GetUserSettings()->SetSyncRequested(false);
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_FALSE(service()->IsSyncFeatureActive());
  EXPECT_FALSE(service()->IsSyncFeatureEnabled());

  // Request start. Now Sync-the-feature should start again.
  service()->GetUserSettings()->SetSyncRequested(true);
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_TRUE(service()->IsSyncFeatureActive());
  EXPECT_TRUE(service()->IsSyncFeatureEnabled());
}

// Test SetSyncRequested(false) after we've initialized the backend.
TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) {
  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  InitializeForNthSync();

  ASSERT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  ASSERT_TRUE(service()->IsSyncFeatureActive());
  ASSERT_TRUE(service()->IsSyncFeatureEnabled());

  testing::Mock::VerifyAndClearExpectations(component_factory());

  service()->GetUserSettings()->SetSyncRequested(false);
  EXPECT_TRUE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_FALSE(service()->IsSyncFeatureActive());
  EXPECT_FALSE(service()->IsSyncFeatureEnabled());

  service()->GetUserSettings()->SetSyncRequested(true);
  EXPECT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_TRUE(service()->IsSyncFeatureActive());
  EXPECT_TRUE(service()->IsSyncFeatureEnabled());
}

// Certain ProfileSyncService tests don't apply to Chrome OS, for example
// things that deal with concepts like "signing out" and policy.
#if !defined(OS_CHROMEOS)
TEST_F(ProfileSyncServiceTest, EnableSyncSignOutAndChangeAccount) {
  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  InitializeForNthSync();

  EXPECT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_EQ(identity_manager()->GetPrimaryAccountId(),
            identity_provider()->GetActiveAccountId());

  auto* account_mutator = identity_manager()->GetPrimaryAccountMutator();

  // GetPrimaryAccountMutator() returns nullptr on ChromeOS only.
  DCHECK(account_mutator);
  account_mutator->ClearPrimaryAccount(
      identity::PrimaryAccountMutator::ClearAccountsAction::kDefault,
      signin_metrics::SIGNOUT_TEST,
      signin_metrics::SignoutDelete::IGNORE_METRIC);
  // Wait for PSS to be notified that the primary account has gone away.
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());
  EXPECT_EQ("", identity_provider()->GetActiveAccountId());

  identity_test_env()->MakePrimaryAccountAvailable("new_user@gmail.com");
  EXPECT_EQ(identity_manager()->GetPrimaryAccountId(),
            identity_provider()->GetActiveAccountId());
}
#endif  // !defined(OS_CHROMEOS)

TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) {
  CreateService(ProfileSyncService::AUTO_START);

  SignIn();
  InitializeForNthSync();

  // Initial status.
  syncer::SyncTokenStatus token_status = service()->GetSyncTokenStatus();
  ASSERT_EQ(syncer::CONNECTION_NOT_ATTEMPTED, token_status.connection_status);
  ASSERT_TRUE(token_status.connection_status_update_time.is_null());
  ASSERT_TRUE(token_status.token_request_time.is_null());
  ASSERT_TRUE(token_status.token_receive_time.is_null());

  // Simulate an auth error.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  // The token request will take the form of a posted task.  Run it.
  base::RunLoop().RunUntilIdle();

  token_status = service()->GetSyncTokenStatus();
  EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR, token_status.connection_status);
  EXPECT_FALSE(token_status.connection_status_update_time.is_null());
  EXPECT_FALSE(token_status.token_request_time.is_null());
  EXPECT_FALSE(token_status.token_receive_time.is_null());
  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
            token_status.last_get_token_error);
  EXPECT_TRUE(token_status.next_token_request_time.is_null());

  // Simulate successful connection.
  service()->OnConnectionStatusChange(syncer::CONNECTION_OK);
  token_status = service()->GetSyncTokenStatus();
  EXPECT_EQ(syncer::CONNECTION_OK, token_status.connection_status);
}

TEST_F(ProfileSyncServiceTest, RevokeAccessTokenFromTokenService) {
  syncer::SyncCredentials init_credentials;

  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(
          Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
              &init_credentials, base::RepeatingClosure()))));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  const std::string primary_account_id =
      identity_manager()->GetPrimaryAccountId();

  // Make sure the expected credentials (correct account_id, empty access token)
  // were passed to the SyncEngine.
  ASSERT_EQ(primary_account_id, init_credentials.account_id);
  ASSERT_TRUE(init_credentials.sync_token.empty());

  // At this point, the real SyncEngine would try to connect to the server, fail
  // (because it has no access token), and eventually call
  // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
  // doesn't do any of this, call that explicitly here.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  base::RunLoop().RunUntilIdle();
  ASSERT_FALSE(service()->GetAccessTokenForTest().empty());

  AccountInfo secondary_account_info =
      identity_test_env()->MakeAccountAvailable("test_user2@gmail.com");
  identity_test_env()->RemoveRefreshTokenForAccount(
      secondary_account_info.account_id);
  EXPECT_FALSE(service()->GetAccessTokenForTest().empty());

  identity_test_env()->RemoveRefreshTokenForPrimaryAccount();
  EXPECT_TRUE(service()->GetAccessTokenForTest().empty());
}

// Checks that CREDENTIALS_REJECTED_BY_CLIENT resets the access token and stops
// Sync. Regression test for https://crbug.com/824791.
TEST_F(ProfileSyncServiceTest, CredentialsRejectedByClient_StopSync) {
  base::test::ScopedFeatureList feature;
  feature.InitAndEnableFeature(switches::kStopSyncInPausedState);

  syncer::SyncCredentials init_credentials;

  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(
          Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
              &init_credentials, base::RepeatingClosure()))));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  TestSyncServiceObserver observer;
  service()->AddObserver(&observer);

  const std::string primary_account_id =
      identity_manager()->GetPrimaryAccountId();

  // Make sure the expected credentials (correct account_id, empty access token)
  // were passed to the SyncEngine.
  ASSERT_EQ(primary_account_id, init_credentials.account_id);
  ASSERT_TRUE(init_credentials.sync_token.empty());

  // At this point, the real SyncEngine would try to connect to the server, fail
  // (because it has no access token), and eventually call
  // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
  // doesn't do any of this, call that explicitly here.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  base::RunLoop().RunUntilIdle();
  ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
  ASSERT_EQ(GoogleServiceAuthError::AuthErrorNone(), service()->GetAuthError());
  ASSERT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.auth_error());

  // Simulate the credentials getting locally rejected by the client by setting
  // the refresh token to a special invalid value.
  identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount();
  const GoogleServiceAuthError rejected_by_client =
      GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
          GoogleServiceAuthError::InvalidGaiaCredentialsReason::
              CREDENTIALS_REJECTED_BY_CLIENT);
  ASSERT_EQ(rejected_by_client,
            identity_test_env()
                ->identity_manager()
                ->GetErrorStateOfRefreshTokenForAccount(primary_account_id));
  EXPECT_TRUE(service()->GetAccessTokenForTest().empty());

  // The observer should have been notified of the auth error state.
  EXPECT_EQ(rejected_by_client, observer.auth_error());
  // The Sync engine should have been shut down.
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());
  EXPECT_TRUE(
      service()->HasDisableReason(syncer::SyncService::DISABLE_REASON_PAUSED));

  service()->RemoveObserver(&observer);
}

TEST_F(ProfileSyncServiceTest, CredentialsRejectedByClient_DoNotStopSync) {
  base::test::ScopedFeatureList feature;
  feature.InitAndDisableFeature(switches::kStopSyncInPausedState);

  syncer::SyncCredentials init_credentials;

  bool invalidate_credentials_called = false;
  base::RepeatingClosure invalidate_credentials_callback =
      base::BindRepeating([](bool* called) { *called = true; },
                          base::Unretained(&invalidate_credentials_called));

  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(
          Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
              &init_credentials, invalidate_credentials_callback))));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  TestSyncServiceObserver observer;
  service()->AddObserver(&observer);

  const std::string primary_account_id =
      identity_manager()->GetPrimaryAccountId();

  // Make sure the expected credentials (correct account_id, empty access token)
  // were passed to the SyncEngine.
  ASSERT_EQ(primary_account_id, init_credentials.account_id);
  ASSERT_TRUE(init_credentials.sync_token.empty());

  // At this point, the real SyncEngine would try to connect to the server, fail
  // (because it has no access token), and eventually call
  // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
  // doesn't do any of this, call that explicitly here.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  base::RunLoop().RunUntilIdle();
  ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
  ASSERT_EQ(GoogleServiceAuthError::AuthErrorNone(), service()->GetAuthError());
  ASSERT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.auth_error());

  // Simulate the credentials getting locally rejected by the client by setting
  // the refresh token to a special invalid value.
  identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount();
  const GoogleServiceAuthError rejected_by_client =
      GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
          GoogleServiceAuthError::InvalidGaiaCredentialsReason::
              CREDENTIALS_REJECTED_BY_CLIENT);
  ASSERT_EQ(rejected_by_client,
            identity_test_env()
                ->identity_manager()
                ->GetErrorStateOfRefreshTokenForAccount(primary_account_id));
  EXPECT_TRUE(service()->GetAccessTokenForTest().empty());
  EXPECT_TRUE(invalidate_credentials_called);

  // The observer should have been notified of the auth error state.
  EXPECT_EQ(rejected_by_client, observer.auth_error());
  // The Sync engine should still be running.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  service()->RemoveObserver(&observer);
}

// CrOS does not support signout.
#if !defined(OS_CHROMEOS)
TEST_F(ProfileSyncServiceTest, SignOutRevokeAccessToken) {
  syncer::SyncCredentials init_credentials;

  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(
          Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
              &init_credentials, base::RepeatingClosure()))));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  const std::string primary_account_id =
      identity_manager()->GetPrimaryAccountId();

  // Make sure the expected credentials (correct account_id, empty access token)
  // were passed to the SyncEngine.
  ASSERT_EQ(primary_account_id, init_credentials.account_id);
  ASSERT_TRUE(init_credentials.sync_token.empty());

  // At this point, the real SyncEngine would try to connect to the server, fail
  // (because it has no access token), and eventually call
  // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
  // doesn't do any of this, call that explicitly here.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(service()->GetAccessTokenForTest().empty());

  auto* account_mutator = identity_manager()->GetPrimaryAccountMutator();

  // GetPrimaryAccountMutator() returns nullptr on ChromeOS only.
  DCHECK(account_mutator);

  account_mutator->ClearPrimaryAccount(
      identity::PrimaryAccountMutator::ClearAccountsAction::kDefault,
      signin_metrics::SIGNOUT_TEST,
      signin_metrics::SignoutDelete::IGNORE_METRIC);
  EXPECT_TRUE(service()->GetAccessTokenForTest().empty());
}
#endif

// Verify that LastSyncedTime and local DeviceInfo is cleared on sign out.
TEST_F(ProfileSyncServiceTest, ClearDataOnSignOut) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  base::Time last_synced_time = service()->GetLastSyncedTime();
  ASSERT_LT(base::Time::Now() - last_synced_time,
            base::TimeDelta::FromMinutes(1));
  ASSERT_TRUE(local_device_info_provider()->GetLocalDeviceInfo());

  // Sign out.
  service()->StopAndClear();

  // Even though Sync-the-feature is disabled, Sync-the-transport should still
  // be running, and should have updated the last synced time.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  EXPECT_FALSE(service()->IsSyncFeatureEnabled());

  EXPECT_NE(service()->GetLastSyncedTime(), last_synced_time);
  EXPECT_TRUE(local_device_info_provider()->GetLocalDeviceInfo());
}

TEST_F(ProfileSyncServiceTest, CancelSyncAfterSignOut) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  base::Time last_synced_time = service()->GetLastSyncedTime();
  ASSERT_LT(base::Time::Now() - last_synced_time,
            base::TimeDelta::FromMinutes(1));

  // Disable sync.
  service()->StopAndClear();
  EXPECT_FALSE(service()->IsSyncFeatureEnabled());

  // Calling StopAndClear while already stopped should not crash. This may
  // (under some circumstances) happen when the user enables sync again but hits
  // the cancel button at the end of the process.
  ASSERT_FALSE(service()->GetUserSettings()->IsSyncRequested());
  service()->StopAndClear();
  EXPECT_FALSE(service()->IsSyncFeatureEnabled());
}

// Verify that credential errors get returned from GetAuthError().
TEST_F(ProfileSyncServiceTest, CredentialErrorReturned) {
  // This test needs to manually send access tokens (or errors), so disable
  // automatic replies to access token requests.
  identity_test_env()->SetAutomaticIssueOfAccessTokens(false);

  syncer::SyncCredentials init_credentials;

  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(
          Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
              &init_credentials, base::RepeatingClosure()))));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  const std::string primary_account_id =
      identity_manager()->GetPrimaryAccountId();

  // Make sure the expected credentials (correct account_id, empty access token)
  // were passed to the SyncEngine.
  ASSERT_EQ(primary_account_id, init_credentials.account_id);
  ASSERT_TRUE(init_credentials.sync_token.empty());

  TestSyncServiceObserver observer;
  service()->AddObserver(&observer);

  // At this point, the real SyncEngine would try to connect to the server, fail
  // (because it has no access token), and eventually call
  // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
  // doesn't do any of this, call that explicitly here.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  // Wait for ProfileSyncService to send an access token request.
  base::RunLoop().RunUntilIdle();
  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
      primary_account_id, "access token", base::Time::Max());
  ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
  ASSERT_EQ(GoogleServiceAuthError::NONE, service()->GetAuthError().state());

  // Emulate Chrome receiving a new, invalid LST. This happens when the user
  // signs out of the content area.
  identity_test_env()->SetRefreshTokenForPrimaryAccount();
  // Again, wait for ProfileSyncService to be notified.
  base::RunLoop().RunUntilIdle();
  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));

  // Check that the invalid token is returned from sync.
  EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
            service()->GetAuthError().state());
  EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
            observer.auth_error().state());
  // The overall state should remain ACTIVE.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  service()->RemoveObserver(&observer);
}

// Verify that credential errors get cleared when a new token is fetched
// successfully.
TEST_F(ProfileSyncServiceTest, CredentialErrorClearsOnNewToken) {
  // This test needs to manually send access tokens (or errors), so disable
  // automatic replies to access token requests.
  identity_test_env()->SetAutomaticIssueOfAccessTokens(false);

  syncer::SyncCredentials init_credentials;

  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(
          Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
              &init_credentials, base::RepeatingClosure()))));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  const std::string primary_account_id =
      identity_manager()->GetPrimaryAccountId();

  // Make sure the expected credentials (correct account_id, empty access token)
  // were passed to the SyncEngine.
  ASSERT_EQ(primary_account_id, init_credentials.account_id);
  ASSERT_TRUE(init_credentials.sync_token.empty());

  TestSyncServiceObserver observer;
  service()->AddObserver(&observer);

  // At this point, the real SyncEngine would try to connect to the server, fail
  // (because it has no access token), and eventually call
  // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
  // doesn't do any of this, call that explicitly here.
  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);

  // Wait for ProfileSyncService to send an access token request.
  base::RunLoop().RunUntilIdle();
  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
      primary_account_id, "access token", base::Time::Max());
  ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
  ASSERT_EQ(GoogleServiceAuthError::NONE, service()->GetAuthError().state());

  // Emulate Chrome receiving a new, invalid LST. This happens when the user
  // signs out of the content area.
  identity_test_env()->SetRefreshTokenForPrimaryAccount();
  // Wait for ProfileSyncService to be notified of the changed credentials and
  // send a new access token request.
  base::RunLoop().RunUntilIdle();
  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));

  // Check that the invalid token is returned from sync.
  ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
            service()->GetAuthError().state());
  // The overall state should remain ACTIVE.
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  // Now emulate Chrome receiving a new, valid LST.
  identity_test_env()->SetRefreshTokenForPrimaryAccount();
  // Again, wait for ProfileSyncService to be notified.
  base::RunLoop().RunUntilIdle();
  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
      "this one works", base::Time::Now() + base::TimeDelta::FromDays(10));

  // Check that sync auth error state cleared.
  EXPECT_EQ(GoogleServiceAuthError::NONE, service()->GetAuthError().state());
  EXPECT_EQ(GoogleServiceAuthError::NONE, observer.auth_error().state());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  service()->RemoveObserver(&observer);
}

// Verify that the disable sync flag disables sync.
TEST_F(ProfileSyncServiceTest, DisableSyncFlag) {
  base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync);
  EXPECT_FALSE(switches::IsSyncAllowedByFlag());
}

// Verify that no disable sync flag enables sync.
TEST_F(ProfileSyncServiceTest, NoDisableSyncFlag) {
  EXPECT_TRUE(switches::IsSyncAllowedByFlag());
}

// Test Sync will stop after receive memory pressure
TEST_F(ProfileSyncServiceTest, MemoryPressureRecording) {
  CreateService(ProfileSyncService::AUTO_START);
  SignIn();
  InitializeForNthSync();

  ASSERT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  testing::Mock::VerifyAndClearExpectations(component_factory());

  syncer::SyncPrefs sync_prefs(prefs());

  ASSERT_EQ(prefs()->GetInteger(syncer::prefs::kSyncMemoryPressureWarningCount),
            0);
  ASSERT_FALSE(sync_prefs.DidSyncShutdownCleanly());

  // Simulate memory pressure notification.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  // Verify memory pressure recorded.
  EXPECT_EQ(prefs()->GetInteger(syncer::prefs::kSyncMemoryPressureWarningCount),
            1);
  EXPECT_FALSE(sync_prefs.DidSyncShutdownCleanly());

  // Simulate memory pressure notification.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();
  ShutdownAndDeleteService();

  // Verify memory pressure and shutdown recorded.
  EXPECT_EQ(prefs()->GetInteger(syncer::prefs::kSyncMemoryPressureWarningCount),
            2);
  EXPECT_TRUE(sync_prefs.DidSyncShutdownCleanly());
}

// Test that the passphrase prompt due to version change logic gets triggered
// on a datatype type requesting startup, but only happens once.
TEST_F(ProfileSyncServiceTest, PassphrasePromptDueToVersion) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();

  syncer::SyncPrefs sync_prefs(prefs());
  ASSERT_EQ(PRODUCT_VERSION, sync_prefs.GetLastRunVersion());

  sync_prefs.SetPassphrasePrompted(true);

  // Until a datatype requests startup while a passphrase is required the
  // passphrase prompt bit should remain set.
  EXPECT_TRUE(sync_prefs.IsPassphrasePrompted());
  TriggerPassphraseRequired();
  EXPECT_TRUE(sync_prefs.IsPassphrasePrompted());

  // Because the last version was unset, this run should be treated as a new
  // version and force a prompt.
  TriggerDataTypeStartRequest();
  EXPECT_FALSE(sync_prefs.IsPassphrasePrompted());

  // At this point further datatype startup request should have no effect.
  sync_prefs.SetPassphrasePrompted(true);
  TriggerDataTypeStartRequest();
  EXPECT_TRUE(sync_prefs.IsPassphrasePrompted());
}

// Test that when ProfileSyncService receives actionable error
// RESET_LOCAL_SYNC_DATA it restarts sync.
TEST_F(ProfileSyncServiceTest, ResetSyncData) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  // Backend should get initialized two times: once during initialization and
  // once when handling actionable error.
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .WillOnce(
          ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()))
      .WillOnce(
          ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
      .WillOnce(ReturnNewFakeSyncEngine())
      .WillOnce(ReturnNewFakeSyncEngine());

  InitializeForNthSync();

  syncer::SyncProtocolError client_cmd;
  client_cmd.action = syncer::RESET_LOCAL_SYNC_DATA;
  service()->OnActionableError(client_cmd);
}

// Test that when ProfileSyncService receives actionable error
// DISABLE_SYNC_ON_CLIENT it disables sync and signs out.
TEST_F(ProfileSyncServiceTest, DisableSyncOnClient) {
  SignIn();
  CreateService(ProfileSyncService::AUTO_START);
  InitializeForNthSync();

  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  ASSERT_LT(base::Time::Now() - service()->GetLastSyncedTime(),
            base::TimeDelta::FromMinutes(1));
  ASSERT_TRUE(local_device_info_provider()->GetLocalDeviceInfo());

  syncer::SyncProtocolError client_cmd;
  client_cmd.action = syncer::DISABLE_SYNC_ON_CLIENT;
  service()->OnActionableError(client_cmd);

#if defined(OS_CHROMEOS)
  // ChromeOS does not support signout.
  EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
            service()->GetDisableReasons());
  // Since ChromeOS doesn't support signout and so the account is still there
  // and available, Sync will restart in standalone transport mode.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
#else
  EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN |
                syncer::SyncService::DISABLE_REASON_USER_CHOICE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());
  EXPECT_TRUE(service()->GetLastSyncedTime().is_null());
  EXPECT_FALSE(local_device_info_provider()->GetLocalDeviceInfo());
#endif

  EXPECT_FALSE(service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(service()->IsSyncFeatureActive());
}

// Verify a that local sync mode resumes after the policy is lifted.
TEST_F(ProfileSyncServiceTest, LocalBackendDisabledByPolicy) {
  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(false));
  CreateServiceWithLocalSyncBackend();
  InitializeForNthSync();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());

  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(true));

  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            service()->GetTransportState());

  // Note: If standalone transport is enabled, then setting kSyncManaged to
  // false will immediately start up the engine. Otherwise, the RequestStart
  // call below will trigger it.
  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
                          std::make_unique<base::Value>(false));

  service()->GetUserSettings()->SetSyncRequested(true);
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
}

// Test ConfigureDataTypeManagerReason on First and Nth start.
TEST_F(ProfileSyncServiceTest, ConfigureDataTypeManagerReason) {
  const syncer::DataTypeManager::ConfigureResult configure_result(
      syncer::DataTypeManager::OK, syncer::ModelTypeSet());
  syncer::ConfigureReason configure_reason = syncer::CONFIGURE_REASON_UNKNOWN;

  SignIn();

  // First sync.
  CreateService(ProfileSyncService::AUTO_START);
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .WillOnce(ReturnNewFakeDataTypeManager(
          GetRecordingConfigureCalledCallback(&configure_reason)));
  InitializeForFirstSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(component_factory()));
  EXPECT_EQ(syncer::CONFIGURE_REASON_NEW_CLIENT, configure_reason);
  service()->OnConfigureDone(configure_result);

  // Reconfiguration.
  // Trigger a reconfig by grabbing a SyncSetupInProgressHandle and immediately
  // releasing it again (via the temporary unique_ptr going away).
  service()->GetSetupInProgressHandle();
  EXPECT_EQ(syncer::CONFIGURE_REASON_RECONFIGURATION, configure_reason);
  service()->OnConfigureDone(configure_result);
  ShutdownAndDeleteService();

  // Nth sync.
  CreateService(ProfileSyncService::AUTO_START);
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .WillOnce(ReturnNewFakeDataTypeManager(
          GetRecordingConfigureCalledCallback(&configure_reason)));
  InitializeForNthSync();
  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
            service()->GetTransportState());
  ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(component_factory()));
  EXPECT_EQ(syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE, configure_reason);
  service()->OnConfigureDone(configure_result);

  // Reconfiguration.
  // Trigger a reconfig by grabbing a SyncSetupInProgressHandle and immediately
  // releasing it again (via the temporary unique_ptr going away).
  service()->GetSetupInProgressHandle();
  EXPECT_EQ(syncer::CONFIGURE_REASON_RECONFIGURATION, configure_reason);
  service()->OnConfigureDone(configure_result);
  ShutdownAndDeleteService();
}

}  // namespace
}  // namespace browser_sync
