diff options
author | tim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-20 01:59:35 +0000 |
---|---|---|
committer | tim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-20 01:59:35 +0000 |
commit | dc55625cce6709a969635777c8df19c1e9b055a2 (patch) | |
tree | 4e005970bc1382f8765c19ac5b011f10a4367261 /chrome/browser/sync/backend_migrator_unittest.cc | |
parent | e0e087f07253fe3d95aeafdfa337463d4334b7fa (diff) | |
download | chromium_src-dc55625cce6709a969635777c8df19c1e9b055a2.zip chromium_src-dc55625cce6709a969635777c8df19c1e9b055a2.tar.gz chromium_src-dc55625cce6709a969635777c8df19c1e9b055a2.tar.bz2 |
sync: add a BackendMigrator class to perform migration flow.
The rest of the change (more innocent than it looks) is mostly callback plumbing to make the long trek from SyncerProtoUtil up to ProfileSyncService.
BUG=79247
TEST=BackendMigratorTest
Review URL: http://codereview.chromium.org/6858002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82215 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync/backend_migrator_unittest.cc')
-rw-r--r-- | chrome/browser/sync/backend_migrator_unittest.cc | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/chrome/browser/sync/backend_migrator_unittest.cc b/chrome/browser/sync/backend_migrator_unittest.cc new file mode 100644 index 0000000..39b2ef0 --- /dev/null +++ b/chrome/browser/sync/backend_migrator_unittest.cc @@ -0,0 +1,267 @@ +// Copyright (c) 2011 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 "chrome/browser/sync/backend_migrator.h" + +#include "chrome/browser/sync/glue/data_type_manager_mock.h" +#include "chrome/browser/sync/profile_sync_service_mock.h" +#include "chrome/browser/sync/sessions/session_state.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::Eq; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::SetArgumentPointee; + +namespace browser_sync { + +using sessions::ErrorCounters; +using sessions::SyncerStatus; +using sessions::SyncSessionSnapshot; + +class BackendMigratorTest : public testing::Test { + public: + BackendMigratorTest() { } + virtual ~BackendMigratorTest() { } + + virtual void SetUp() { + Mock::VerifyAndClear(manager()); + Mock::VerifyAndClear(&service_); + preferred_types_.insert(syncable::BOOKMARKS); + preferred_types_.insert(syncable::PREFERENCES); + preferred_types_.insert(syncable::AUTOFILL); + + ON_CALL(service_, GetPreferredDataTypes(_)). + WillByDefault(SetArgumentPointee<0>(preferred_types_)); + } + + void ReturnEmptyProgressMarkersInSnapshot() { + ReturnNonEmptyProgressMarkersInSnapshot(syncable::ModelTypeSet()); + } + + void ReturnNonEmptyProgressMarkersInSnapshot( + const syncable::ModelTypeSet& for_types) { + std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; + for (syncable::ModelTypeSet::const_iterator it = for_types.begin(); + it != for_types.end(); ++it) { + download_progress_markers[*it] = "foobar"; + } + + snap_.reset(new SyncSessionSnapshot(SyncerStatus(), ErrorCounters(), + 0, false, syncable::ModelTypeBitSet(), download_progress_markers, + false, false, 0, 0, false, sessions::SyncSourceInfo())); + EXPECT_CALL(service_, GetLastSessionSnapshot()) + .WillOnce(Return(snap_.get())); + } + + void SendConfigureDone(DataTypeManager::ConfigureResult result, + const syncable::ModelTypeSet& types) { + DataTypeManager::ConfigureResultWithErrorLocation result_with_location( + result, FROM_HERE, types); + NotificationService::current()->Notify( + NotificationType::SYNC_CONFIGURE_DONE, + Source<DataTypeManager>(&manager_), + Details<DataTypeManager::ConfigureResultWithErrorLocation>( + &result_with_location)); + } + + ProfileSyncService* service() { return &service_; } + DataTypeManagerMock* manager() { return &manager_; } + const syncable::ModelTypeSet& preferred_types() { return preferred_types_; } + void RemovePreferredType(syncable::ModelType type) { + preferred_types_.erase(type); + Mock::VerifyAndClear(&service_); + ON_CALL(service_, GetPreferredDataTypes(_)). + WillByDefault(SetArgumentPointee<0>(preferred_types_)); + } + private: + scoped_ptr<SyncSessionSnapshot> snap_; + syncable::ModelTypeSet preferred_types_; + NiceMock<ProfileSyncServiceMock> service_; + NiceMock<DataTypeManagerMock> manager_; +}; + +// Test that in the normal case a migration does transition through each state +// and wind up back in IDLE. +TEST_F(BackendMigratorTest, Sanity) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate, difference; + to_migrate.insert(syncable::PREFERENCES); + difference.insert(syncable::AUTOFILL); + difference.insert(syncable::BOOKMARKS); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(_)); + + migrator.MigrateTypes(to_migrate); + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); + + SendConfigureDone(DataTypeManager::OK, difference); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); + + ReturnEmptyProgressMarkersInSnapshot(); + EXPECT_CALL(*manager(), Configure(preferred_types())); + migrator.OnStateChanged(); + EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state()); + + SendConfigureDone(DataTypeManager::OK, preferred_types()); + EXPECT_EQ(BackendMigrator::IDLE, migrator.state()); +} + +// Test that the migrator waits for the data type manager to be idle before +// starting a migration. +TEST_F(BackendMigratorTest, WaitToStart) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate; + to_migrate.insert(syncable::PREFERENCES); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURING)); + EXPECT_CALL(*manager(), Configure(_)).Times(0); + migrator.MigrateTypes(to_migrate); + EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator.state()); + + Mock::VerifyAndClearExpectations(manager()); + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(_)); + SendConfigureDone(DataTypeManager::OK, syncable::ModelTypeSet()); + + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); +} + +// Test that the migrator can cope with a migration request while a migration +// is in progress. +TEST_F(BackendMigratorTest, RestartMigration) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate1, to_migrate2, bookmarks; + to_migrate1.insert(syncable::PREFERENCES); + to_migrate2.insert(syncable::AUTOFILL); + bookmarks.insert(syncable::BOOKMARKS); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(_)).Times(1); + migrator.MigrateTypes(to_migrate1); + + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); + migrator.MigrateTypes(to_migrate2); + + syncable::ModelTypeSet difference1; + std::set_difference(preferred_types().begin(), preferred_types().end(), + to_migrate1.begin(), to_migrate1.end(), + std::inserter(difference1, difference1.end())); + + Mock::VerifyAndClearExpectations(manager()); + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(bookmarks)); + SendConfigureDone(DataTypeManager::OK, difference1); + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); + + SendConfigureDone(DataTypeManager::OK, bookmarks); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); +} + +// Test that an external invocation of Configure(...) during a migration results +// in a migration reattempt. +TEST_F(BackendMigratorTest, InterruptedWhileDisablingTypes) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate; + syncable::ModelTypeSet difference; + to_migrate.insert(syncable::PREFERENCES); + difference.insert(syncable::AUTOFILL); + difference.insert(syncable::BOOKMARKS); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(difference)); + migrator.MigrateTypes(to_migrate); + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); + + Mock::VerifyAndClearExpectations(manager()); + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(difference)); + SendConfigureDone(DataTypeManager::OK, preferred_types()); + + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); +} + +// Test that spurious OnStateChanged events don't confuse the migrator while +// it's waiting for disabled types to have been purged from the sync db. +TEST_F(BackendMigratorTest, WaitingForPurge) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate, difference; + to_migrate.insert(syncable::PREFERENCES); + to_migrate.insert(syncable::AUTOFILL); + difference.insert(syncable::BOOKMARKS); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(_)); + migrator.MigrateTypes(to_migrate); + SendConfigureDone(DataTypeManager::OK, difference); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); + + ReturnNonEmptyProgressMarkersInSnapshot(to_migrate); + migrator.OnStateChanged(); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); + + syncable::ModelTypeSet prefs; + prefs.insert(syncable::PREFERENCES); + ReturnNonEmptyProgressMarkersInSnapshot(prefs); + migrator.OnStateChanged(); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); + + syncable::ModelTypeSet bookmarks; + bookmarks.insert(syncable::BOOKMARKS); + ReturnNonEmptyProgressMarkersInSnapshot(bookmarks); + EXPECT_CALL(*manager(), Configure(preferred_types())); + migrator.OnStateChanged(); + EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state()); +} + +TEST_F(BackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate; + to_migrate.insert(syncable::PREFERENCES); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(_)); + migrator.MigrateTypes(to_migrate); + + RemovePreferredType(syncable::PREFERENCES); + SendConfigureDone(DataTypeManager::OK, preferred_types()); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); + + Mock::VerifyAndClearExpectations(manager()); + ReturnEmptyProgressMarkersInSnapshot(); + EXPECT_CALL(*manager(), Configure(preferred_types())); + migrator.OnStateChanged(); + + EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state()); + SendConfigureDone(DataTypeManager::OK, preferred_types()); + EXPECT_EQ(BackendMigrator::IDLE, migrator.state()); +} + +TEST_F(BackendMigratorTest, ConfigureFailure) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate; + to_migrate.insert(syncable::PREFERENCES); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + EXPECT_CALL(*manager(), Configure(_)).Times(1); + migrator.MigrateTypes(to_migrate); + SendConfigureDone(DataTypeManager::ABORTED, syncable::ModelTypeSet()); + EXPECT_EQ(BackendMigrator::IDLE, migrator.state()); +} + +}; // namespace browser_sync |