// 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 "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "components/browser_sync/profile_sync_test_util.h"
#include "components/prefs/pref_service.h"
#include "components/sync/base/pref_names.h"
#include "components/sync/driver/data_type_manager_mock.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_driver_switches.h"
#include "components/sync/engine/fake_sync_engine.h"
#include "components/sync/engine/mock_sync_engine.h"
#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using syncer::DataTypeManager;
using syncer::DataTypeManagerMock;
using syncer::FakeSyncEngine;
using syncer::MockSyncEngine;
using testing::_;
using testing::ByMove;
using testing::DoAll;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::NiceMock;
using testing::Return;

namespace browser_sync {

namespace {

const char kEmail[] = "test_user@gmail.com";

void SetError(DataTypeManager::ConfigureResult* result) {
  syncer::DataTypeStatusTable::TypeErrorMap errors;
  errors[syncer::BOOKMARKS] =
      syncer::SyncError(FROM_HERE, syncer::SyncError::UNRECOVERABLE_ERROR,
                        "Error", syncer::BOOKMARKS);
  result->data_type_status_table.UpdateFailedDataTypes(errors);
}

}  // namespace

ACTION_P(InvokeOnConfigureStart, sync_service) {
  sync_service->OnConfigureStart();
}

ACTION_P3(InvokeOnConfigureDone, sync_service, error_callback, result) {
  DataTypeManager::ConfigureResult configure_result =
      static_cast<DataTypeManager::ConfigureResult>(result);
  if (result.status == syncer::DataTypeManager::ABORTED)
    error_callback.Run(&configure_result);
  sync_service->OnConfigureDone(configure_result);
}

class ProfileSyncServiceStartupTest : public testing::Test {
 public:
  ProfileSyncServiceStartupTest()
      : scoped_task_environment_(
            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
        sync_prefs_(profile_sync_service_bundle_.pref_service()) {
    profile_sync_service_bundle_.identity_test_env()
        ->SetAutomaticIssueOfAccessTokens(true);
  }

  ~ProfileSyncServiceStartupTest() override {
    sync_service_->Shutdown();
  }

  void CreateSyncService(ProfileSyncService::StartBehavior start_behavior,
                         syncer::ModelTypeSet registered_types =
                             syncer::ModelTypeSet(syncer::BOOKMARKS)) {
    ProfileSyncServiceBundle::SyncClientBuilder builder(
        &profile_sync_service_bundle_);
    ProfileSyncService::InitParams init_params =
        profile_sync_service_bundle_.CreateBasicInitParams(start_behavior,
                                                           builder.Build());

    ON_CALL(*component_factory(), CreateCommonDataTypeControllers(_, _))
        .WillByDefault(InvokeWithoutArgs([=]() {
          syncer::DataTypeController::TypeVector controllers;
          for (syncer::ModelType type : registered_types) {
            controllers.push_back(
                std::make_unique<syncer::FakeDataTypeController>(type));
          }
          return controllers;
        }));

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

  void SimulateTestUserSignin() {
    profile_sync_service_bundle_.identity_test_env()
        ->MakePrimaryAccountAvailable(kEmail);
  }

  void SimulateTestUserSigninWithoutRefreshToken() {
    // Set the primary account *without* providing an OAuth token.
    profile_sync_service_bundle_.identity_test_env()->SetPrimaryAccount(kEmail);
  }

  void UpdateCredentials() {
    profile_sync_service_bundle_.identity_test_env()
        ->SetRefreshTokenForPrimaryAccount();
  }

  DataTypeManagerMock* SetUpDataTypeManagerMock() {
    auto data_type_manager = std::make_unique<NiceMock<DataTypeManagerMock>>();
    DataTypeManagerMock* data_type_manager_raw = data_type_manager.get();
    ON_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
        .WillByDefault(Return(ByMove(std::move(data_type_manager))));
    return data_type_manager_raw;
  }

  FakeSyncEngine* SetUpFakeSyncEngine() {
    auto sync_engine = std::make_unique<FakeSyncEngine>();
    FakeSyncEngine* sync_engine_raw = sync_engine.get();
    ON_CALL(*component_factory(), CreateSyncEngine(_, _, _, _))
        .WillByDefault(Return(ByMove(std::move(sync_engine))));
    return sync_engine_raw;
  }

  MockSyncEngine* SetUpMockSyncEngine() {
    auto sync_engine = std::make_unique<NiceMock<MockSyncEngine>>();
    MockSyncEngine* sync_engine_raw = sync_engine.get();
    ON_CALL(*component_factory(), CreateSyncEngine(_, _, _, _))
        .WillByDefault(Return(ByMove(std::move(sync_engine))));
    return sync_engine_raw;
  }

  syncer::SyncPrefs* sync_prefs() { return &sync_prefs_; }

  ProfileSyncService* sync_service() { return sync_service_.get(); }

  PrefService* pref_service() {
    return profile_sync_service_bundle_.pref_service();
  }

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

  void FastForwardUntilNoTasksRemain() {
    scoped_task_environment_.FastForwardUntilNoTasksRemain();
  }

 private:
  base::test::ScopedTaskEnvironment scoped_task_environment_;
  ProfileSyncServiceBundle profile_sync_service_bundle_;
  syncer::SyncPrefs sync_prefs_;
  std::unique_ptr<ProfileSyncService> sync_service_;
};

class ProfileSyncServiceWithStandaloneTransportStartupTest
    : public ProfileSyncServiceStartupTest {
 protected:
  ProfileSyncServiceWithStandaloneTransportStartupTest() {
    feature_list_.InitAndEnableFeature(switches::kSyncStandaloneTransport);
  }

  ~ProfileSyncServiceWithStandaloneTransportStartupTest() override {}

 private:
  base::test::ScopedFeatureList feature_list_;
};

class ProfileSyncServiceWithoutStandaloneTransportStartupTest
    : public ProfileSyncServiceStartupTest {
 protected:
  ProfileSyncServiceWithoutStandaloneTransportStartupTest() {
    feature_list_.InitAndDisableFeature(switches::kSyncStandaloneTransport);
  }

  ~ProfileSyncServiceWithoutStandaloneTransportStartupTest() override {}

 private:
  base::test::ScopedFeatureList feature_list_;
};

// ChromeOS does not support sign-in after startup (in particular,
// IdentityManager::Observer::OnPrimaryAccountSet never gets called).
#if !defined(OS_CHROMEOS)
TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest,
       StartFirstTime) {
  // We've never completed startup.
  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());

