#include "components/sync/driver/startup_controller.h"
#include <memory>
#include "base/functional/bind.h"
#include "base/test/task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
class StartupControllerTest : public testing::Test {
public:
StartupControllerTest() = default;
void SetUp() override {
controller_ = std::make_unique<StartupController>(
base::BindRepeating(&StartupControllerTest::GetPreferredDataTypes,
base::Unretained(this)),
base::BindRepeating(&StartupControllerTest::ShouldStart,
base::Unretained(this)),
base::BindRepeating(&StartupControllerTest::FakeStartBackend,
base::Unretained(this)));
}
void SetPreferredDataTypes(const ModelTypeSet& types) {
preferred_types_ = types;
}
void SetShouldStart(bool should_start) { should_start_ = should_start; }
void ExpectStarted() {
task_environment_.RunUntilIdle();
EXPECT_TRUE(started());
EXPECT_EQ(StartupController::State::STARTED, controller()->GetState());
}
void ExpectStartDeferred() {
task_environment_.RunUntilIdle();
EXPECT_FALSE(started());
EXPECT_EQ(StartupController::State::STARTING_DEFERRED,
controller()->GetState());
}
void ExpectNotStarted() {
task_environment_.RunUntilIdle();
EXPECT_FALSE(started());
EXPECT_EQ(StartupController::State::NOT_STARTED, controller()->GetState());
}
bool started() const { return started_; }
void clear_started() { started_ = false; }
StartupController* controller() { return controller_.get(); }
void RunDeferredTasks() { task_environment_.FastForwardUntilNoTasksRemain(); }
private:
ModelTypeSet GetPreferredDataTypes() { return preferred_types_; }
bool ShouldStart() { return should_start_; }
void FakeStartBackend() { started_ = true; }
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
ModelTypeSet preferred_types_ = UserTypes();
bool should_start_ = false;
bool started_ = false;
std::unique_ptr<StartupController> controller_;
};
TEST_F(StartupControllerTest, ShouldNotStart) {
controller()->TryStart(false);
ExpectNotStarted();
controller()->TryStart(true);
ExpectNotStarted();
}
TEST_F(StartupControllerTest, DefersByDefault) {
SetShouldStart(true);
controller()->TryStart(false);
ExpectStartDeferred();
}
TEST_F(StartupControllerTest, NoDeferralDataTypeTrigger) {
SetShouldStart(true);
controller()->OnDataTypeRequestsSyncStartup(SESSIONS);
ExpectStarted();
}
TEST_F(StartupControllerTest, DataTypeTriggerInterruptsDeferral) {
SetShouldStart(true);
controller()->TryStart(false);
ExpectStartDeferred();
controller()->OnDataTypeRequestsSyncStartup(SESSIONS);
ExpectStarted();
clear_started();
RunDeferredTasks();
EXPECT_FALSE(started());
}
TEST_F(StartupControllerTest, FallbackTimer) {
SetShouldStart(true);
controller()->TryStart(false);
ExpectStartDeferred();
RunDeferredTasks();
ExpectStarted();
}
TEST_F(StartupControllerTest, NoDeferralWithoutSessionsSync) {
ModelTypeSet types(UserTypes());
types.Remove(SESSIONS);
types.Remove(PROXY_TABS);
types.Remove(TYPED_URLS);
types.Remove(SUPERVISED_USER_SETTINGS);
SetPreferredDataTypes(types);
SetShouldStart(true);
controller()->TryStart(false);
ExpectStarted();
}
TEST_F(StartupControllerTest, FallbackTimerWaits) {
controller()->TryStart(false);
ExpectNotStarted();
RunDeferredTasks();
ExpectNotStarted();
}
TEST_F(StartupControllerTest, NoDeferralIfForceImmediate) {
SetShouldStart(true);
ExpectNotStarted();
controller()->TryStart(true);
ExpectStarted();
}
TEST_F(StartupControllerTest, ForceImmediateInterruptsDeferral) {
SetShouldStart(true);
controller()->TryStart(false);
ExpectStartDeferred();
controller()->TryStart(true);
ExpectStarted();
}
}