| Index: chrome/browser/extensions/settings/settings_sync_unittest.cc
|
| diff --git a/chrome/browser/extensions/settings/settings_sync_unittest.cc b/chrome/browser/extensions/settings/settings_sync_unittest.cc
|
| index 5cf90399648e184e3f7f231f17f3de6334968f02..2f22f57c89e6696fca0376fcc72a06772ad85a8a 100644
|
| --- a/chrome/browser/extensions/settings/settings_sync_unittest.cc
|
| +++ b/chrome/browser/extensions/settings/settings_sync_unittest.cc
|
| @@ -11,19 +11,22 @@
|
| #include "base/message_loop.h"
|
| #include "base/scoped_temp_dir.h"
|
| #include "base/task.h"
|
| +#include "chrome/browser/extensions/settings/failing_settings_storage.h"
|
| #include "chrome/browser/extensions/settings/settings_frontend.h"
|
| #include "chrome/browser/extensions/settings/settings_storage_cache.h"
|
| +#include "chrome/browser/extensions/settings/settings_storage_factory.h"
|
| #include "chrome/browser/extensions/settings/settings_sync_util.h"
|
| -#include "chrome/browser/extensions/settings/syncable_settings_storage.h"
|
| #include "chrome/browser/extensions/settings/settings_test_util.h"
|
| +#include "chrome/browser/extensions/settings/syncable_settings_storage.h"
|
| +#include "chrome/browser/extensions/settings/testing_settings_storage.h"
|
| #include "chrome/browser/sync/api/sync_change_processor.h"
|
| #include "content/test/test_browser_thread.h"
|
|
|
| -namespace extensions {
|
| +// TODO(kalman): Integration tests for sync.
|
|
|
| using content::BrowserThread;
|
|
|
| -// TODO(kalman): Integration tests for sync.
|
| +namespace extensions {
|
|
|
| using namespace settings_test_util;
|
|
|
| @@ -77,9 +80,18 @@ testing::AssertionResult SettingsEq(
|
| // being converted to the more useful SettingSyncData via changes().
|
| class MockSyncChangeProcessor : public SyncChangeProcessor {
|
| public:
|
| + MockSyncChangeProcessor() : fail_all_requests_(false) {}
|
| +
|
| + // SyncChangeProcessor implementation.
|
| virtual SyncError ProcessSyncChanges(
|
| const tracked_objects::Location& from_here,
|
| const SyncChangeList& change_list) OVERRIDE {
|
| + if (fail_all_requests_) {
|
| + return SyncError(
|
| + FROM_HERE,
|
| + "MockSyncChangeProcessor: configured to fail",
|
| + change_list[0].sync_data().GetDataType());
|
| + }
|
| for (SyncChangeList::const_iterator it = change_list.begin();
|
| it != change_list.end(); ++it) {
|
| changes_.push_back(SettingSyncData(*it));
|
| @@ -87,12 +99,18 @@ class MockSyncChangeProcessor : public SyncChangeProcessor {
|
| return SyncError();
|
| }
|
|
|
| + // Mock methods.
|
| +
|
| const SettingSyncDataList& changes() { return changes_; }
|
|
|
| void ClearChanges() {
|
| changes_.clear();
|
| }
|
|
|
| + void SetFailAllRequests(bool fail_all_requests) {
|
| + fail_all_requests_ = fail_all_requests;
|
| + }
|
| +
|
| // Returns the only change for a given extension setting. If there is not
|
| // exactly 1 change for that key, a test assertion will fail.
|
| SettingSyncData GetOnlyChange(
|
| @@ -119,6 +137,31 @@ class MockSyncChangeProcessor : public SyncChangeProcessor {
|
|
|
| private:
|
| SettingSyncDataList changes_;
|
| + bool fail_all_requests_;
|
| +};
|
| +
|
| +// SettingsStorageFactory which always returns TestingSettingsStorage objects,
|
| +// and allows individually created objects to be returned.
|
| +class TestingSettingsStorageFactory : public SettingsStorageFactory {
|
| + public:
|
| + TestingSettingsStorage* GetExisting(const std::string& extension_id) {
|
| + DCHECK(created_.count(extension_id));
|
| + return created_[extension_id];
|
| + }
|
| +
|
| + // SettingsStorageFactory implementation.
|
| + virtual SettingsStorage* Create(
|
| + const FilePath& base_path, const std::string& extension_id) OVERRIDE {
|
| + TestingSettingsStorage* new_storage = new TestingSettingsStorage();
|
| + DCHECK(!created_.count(extension_id));
|
| + created_[extension_id] = new_storage;
|
| + return new_storage;
|
| + }
|
| +
|
| + private:
|
| + // None of these storage areas are owned by this factory, so care must be
|
| + // taken when calling GetExisting.
|
| + std::map<std::string, TestingSettingsStorage*> created_;
|
| };
|
|
|
| void AssignSettingsService(SyncableService** dst, SyncableService* src) {
|
| @@ -136,7 +179,9 @@ class ExtensionSettingsSyncTest : public testing::Test {
|
| virtual void SetUp() OVERRIDE {
|
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| profile_.reset(new MockProfile(temp_dir_.path()));
|
| - frontend_.reset(SettingsFrontend::Create(profile_.get()));
|
| + storage_factory_ =
|
| + new ScopedSettingsStorageFactory(new SettingsLeveldbStorage::Factory());
|
| + frontend_.reset(SettingsFrontend::Create(storage_factory_, profile_.get()));
|
| }
|
|
|
| virtual void TearDown() OVERRIDE {
|
| @@ -186,6 +231,9 @@ class ExtensionSettingsSyncTest : public testing::Test {
|
| MockSyncChangeProcessor sync_;
|
| scoped_ptr<MockProfile> profile_;
|
| scoped_ptr<SettingsFrontend> frontend_;
|
| +
|
| + // Owned by |frontend_|.
|
| + ScopedSettingsStorageFactory* storage_factory_;
|
| };
|
|
|
| // Get a semblance of coverage for both EXTENSION_SETTINGS and APP_SETTINGS
|
| @@ -587,4 +635,615 @@ TEST_F(ExtensionSettingsSyncTest, ExtensionAndAppSettingsSyncSeparately) {
|
| ASSERT_EQ(0u, sync_.changes().size());
|
| }
|
|
|
| +TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
|
| + syncable::ModelType model_type = syncable::EXTENSION_SETTINGS;
|
| + Extension::Type type = Extension::TYPE_EXTENSION;
|
| +
|
| + StringValue fooValue("fooValue");
|
| + StringValue barValue("barValue");
|
| +
|
| + // There is a bit of a convoluted method to get storage areas that can fail;
|
| + // hand out TestingSettingsStorage object then toggle them failing/succeeding
|
| + // as necessary.
|
| + TestingSettingsStorageFactory* testing_factory =
|
| + new TestingSettingsStorageFactory();
|
| + storage_factory_->Reset(testing_factory);
|
| +
|
| + SettingsStorage* good = AddExtensionAndGetStorage("good", type);
|
| + SettingsStorage* bad = AddExtensionAndGetStorage("bad", type);
|
| +
|
| + // Make bad fail for incoming sync changes.
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(true);
|
| + {
|
| + SyncDataList sync_data;
|
| + sync_data.push_back(
|
| + settings_sync_util::CreateData("good", "foo", fooValue));
|
| + sync_data.push_back(
|
| + settings_sync_util::CreateData("bad", "foo", fooValue));
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, sync_data, &sync_);
|
| + }
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(false);
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Changes made to good should be sent to sync, changes from bad shouldn't.
|
| + sync_.ClearChanges();
|
| + good->Set("bar", barValue);
|
| + bad->Set("bar", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Changes received from sync should go to good but not bad (even when it's
|
| + // not failing).
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("good", "foo", barValue));
|
| + // (Sending UPDATE here even though it's adding, since that's what the state
|
| + // of sync is. In any case, it won't work.)
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("bad", "foo", barValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Changes made to bad still shouldn't go to sync, even though it didn't fail
|
| + // last time.
|
| + sync_.ClearChanges();
|
| + good->Set("bar", fooValue);
|
| + bad->Set("bar", fooValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + dict.Set("bar", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("bar", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Failing ProcessSyncChanges shouldn't go to the storage.
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(true);
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("good", "foo", fooValue));
|
| + // (Ditto.)
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("bad", "foo", fooValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(false);
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + dict.Set("bar", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("bar", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Restarting sync should make bad start syncing again.
|
| + sync_.ClearChanges();
|
| + GetSyncableService(model_type)->StopSyncing(model_type);
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| +
|
| + // Local settings will have been pushed to sync, since it's empty (in this
|
| + // test; presumably it wouldn't be live, since we've been getting changes).
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "bar").change_type());
|
| + EXPECT_EQ(3u, sync_.changes().size());
|
| +
|
| + // Live local changes now get pushed, too.
|
| + sync_.ClearChanges();
|
| + good->Set("bar", barValue);
|
| + bad->Set("bar", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("bad", "bar").change_type());
|
| + EXPECT_EQ(2u, sync_.changes().size());
|
| +
|
| + // And ProcessSyncChanges work, too.
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("good", "bar", fooValue));
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("bad", "bar", fooValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + dict.Set("bar", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("bar", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +}
|
| +
|
| +TEST_F(ExtensionSettingsSyncTest, FailingProcessChangesDisablesSync) {
|
| + // The test above tests a failing ProcessSyncChanges too, but here test with
|
| + // an initially passing MergeDataAndStartSyncing.
|
| + syncable::ModelType model_type = syncable::APP_SETTINGS;
|
| + Extension::Type type = Extension::TYPE_PACKAGED_APP;
|
| +
|
| + StringValue fooValue("fooValue");
|
| + StringValue barValue("barValue");
|
| +
|
| + TestingSettingsStorageFactory* testing_factory =
|
| + new TestingSettingsStorageFactory();
|
| + storage_factory_->Reset(testing_factory);
|
| +
|
| + SettingsStorage* good = AddExtensionAndGetStorage("good", type);
|
| + SettingsStorage* bad = AddExtensionAndGetStorage("bad", type);
|
| +
|
| + // Unlike before, initially succeeding MergeDataAndStartSyncing.
|
| + {
|
| + SyncDataList sync_data;
|
| + sync_data.push_back(
|
| + settings_sync_util::CreateData("good", "foo", fooValue));
|
| + sync_data.push_back(
|
| + settings_sync_util::CreateData("bad", "foo", fooValue));
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, sync_data, &sync_);
|
| + }
|
| +
|
| + EXPECT_EQ(0u, sync_.changes().size());
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Now fail ProcessSyncChanges for bad.
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(true);
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("good", "bar", barValue));
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("bad", "bar", barValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(false);
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // No more changes sent to sync for bad.
|
| + sync_.ClearChanges();
|
| + good->Set("foo", barValue);
|
| + bad->Set("foo", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + // No more changes received from sync should go to bad.
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("good", "foo", fooValue));
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("bad", "foo", fooValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +}
|
| +
|
| +TEST_F(ExtensionSettingsSyncTest, FailingGetAllSyncDataDoesntStopSync) {
|
| + syncable::ModelType model_type = syncable::EXTENSION_SETTINGS;
|
| + Extension::Type type = Extension::TYPE_EXTENSION;
|
| +
|
| + StringValue fooValue("fooValue");
|
| + StringValue barValue("barValue");
|
| +
|
| + TestingSettingsStorageFactory* testing_factory =
|
| + new TestingSettingsStorageFactory();
|
| + storage_factory_->Reset(testing_factory);
|
| +
|
| + SettingsStorage* good = AddExtensionAndGetStorage("good", type);
|
| + SettingsStorage* bad = AddExtensionAndGetStorage("bad", type);
|
| +
|
| + good->Set("foo", fooValue);
|
| + bad->Set("foo", fooValue);
|
| +
|
| + // Even though bad will fail to get all sync data, sync data should still
|
| + // include that from good.
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(true);
|
| + {
|
| + SyncDataList all_sync_data =
|
| + GetSyncableService(model_type)->GetAllSyncData(model_type);
|
| + EXPECT_EQ(1u, all_sync_data.size());
|
| + EXPECT_EQ("good/foo", all_sync_data[0].GetTag());
|
| + }
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(false);
|
| +
|
| + // Sync shouldn't be disabled for good (nor bad -- but this is unimportant).
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "foo").change_type());
|
| + EXPECT_EQ(2u, sync_.changes().size());
|
| +
|
| + sync_.ClearChanges();
|
| + good->Set("bar", barValue);
|
| + bad->Set("bar", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "bar").change_type());
|
| + EXPECT_EQ(2u, sync_.changes().size());
|
| +}
|
| +
|
| +TEST_F(ExtensionSettingsSyncTest, FailureToReadChangesToPushDisablesSync) {
|
| + syncable::ModelType model_type = syncable::APP_SETTINGS;
|
| + Extension::Type type = Extension::TYPE_PACKAGED_APP;
|
| +
|
| + StringValue fooValue("fooValue");
|
| + StringValue barValue("barValue");
|
| +
|
| + TestingSettingsStorageFactory* testing_factory =
|
| + new TestingSettingsStorageFactory();
|
| + storage_factory_->Reset(testing_factory);
|
| +
|
| + SettingsStorage* good = AddExtensionAndGetStorage("good", type);
|
| + SettingsStorage* bad = AddExtensionAndGetStorage("bad", type);
|
| +
|
| + good->Set("foo", fooValue);
|
| + bad->Set("foo", fooValue);
|
| +
|
| + // good will successfully push foo:fooValue to sync, but bad will fail to
|
| + // get them so won't.
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(true);
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| + testing_factory->GetExisting("bad")->SetFailAllRequests(false);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + // bad should now be disabled for sync.
|
| + sync_.ClearChanges();
|
| + good->Set("bar", barValue);
|
| + bad->Set("bar", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateUpdate("good", "foo", barValue));
|
| + // (Sending ADD here even though it's updating, since that's what the state
|
| + // of sync is. In any case, it won't work.)
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("bad", "foo", barValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", fooValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Re-enabling sync without failing should cause the local changes from bad
|
| + // to be pushed to sync successfully, as should future changes to bad.
|
| + sync_.ClearChanges();
|
| + GetSyncableService(model_type)->StopSyncing(model_type);
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "bar").change_type());
|
| + EXPECT_EQ(4u, sync_.changes().size());
|
| +
|
| + sync_.ClearChanges();
|
| + good->Set("bar", fooValue);
|
| + bad->Set("bar", fooValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(2u, sync_.changes().size());
|
| +}
|
| +
|
| +TEST_F(ExtensionSettingsSyncTest, FailureToPushLocalStateDisablesSync) {
|
| + syncable::ModelType model_type = syncable::EXTENSION_SETTINGS;
|
| + Extension::Type type = Extension::TYPE_EXTENSION;
|
| +
|
| + StringValue fooValue("fooValue");
|
| + StringValue barValue("barValue");
|
| +
|
| + TestingSettingsStorageFactory* testing_factory =
|
| + new TestingSettingsStorageFactory();
|
| + storage_factory_->Reset(testing_factory);
|
| +
|
| + SettingsStorage* good = AddExtensionAndGetStorage("good", type);
|
| + SettingsStorage* bad = AddExtensionAndGetStorage("bad", type);
|
| +
|
| + // Only set bad; setting good will cause it to fail below.
|
| + bad->Set("foo", fooValue);
|
| +
|
| + sync_.SetFailAllRequests(true);
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| + sync_.SetFailAllRequests(false);
|
| +
|
| + // Changes from good will be send to sync, changes from bad won't.
|
| + sync_.ClearChanges();
|
| + good->Set("foo", barValue);
|
| + bad->Set("foo", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + // Changes from sync will be sent to good, not to bad.
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("good", "bar", barValue));
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("bad", "bar", barValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Restarting sync makes everything work again.
|
| + sync_.ClearChanges();
|
| + GetSyncableService(model_type)->StopSyncing(model_type);
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "foo").change_type());
|
| + EXPECT_EQ(3u, sync_.changes().size());
|
| +
|
| + sync_.ClearChanges();
|
| + good->Set("foo", fooValue);
|
| + bad->Set("foo", fooValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(2u, sync_.changes().size());
|
| +}
|
| +
|
| +TEST_F(ExtensionSettingsSyncTest, FailureToPushLocalChangeDisablesSync) {
|
| + syncable::ModelType model_type = syncable::EXTENSION_SETTINGS;
|
| + Extension::Type type = Extension::TYPE_EXTENSION;
|
| +
|
| + StringValue fooValue("fooValue");
|
| + StringValue barValue("barValue");
|
| +
|
| + TestingSettingsStorageFactory* testing_factory =
|
| + new TestingSettingsStorageFactory();
|
| + storage_factory_->Reset(testing_factory);
|
| +
|
| + SettingsStorage* good = AddExtensionAndGetStorage("good", type);
|
| + SettingsStorage* bad = AddExtensionAndGetStorage("bad", type);
|
| +
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| +
|
| + // bad will fail to send changes.
|
| + good->Set("foo", fooValue);
|
| + sync_.SetFailAllRequests(true);
|
| + bad->Set("foo", fooValue);
|
| + sync_.SetFailAllRequests(false);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + // No further changes should be sent from bad.
|
| + sync_.ClearChanges();
|
| + good->Set("foo", barValue);
|
| + bad->Set("foo", barValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(1u, sync_.changes().size());
|
| +
|
| + // Changes from sync will be sent to good, not to bad.
|
| + {
|
| + SyncChangeList change_list;
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("good", "bar", barValue));
|
| + change_list.push_back(
|
| + settings_sync_util::CreateAdd("bad", "bar", barValue));
|
| + GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
|
| + }
|
| +
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + dict.Set("bar", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
|
| + }
|
| + {
|
| + DictionaryValue dict;
|
| + dict.Set("foo", barValue.DeepCopy());
|
| + EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
|
| + }
|
| +
|
| + // Restarting sync makes everything work again.
|
| + sync_.ClearChanges();
|
| + GetSyncableService(model_type)->StopSyncing(model_type);
|
| + GetSyncableService(model_type)->MergeDataAndStartSyncing(
|
| + model_type, SyncDataList(), &sync_);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("good", "bar").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_ADD,
|
| + sync_.GetOnlyChange("bad", "foo").change_type());
|
| + EXPECT_EQ(3u, sync_.changes().size());
|
| +
|
| + sync_.ClearChanges();
|
| + good->Set("foo", fooValue);
|
| + bad->Set("foo", fooValue);
|
| +
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(
|
| + SyncChange::ACTION_UPDATE,
|
| + sync_.GetOnlyChange("good", "foo").change_type());
|
| + EXPECT_EQ(2u, sync_.changes().size());
|
| +}
|
| +
|
| } // namespace extensions
|
|
|