  CreateSyncService(ProfileSyncService::MANUAL_START);
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::STOPPED));

  // Should not actually start, rather just clean things up and wait
  // to be enabled.
  sync_service()->Initialize();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());

  // Preferences should be back to defaults.
  EXPECT_EQ(base::Time(), sync_prefs()->GetLastSyncedTime());
  EXPECT_FALSE(sync_prefs()->IsFirstSetupComplete());

  // This tells the ProfileSyncService that setup is now in progress, which
  // causes it to try starting up the engine. We're not signed in yet though, so
  // that won't work.
  auto sync_blocker = sync_service()->GetSetupInProgressHandle();
  EXPECT_FALSE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());

  // Simulate successful signin. This will cause ProfileSyncService to start,
  // since all conditions are now fulfilled.
  SimulateTestUserSignin();

  // Now we're signed in, so the engine can start. There's already a setup in
  // progress, so we don't go into the WAITING_FOR_START_REQUEST state. Engine
  // initialization is immediate in this test, so we also bypass the
  // INITIALIZING state.
  EXPECT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());

  // Simulate the UI telling sync it has finished setting up. Note that this is
  // a two-step process: Releasing the SetupInProgressHandle, and marking first
  // setup complete.
  sync_blocker.reset();
  // Now setup isn't in progress anymore, but Sync is still waiting to be told
  // that the initial setup was completed.
  ASSERT_FALSE(sync_service()->IsSetupInProgress());
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());

  // Marking first setup complete will let ProfileSyncService configure the
  // DataTypeManager.
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  sync_service()->GetUserSettings()->SetFirstSetupComplete();

  // This should have fully enabled sync.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());

  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
}

TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, StartFirstTime) {
  // We've never completed startup.
  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());

  CreateSyncService(ProfileSyncService::MANUAL_START);
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::STOPPED));

  // Should not actually start, rather just clean things up and wait
  // to be enabled.
  sync_service()->Initialize();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());

  // Preferences should be back to defaults.
  EXPECT_EQ(base::Time(), sync_prefs()->GetLastSyncedTime());
  EXPECT_FALSE(sync_prefs()->IsFirstSetupComplete());

  // This tells the ProfileSyncService that setup is now in progress, which
  // causes it to try starting up the engine. We're not signed in yet though, so
  // that won't work.
  auto sync_blocker = sync_service()->GetSetupInProgressHandle();
  EXPECT_FALSE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());

  SimulateTestUserSignin();

  // Now we're signed in, so the engine can start. There's already a setup in
  // progress, so we don't go into the WAITING_FOR_START_REQUEST state. Engine
  // initialization is immediate in this test, so we also bypass the
  // INITIALIZING state.
  EXPECT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());

  // Simulate the UI telling sync it has finished setting up. Note that this is
  // a two-step process: Releasing the SetupInProgressHandle, and marking first
  // setup complete.
  // Since standalone transport is enabled, completed first-time setup is not a
  // requirement, so the service will start up as soon as the setup handle is
  // released.
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  sync_blocker.reset();
  ASSERT_FALSE(sync_service()->IsSetupInProgress());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  // Sync-the-feature is still not active, but rather pending confirmation.
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());

  // Marking first setup complete will let ProfileSyncService reconfigure the
  // DataTypeManager in full Sync-the-feature mode.
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  sync_service()->GetUserSettings()->SetFirstSetupComplete();

  // This should have fully enabled sync.
  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());

  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
}
#endif  // OS_CHROMEOS

TEST_F(ProfileSyncServiceStartupTest, StartNoCredentials) {
  // We're already signed in, but don't have a refresh token.
  SimulateTestUserSigninWithoutRefreshToken();
  sync_prefs()->SetFirstSetupComplete();

  CreateSyncService(ProfileSyncService::MANUAL_START);

  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));

  sync_service()->Initialize();

  // ProfileSyncService should now be active, but of course not have an access
  // token.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->GetAccessTokenForTest().empty());
  // Note that ProfileSyncService is not in an auth error state - no auth was
  // attempted, so no error.
}

TEST_F(ProfileSyncServiceStartupTest, StartInvalidCredentials) {
  SimulateTestUserSignin();
  sync_prefs()->SetFirstSetupComplete();

  CreateSyncService(ProfileSyncService::MANUAL_START);

  // Tell the engine to stall while downloading control types (simulating an
  // auth error).
  FakeSyncEngine* fake_engine = SetUpFakeSyncEngine();
  fake_engine->set_fail_initial_download(true);
  // Note: Since engine initialization will fail, the DataTypeManager should not
  // get created at all here.

  sync_service()->Initialize();

  // Engine initialization failures puts the service into an unrecoverable error
  // state. It'll take either a browser restart or a full sign-out+sign-in to
  // get out of this.
  EXPECT_TRUE(sync_service()->HasUnrecoverableError());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());
}

TEST_F(ProfileSyncServiceStartupTest, StartCrosNoCredentials) {
  // We've never completed startup.
  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());

  // On ChromeOS, the user is always immediately signed in, but a refresh token
  // isn't necessarily available yet.
  SimulateTestUserSigninWithoutRefreshToken();

  CreateSyncService(ProfileSyncService::AUTO_START);

  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();

  // Calling Initialize should cause the service to immediately create and
  // initialize the engine, and configure the DataTypeManager.
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  sync_service()->Initialize();
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));

  // Sync should be considered active, even though there is no refresh token.
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  // Since we're in AUTO_START mode, FirstSetupComplete gets set automatically.
  EXPECT_TRUE(sync_service()->GetUserSettings()->IsFirstSetupComplete());
}

