| Index: components/sync/model_impl/shared_model_type_processor_unittest.cc
|
| diff --git a/components/sync/model_impl/shared_model_type_processor_unittest.cc b/components/sync/model_impl/shared_model_type_processor_unittest.cc
|
| index 819a0bb303aabd6d039f8cea1c0b55eeb9632711..091d78e9fa229da9ff035a004d4aa039bfef7df4 100644
|
| --- a/components/sync/model_impl/shared_model_type_processor_unittest.cc
|
| +++ b/components/sync/model_impl/shared_model_type_processor_unittest.cc
|
| @@ -14,6 +14,7 @@
|
| #include "base/callback.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/message_loop/message_loop.h"
|
| +#include "base/rand_util.h"
|
| #include "base/run_loop.h"
|
| #include "components/sync/base/time.h"
|
| #include "components/sync/engine/activation_context.h"
|
| @@ -30,7 +31,10 @@ namespace syncer {
|
|
|
| namespace {
|
|
|
| -const char kKey1[] = "key1";
|
| +// TODO(gangwu): crbug.com/719570 should assign kKey1 as "key1" after bug fixed.
|
| +// Assign a prefix 'l' for kKey1 to let TestModelTypeSyncBridge::GetStorageKey
|
| +// generate a random storage key for it.
|
| +const char kKey1[] = "lkey1";
|
| const char kKey2[] = "key2";
|
| const char kKey3[] = "key3";
|
| const char kKey4[] = "key4";
|
| @@ -48,6 +52,10 @@ const std::string kHash5(FakeModelTypeSyncBridge::TagHashFromKey(kKey5));
|
| // worker/processor will not have been initialized and thus empty.
|
| const EntitySpecifics kEmptySpecifics;
|
|
|
| +const int invalidStorageKeySize = 64;
|
| +
|
| +static char InvalidStorageKeyPrefix[] = "InvalidStorageKey";
|
| +
|
| EntitySpecifics GenerateSpecifics(const std::string& key,
|
| const std::string& value) {
|
| return FakeModelTypeSyncBridge::GenerateSpecifics(key, value);
|
| @@ -58,6 +66,15 @@ std::unique_ptr<EntityData> GenerateEntityData(const std::string& key,
|
| return FakeModelTypeSyncBridge::GenerateEntityData(key, value);
|
| }
|
|
|
| +std::string GenerateInvalidStorageKey() {
|
| + return InvalidStorageKeyPrefix +
|
| + base::RandBytesAsString(invalidStorageKeySize);
|
| +}
|
| +
|
| +bool IsInvalidStorageKey(const std::string& storage_key) {
|
| + return 0 == storage_key.find(InvalidStorageKeyPrefix);
|
| +}
|
| +
|
| class TestModelTypeSyncBridge : public FakeModelTypeSyncBridge {
|
| public:
|
| TestModelTypeSyncBridge()
|
| @@ -101,13 +118,62 @@ class TestModelTypeSyncBridge : public FakeModelTypeSyncBridge {
|
| // FakeModelTypeSyncBridge overrides.
|
|
|
| base::Optional<ModelError> MergeSyncData(
|
| - std::unique_ptr<MetadataChangeList> mcl,
|
| + std::unique_ptr<MetadataChangeList> metadata_changes,
|
| EntityDataMap entity_data_map) override {
|
| merge_call_count_++;
|
| - return FakeModelTypeSyncBridge::MergeSyncData(std::move(mcl),
|
| +
|
| + std::map<std::string, std::string> updated_keys;
|
| +
|
| + // Update storage key for entities with invalid one.
|
| + for (const auto& kv : entity_data_map) {
|
| + std::string storage_key = kv.first;
|
| + if (IsInvalidStorageKey(storage_key)) {
|
| + change_processor()->UpdateStorageKey(
|
| + storage_key, kv.second.value().specifics.preference().name(),
|
| + metadata_changes.get());
|
| + updated_keys[storage_key] =
|
| + kv.second.value().specifics.preference().name();
|
| + }
|
| + }
|
| +
|
| + for (const auto& kv : updated_keys) {
|
| + DCHECK_NE(kv.first, kv.second);
|
| + entity_data_map[kv.second] = entity_data_map[kv.first];
|
| + entity_data_map.erase(kv.first);
|
| + }
|
| +
|
| + return FakeModelTypeSyncBridge::MergeSyncData(std::move(metadata_changes),
|
| entity_data_map);
|
| }
|
|
|
| + base::Optional<ModelError> ApplySyncChanges(
|
| + std::unique_ptr<MetadataChangeList> metadata_changes,
|
| + EntityChangeList entity_changes) override {
|
| + EntityChangeList new_changes;
|
| + for (EntityChangeList::iterator iter = entity_changes.begin();
|
| + iter != entity_changes.end();) {
|
| + std::string storage_key = iter->storage_key();
|
| + if (IsInvalidStorageKey(storage_key)) {
|
| + EXPECT_TRUE(iter->type() == EntityChange::ACTION_ADD);
|
| +
|
| + change_processor()->UpdateStorageKey(
|
| + storage_key, iter->data().specifics.preference().name(),
|
| + metadata_changes.get());
|
| + new_changes.push_back(EntityChange::CreateAdd(
|
| + iter->data().specifics.preference().name(),
|
| + FakeModelTypeSyncBridge::CopyEntityData(iter->data())
|
| + ->PassToPtr()));
|
| + iter = entity_changes.erase(iter);
|
| + } else {
|
| + ++iter;
|
| + }
|
| + }
|
| + entity_changes.insert(entity_changes.end(), new_changes.begin(),
|
| + new_changes.end());
|
| +
|
| + return FakeModelTypeSyncBridge::ApplySyncChanges(
|
| + std::move(metadata_changes), entity_changes);
|
| + }
|
| void GetData(StorageKeyList keys, DataCallback callback) override {
|
| if (synchronous_data_callback_) {
|
| synchronous_data_callback_ = false;
|
| @@ -119,6 +185,14 @@ class TestModelTypeSyncBridge : public FakeModelTypeSyncBridge {
|
| }
|
| }
|
|
|
| + std::string GetStorageKey(const EntityData& entity_data) override {
|
| + std::string name = entity_data.specifics.preference().name();
|
| + if (name.length() > 0 && name[0] <= 'k') {
|
| + return entity_data.specifics.preference().name();
|
| + }
|
| + return GenerateInvalidStorageKey();
|
| + }
|
| +
|
| private:
|
| void CaptureDataCallback(DataCallback callback,
|
| std::unique_ptr<DataBatch> data) {
|
| @@ -1170,7 +1244,9 @@ TEST_F(SharedModelTypeProcessorTest, Disable) {
|
|
|
| // Once we're ready to commit, all three local items should consider
|
| // themselves uncommitted and pending for commit.
|
| - worker()->ExpectPendingCommits({kHash1, kHash2, kHash3});
|
| + // The hashes need to be in alphabet order of their storage keys since
|
| + // enabling sync trigered merge and it will reorder the commits.
|
| + worker()->ExpectPendingCommits({kHash2, kHash3, kHash1});
|
| }
|
|
|
| // Test re-encrypt everything when desired encryption key changes.
|
|
|