| Index: chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
|
| diff --git a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
|
| index 6ddd813469007c867d6edb3d85f179e87b0b35e4..0c1d6b3db03386ef3255d7ec7b2ac4841e0cb86a 100644
|
| --- a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
|
| +++ b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
|
| @@ -12,6 +12,7 @@
|
| #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
|
| #include "chrome/browser/sync/test/integration/sync_test.h"
|
| #include "components/browser_sync/browser/profile_sync_components_factory_impl.h"
|
| +#include "components/browser_sync/browser/profile_sync_service.h"
|
| #include "components/sync/api/fake_model_type_service.h"
|
|
|
| using browser_sync::ChromeSyncClient;
|
| @@ -19,6 +20,11 @@ using syncer_v2::FakeModelTypeService;
|
| using syncer_v2::ModelTypeService;
|
| using syncer_v2::SharedModelTypeProcessor;
|
|
|
| +const char kKey1[] = "key1";
|
| +const char kValue1[] = "value1";
|
| +const char kValue2[] = "value2";
|
| +const char kResolutionValue[] = "RESOLVED";
|
| +
|
| // A ChromeSyncClient that provides a ModelTypeService for PREFERENCES.
|
| class TestSyncClient : public ChromeSyncClient {
|
| public:
|
| @@ -62,6 +68,13 @@ class TestModelTypeService : public FakeModelTypeService {
|
| db().CreateMetadataBatch());
|
| }
|
|
|
| + syncer_v2::ConflictResolution ResolveConflict(
|
| + const syncer_v2::EntityData& local_data,
|
| + const syncer_v2::EntityData& remote_data) const override {
|
| + return syncer_v2::ConflictResolution::UseNew(
|
| + GenerateEntityData(local_data.non_unique_name, kResolutionValue));
|
| + }
|
| +
|
| void AddObserver(Observer* observer) { observers_.insert(observer); }
|
| void RemoveObserver(Observer* observer) { observers_.erase(observer); }
|
|
|
| @@ -103,35 +116,73 @@ class KeyChecker : public StatusChangeChecker,
|
| const std::string key_;
|
| };
|
|
|
| -// Wait for a key to be present.
|
| -class KeyPresentChecker : public KeyChecker {
|
| +// Wait for data for a key to have a certain value.
|
| +class DataChecker : public KeyChecker {
|
| public:
|
| - KeyPresentChecker(TestModelTypeService* service, const std::string& key)
|
| - : KeyChecker(service, key) {}
|
| - ~KeyPresentChecker() override {}
|
| + DataChecker(TestModelTypeService* service,
|
| + const std::string& key,
|
| + const std::string& value)
|
| + : KeyChecker(service, key), value_(value) {}
|
| + ~DataChecker() override {}
|
|
|
| bool IsExitConditionSatisfied() override {
|
| - return service_->db().HasData(key_);
|
| + const auto& db = service_->db();
|
| + return db.HasData(key_) && db.GetValue(key_) == value_;
|
| }
|
|
|
| std::string GetDebugMessage() const override {
|
| - return "Waiting for key '" + key_ + "' to be present.";
|
| + return "Waiting for data for key '" + key_ + "' to be '" + value_ + "'.";
|
| }
|
| +
|
| + private:
|
| + const std::string value_;
|
| };
|
|
|
| -// Wait for a key to be absent.
|
| -class KeyAbsentChecker : public KeyChecker {
|
| +// Wait for data for a key to be absent.
|
| +class DataAbsentChecker : public KeyChecker {
|
| public:
|
| - KeyAbsentChecker(TestModelTypeService* service, const std::string& key)
|
| + DataAbsentChecker(TestModelTypeService* service, const std::string& key)
|
| : KeyChecker(service, key) {}
|
| - ~KeyAbsentChecker() override {}
|
| + ~DataAbsentChecker() override {}
|
|
|
| bool IsExitConditionSatisfied() override {
|
| return !service_->db().HasData(key_);
|
| }
|
|
|
| std::string GetDebugMessage() const override {
|
| - return "Waiting for key '" + key_ + "' to be absent.";
|
| + return "Waiting for data for key '" + key_ + "' to be absent.";
|
| + }
|
| +};
|
| +
|
| +// Wait for metadata for a key to be present.
|
| +class MetadataPresentChecker : public KeyChecker {
|
| + public:
|
| + MetadataPresentChecker(TestModelTypeService* service, const std::string& key)
|
| + : KeyChecker(service, key) {}
|
| + ~MetadataPresentChecker() override {}
|
| +
|
| + bool IsExitConditionSatisfied() override {
|
| + return service_->db().HasMetadata(key_);
|
| + }
|
| +
|
| + std::string GetDebugMessage() const override {
|
| + return "Waiting for metadata for key '" + key_ + "' to be present.";
|
| + }
|
| +};
|
| +
|
| +// Wait for metadata for a key to be absent.
|
| +class MetadataAbsentChecker : public KeyChecker {
|
| + public:
|
| + MetadataAbsentChecker(TestModelTypeService* service, const std::string& key)
|
| + : KeyChecker(service, key) {}
|
| + ~MetadataAbsentChecker() override {}
|
| +
|
| + bool IsExitConditionSatisfied() override {
|
| + return !service_->db().HasMetadata(key_);
|
| + }
|
| +
|
| + std::string GetDebugMessage() const override {
|
| + return "Waiting for metadata for key '" + key_ + "' to be absent.";
|
| }
|
| };
|
|
|
| @@ -176,6 +227,7 @@ class TwoClientUssSyncTest : public SyncTest {
|
| std::vector<TestSyncClient*> clients_;
|
| bool first_client_ignored_ = false;
|
|
|
| + private:
|
| DISALLOW_COPY_AND_ASSIGN(TwoClientUssSyncTest);
|
| };
|
|
|
| @@ -186,10 +238,67 @@ IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, Sanity) {
|
| TestModelTypeService* model1 = GetModelTypeService(0);
|
| TestModelTypeService* model2 = GetModelTypeService(1);
|
|
|
| - model1->WriteItem("foo", "bar");
|
| - ASSERT_TRUE(KeyPresentChecker(model2, "foo").Wait());
|
| - EXPECT_EQ("bar", model2->db().GetValue("foo"));
|
| + // Add an entity.
|
| + model1->WriteItem(kKey1, kValue1);
|
| + ASSERT_TRUE(DataChecker(model2, kKey1, kValue1).Wait());
|
| +
|
| + // Update an entity.
|
| + model1->WriteItem(kKey1, kValue2);
|
| + ASSERT_TRUE(DataChecker(model2, kKey1, kValue2).Wait());
|
| +
|
| + // Delete an entity.
|
| + model1->DeleteItem(kKey1);
|
| + ASSERT_TRUE(DataAbsentChecker(model2, kKey1).Wait());
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, DisableEnable) {
|
| + ASSERT_TRUE(SetupSync());
|
| + TestModelTypeService* model1 = GetModelTypeService(0);
|
| + TestModelTypeService* model2 = GetModelTypeService(1);
|
| +
|
| + // Add an entity to test with.
|
| + model1->WriteItem(kKey1, kValue1);
|
| + ASSERT_TRUE(DataChecker(model2, kKey1, kValue1).Wait());
|
| + ASSERT_EQ(1U, model1->db().data_count());
|
| + ASSERT_EQ(1U, model1->db().metadata_count());
|
| + ASSERT_EQ(1U, model2->db().data_count());
|
| + ASSERT_EQ(1U, model2->db().metadata_count());
|
| +
|
| + // Disable PREFERENCES.
|
| + syncer::ModelTypeSet types = syncer::UserSelectableTypes();
|
| + types.Remove(syncer::PREFERENCES);
|
| + GetSyncService(0)->OnUserChoseDatatypes(false, types);
|
| +
|
| + // Wait for it to take effect and remove the metadata.
|
| + ASSERT_TRUE(MetadataAbsentChecker(model1, kKey1).Wait());
|
| + ASSERT_EQ(1U, model1->db().data_count());
|
| + ASSERT_EQ(0U, model1->db().metadata_count());
|
| + // Model 2 should not be affected.
|
| + ASSERT_EQ(1U, model2->db().data_count());
|
| + ASSERT_EQ(1U, model2->db().metadata_count());
|
| +
|
| + // Re-enable PREFERENCES.
|
| + GetSyncService(0)->OnUserChoseDatatypes(true, syncer::UserSelectableTypes());
|
| +
|
| + // Wait for metadata to be re-added.
|
| + ASSERT_TRUE(MetadataPresentChecker(model1, kKey1).Wait());
|
| + ASSERT_EQ(1U, model1->db().data_count());
|
| + ASSERT_EQ(1U, model1->db().metadata_count());
|
| + ASSERT_EQ(1U, model2->db().data_count());
|
| + ASSERT_EQ(1U, model2->db().metadata_count());
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(TwoClientUssSyncTest, ConflictResolution) {
|
| + ASSERT_TRUE(SetupSync());
|
| + TestModelTypeService* model1 = GetModelTypeService(0);
|
| + TestModelTypeService* model2 = GetModelTypeService(1);
|
| +
|
| + // Write conflicting entities.
|
| + model1->WriteItem(kKey1, kValue1);
|
| + model2->WriteItem(kKey1, kValue2);
|
|
|
| - model1->DeleteItem("foo");
|
| - ASSERT_TRUE(KeyAbsentChecker(model2, "foo").Wait());
|
| + // Wait for them to be resolved to kResolutionValue by the custom conflict
|
| + // resolution logic in TestModelTypeService.
|
| + ASSERT_TRUE(DataChecker(model1, kKey1, kResolutionValue).Wait());
|
| + ASSERT_TRUE(DataChecker(model2, kKey1, kResolutionValue).Wait());
|
| }
|
|
|