TEST_F(ProfileSyncServiceStartupTest, StartCrosFirstTime) {
  // On ChromeOS, the user is always immediately signed in, but a refresh token
  // isn't necessarily available yet.
  SimulateTestUserSigninWithoutRefreshToken();

  CreateSyncService(ProfileSyncService::AUTO_START);

  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));

  // The primary account is already populated, all that's left to do is provide
  // a refresh token.
  UpdateCredentials();
  sync_service()->Initialize();
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
}

TEST_F(ProfileSyncServiceStartupTest, StartNormal) {
  // We have previously completed the initial Sync setup, and the user is
  // already signed in.
  sync_prefs()->SetFirstSetupComplete();
  SimulateTestUserSignin();

  CreateSyncService(ProfileSyncService::MANUAL_START);
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  // Since all conditions for starting Sync are already fulfilled, calling
  // Initialize should immediately create and initialize the engine and
  // configure the DataTypeManager. In this test, all of these operations are
  // synchronous.
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  sync_service()->Initialize();
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));

  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());

  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
}

TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, StopSync) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  sync_service()->Initialize();

  EXPECT_CALL(*data_type_manager, Stop(syncer::STOP_SYNC));
  sync_service()->GetUserSettings()->SetSyncRequested(false);

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

TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, StopSync) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  sync_service()->Initialize();

  EXPECT_CALL(*data_type_manager, Stop(syncer::STOP_SYNC));
  // On SetSyncRequested(false), the sync service will immediately start up
  // again in transport mode.
  SetUpFakeSyncEngine();
  data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  sync_service()->GetUserSettings()->SetSyncRequested(false);

  // Sync-the-feature is still considered off.
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
}

TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, DisableSync) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  sync_service()->Initialize();

  EXPECT_CALL(*data_type_manager, Stop(syncer::DISABLE_SYNC));
  sync_service()->StopAndClear();

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

TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, DisableSync) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  sync_service()->Initialize();

  // On StopAndClear(), the sync service will immediately start up again in
  // transport mode.
  SetUpFakeSyncEngine();
  data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  sync_service()->StopAndClear();

  // Sync-the-feature is still considered off.
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
}

// Test that we can recover from a case where a bug in the code resulted in
// OnUserChoseDatatypes not being properly called and datatype preferences
// therefore being left unset.
TEST_F(ProfileSyncServiceStartupTest, StartRecoverDatatypePrefs) {
  // Clear the datatype preference fields (simulating bug 154940).
  pref_service()->ClearPref(syncer::prefs::kSyncKeepEverythingSynced);
  syncer::ModelTypeSet user_types = syncer::UserTypes();
  for (syncer::ModelType type : user_types) {
    pref_service()->ClearPref(syncer::SyncPrefs::GetPrefNameForDataType(type));
  }

  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  sync_service()->Initialize();

  EXPECT_TRUE(sync_prefs()->HasKeepEverythingSynced());
}

// Verify that the recovery of datatype preferences doesn't overwrite a valid
// case where only bookmarks are enabled.
TEST_F(ProfileSyncServiceStartupTest, StartDontRecoverDatatypePrefs) {
  // Explicitly set Keep Everything Synced to false and have only bookmarks
  // enabled.
  sync_prefs()->SetDataTypesConfiguration(/*keep_everything_synced=*/false,
                                          syncer::UserTypes(),
                                          {syncer::BOOKMARKS});

  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));

  sync_service()->Initialize();

  EXPECT_FALSE(sync_prefs()->HasKeepEverythingSynced());
}

TEST_F(ProfileSyncServiceStartupTest, ManagedStartup) {
  // Service should not be started by Initialize() since it's managed.
  SimulateTestUserSignin();
  CreateSyncService(ProfileSyncService::MANUAL_START);

  // Disable sync through policy.
  sync_prefs()->SetManagedForTest(true);

  EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _, _)).Times(0);
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .Times(0);
  sync_service()->Initialize();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
            sync_service()->GetDisableReasons());
}

TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest, SwitchManaged) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));
  sync_service()->Initialize();
  EXPECT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());

  // The service should stop when switching to managed mode.
  Mock::VerifyAndClearExpectations(data_type_manager);
  EXPECT_CALL(*data_type_manager, state())
      .WillOnce(Return(DataTypeManager::CONFIGURED));
  EXPECT_CALL(*data_type_manager, Stop(syncer::DISABLE_SYNC));
  sync_prefs()->SetManagedForTest(true);
  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
            sync_service()->GetDisableReasons());
  EXPECT_FALSE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
  // Note that PSS no longer references |data_type_manager| after stopping.

  // When switching back to unmanaged, the state should change but sync should
  // not start automatically because IsFirstSetupComplete() will be false and
  // no setup is in progress.
  // A new DataTypeManager should not be created.
  Mock::VerifyAndClearExpectations(data_type_manager);
  EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
      .Times(0);
  sync_prefs()->SetManagedForTest(false);
  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            sync_service()->GetDisableReasons());
  EXPECT_FALSE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST,
            sync_service()->GetTransportState());
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
}

TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest, SwitchManaged) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));
  sync_service()->Initialize();
  EXPECT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());

  // The service should stop when switching to managed mode.
  Mock::VerifyAndClearExpectations(data_type_manager);
  EXPECT_CALL(*data_type_manager, state())
      .WillOnce(Return(DataTypeManager::CONFIGURED));
  EXPECT_CALL(*data_type_manager, Stop(syncer::DISABLE_SYNC));

  sync_prefs()->SetManagedForTest(true);
  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
            sync_service()->GetDisableReasons());
  EXPECT_FALSE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
  // Note that PSS no longer references |data_type_manager| after stopping.

  // When switching back to unmanaged, Sync-the-transport should start up
  // automatically, which causes (re)creation of SyncEngine and
  // DataTypeManager.
  SetUpFakeSyncEngine();
  Mock::VerifyAndClearExpectations(data_type_manager);
  data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));

  sync_prefs()->SetManagedForTest(false);

  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
            sync_service()->GetDisableReasons());

  EXPECT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  // Sync-the-feature is still considered off.
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
  EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
}

TEST_F(ProfileSyncServiceStartupTest, StartFailure) {
  sync_prefs()->SetFirstSetupComplete();
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  SetUpFakeSyncEngine();
  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  DataTypeManager::ConfigureStatus status = DataTypeManager::ABORTED;
  DataTypeManager::ConfigureResult result(status, syncer::ModelTypeSet());
  EXPECT_CALL(*data_type_manager, Configure(_, _))
      .WillRepeatedly(
          DoAll(InvokeOnConfigureStart(sync_service()),
                InvokeOnConfigureDone(sync_service(),
                                      base::BindRepeating(&SetError), result)));
  EXPECT_CALL(*data_type_manager, state())
      .WillOnce(Return(DataTypeManager::STOPPED));
  ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));
  sync_service()->Initialize();
  EXPECT_TRUE(sync_service()->HasUnrecoverableError());
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
            sync_service()->GetDisableReasons());
}

TEST_F(ProfileSyncServiceStartupTest, StartDownloadFailed) {
  CreateSyncService(ProfileSyncService::MANUAL_START);
  SimulateTestUserSignin();
  FakeSyncEngine* fake_engine = SetUpFakeSyncEngine();
  fake_engine->set_fail_initial_download(true);

  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());

  sync_service()->Initialize();

  auto sync_blocker = sync_service()->GetSetupInProgressHandle();
  sync_blocker.reset();
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());
}

