summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/backend_migrator_unittest.cc
diff options
context:
space:
mode:
authortim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-20 01:59:35 +0000
committertim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-20 01:59:35 +0000
commitdc55625cce6709a969635777c8df19c1e9b055a2 (patch)
tree4e005970bc1382f8765c19ac5b011f10a4367261 /chrome/browser/sync/backend_migrator_unittest.cc
parente0e087f07253fe3d95aeafdfa337463d4334b7fa (diff)
downloadchromium_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.cc267
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