// ChromeOS does not support sign-in after startup (in particular,
// IdentityManager::Observer::OnPrimaryAccountSet never gets called).
#if !defined(OS_CHROMEOS)
TEST_F(ProfileSyncServiceWithoutStandaloneTransportStartupTest,
       FullStartupSequenceFirstTime) {
  // We've never completed startup.
  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());

  MockSyncEngine* sync_engine = SetUpMockSyncEngine();
  EXPECT_CALL(*sync_engine, Initialize(_)).Times(0);

  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::STOPPED));

  // Note: Deferred startup is only enabled if SESSIONS is among the preferred
  // data types.
  CreateSyncService(ProfileSyncService::MANUAL_START,
                    syncer::ModelTypeSet(syncer::SESSIONS));
  sync_service()->Initialize();

  // There is no signed-in user, but nothing else prevents Sync from starting.
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());

  // Sign in. Now Sync is ready to start, just waiting for a prod.
  SimulateTestUserSignin();
  EXPECT_EQ(syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST,
            sync_service()->GetTransportState());

  // Once we give the service a prod by initiating Sync setup, it'll start and
  // initialize the engine. Since this is the initial Sync start, this will not
  // be deferred.
  EXPECT_CALL(*sync_engine, Initialize(_));
  auto setup_in_progress_handle = sync_service()->GetSetupInProgressHandle();
  EXPECT_EQ(syncer::SyncService::TransportState::INITIALIZING,
            sync_service()->GetTransportState());

  // Once the engine calls back and says it's initialized, we're just waiting
  // for the user to finish the initial configuration (choosing data types etc.)
  // before actually syncing data.
  sync_service()->OnEngineInitialized(
      syncer::ModelTypeSet(), syncer::WeakHandle<syncer::JsBackend>(),
      syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), "test-guid",
      "test-session-name", /*success=*/true);
  ASSERT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());

  // Once the user finishes the initial setup, the service can actually start
  // configuring the data types. Just marking the initial setup as complete
  // isn't enough though, because setup is still considered in progress (we
  // haven't released the setup-in-progress handle).
  sync_service()->GetUserSettings()->SetFirstSetupComplete();
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());

  // Releasing the setup in progress handle lets the service actually configure
  // the DataTypeManager.
  EXPECT_CALL(*data_type_manager, Configure(_, _))
      .WillOnce(InvokeWithoutArgs(sync_service(),
                                  &ProfileSyncService::OnConfigureStart));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURING));
  setup_in_progress_handle.reset();
  // While DataTypeManager configuration is ongoing, the overall state is still
  // CONFIGURING.
  EXPECT_EQ(syncer::SyncService::TransportState::CONFIGURING,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());

  // Finally, once the DataTypeManager says it's done with configuration, Sync
  // is actually fully up and running.
  DataTypeManager::ConfigureResult configure_result(
      DataTypeManager::OK, syncer::ModelTypeSet(syncer::SESSIONS));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  sync_service()->OnConfigureDone(configure_result);
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
}

TEST_F(ProfileSyncServiceWithStandaloneTransportStartupTest,
       FullStartupSequenceFirstTime) {
  // We've never completed startup.
  ASSERT_FALSE(sync_prefs()->IsFirstSetupComplete());

  MockSyncEngine* sync_engine = SetUpMockSyncEngine();
  EXPECT_CALL(*sync_engine, Initialize(_)).Times(0);

  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::STOPPED));

  // Note: Deferred startup is only enabled if SESSIONS is among the preferred
  // data types.
  CreateSyncService(ProfileSyncService::MANUAL_START,
                    syncer::ModelTypeSet(syncer::SESSIONS));
  sync_service()->Initialize();

  // There is no signed-in user, but nothing else prevents Sync from starting.
  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
            sync_service()->GetDisableReasons());
  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
            sync_service()->GetTransportState());

  // Sign in. Now Sync is ready to start, just waiting for a prod.
  SimulateTestUserSignin();
  EXPECT_EQ(syncer::SyncService::TransportState::START_DEFERRED,
            sync_service()->GetTransportState());

  // Once we give the service a prod by initiating Sync setup, it'll start and
  // initialize the engine. Since this is the initial Sync start, this will not
  // be deferred.
  EXPECT_CALL(*sync_engine, Initialize(_));
  auto setup_in_progress_handle = sync_service()->GetSetupInProgressHandle();
  EXPECT_EQ(syncer::SyncService::TransportState::INITIALIZING,
            sync_service()->GetTransportState());

  // Once the engine calls back and says it's initialized, we're just waiting
  // for the user to finish the initial configuration (choosing data types etc.)
  // before actually syncing data.
  sync_service()->OnEngineInitialized(
      syncer::ModelTypeSet(), syncer::WeakHandle<syncer::JsBackend>(),
      syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), "test-guid",
      "test-session-name", /*success=*/true);
  ASSERT_TRUE(sync_service()->IsEngineInitialized());
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());
  EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());

  // Once the user finishes the initial setup, the service can actually start
  // configuring the data types. Just marking the initial setup as complete
  // isn't enough though, because setup is still considered in progress (we
  // haven't released the setup-in-progress handle).
  sync_service()->GetUserSettings()->SetFirstSetupComplete();
  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());

  // Releasing the setup in progress handle lets the service actually configure
  // the DataTypeManager.
  EXPECT_CALL(*data_type_manager, Configure(_, _))
      .WillOnce(InvokeWithoutArgs(sync_service(),
                                  &ProfileSyncService::OnConfigureStart));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURING));
  setup_in_progress_handle.reset();
  // While DataTypeManager configuration is ongoing, the overall state is still
  // CONFIGURING.
  EXPECT_EQ(syncer::SyncService::TransportState::CONFIGURING,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());

  // Finally, once the DataTypeManager says it's done with configuration, Sync
  // is actually fully up and running.
  DataTypeManager::ConfigureResult configure_result(
      DataTypeManager::OK, syncer::ModelTypeSet(syncer::SESSIONS));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  sync_service()->OnConfigureDone(configure_result);
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
  EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
}
#endif  // OS_CHROMEOS

TEST_F(ProfileSyncServiceStartupTest, FullStartupSequenceNthTime) {
  // The user is already signed in and has completed Sync setup before.
  SimulateTestUserSignin();
  sync_prefs()->SetFirstSetupComplete();

  MockSyncEngine* sync_engine = SetUpMockSyncEngine();
  EXPECT_CALL(*sync_engine, Initialize(_)).Times(0);

  DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
  EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::STOPPED));

  // Note: Deferred startup is only enabled if SESSIONS is among the preferred
  // data types.
  CreateSyncService(ProfileSyncService::MANUAL_START,
                    syncer::ModelTypeSet(syncer::SESSIONS));
  sync_service()->Initialize();

  // Nothing is preventing Sync from starting, but it should be deferred so as
  // to now slow down browser startup.
  EXPECT_EQ(syncer::SyncService::TransportState::START_DEFERRED,
            sync_service()->GetTransportState());

  // Wait for the deferred startup timer to expire. The Sync service will start
  // and initialize the engine.
  EXPECT_CALL(*sync_engine, Initialize(_));
  FastForwardUntilNoTasksRemain();
  EXPECT_EQ(syncer::SyncService::TransportState::INITIALIZING,
            sync_service()->GetTransportState());

  // Once the engine calls back and says it's initialized, the DataTypeManager
  // will get configured, since initial setup is already done.
  EXPECT_CALL(*data_type_manager, Configure(_, _));
  sync_service()->OnEngineInitialized(
      syncer::ModelTypeSet(), syncer::WeakHandle<syncer::JsBackend>(),
      syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), "test-guid",
      "test-session-name", /*success=*/true);
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURING));
  EXPECT_EQ(syncer::SyncService::TransportState::CONFIGURING,
            sync_service()->GetTransportState());

  // Finally, once the DataTypeManager says it's done with configuration, Sync
  // is actually fully up and running.
  DataTypeManager::ConfigureResult configure_result(
      DataTypeManager::OK, syncer::ModelTypeSet(syncer::SESSIONS));
  ON_CALL(*data_type_manager, state())
      .WillByDefault(Return(DataTypeManager::CONFIGURED));
  sync_service()->OnConfigureDone(configure_result);
  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
            sync_service()->GetTransportState());
}

}  // namespace browser_sync
