| Index: sync/engine/syncer_unittest.cc
|
| diff --git a/sync/engine/syncer_unittest.cc b/sync/engine/syncer_unittest.cc
|
| index b2a92dea45dfe1af28f934c1b00551fd6f87866d..b968e9278aa9b51704c0c3341ffcc2d86e34ab63 100644
|
| --- a/sync/engine/syncer_unittest.cc
|
| +++ b/sync/engine/syncer_unittest.cc
|
| @@ -283,6 +283,7 @@ class SyncerTest : public testing::Test,
|
| &cancelation_signal_));
|
| debug_info_getter_.reset(new MockDebugInfoGetter);
|
| EnableDatatype(BOOKMARKS);
|
| + EnableDatatype(EXTENSIONS);
|
| EnableDatatype(NIGORI);
|
| EnableDatatype(PREFERENCES);
|
| EnableDatatype(NIGORI);
|
| @@ -2670,11 +2671,11 @@ TEST_F(SyncerTest, CommitsUpdateDoesntAlterEntry) {
|
| }
|
|
|
| TEST_F(SyncerTest, ParentAndChildBothMatch) {
|
| - // Disable PREFERENCES which is enabled at the setup step to avoid
|
| - // auto-creating
|
| - // PREFERENCES root folder and failing the test below that verifies the number
|
| - // of children at the root.
|
| + // Disable PREFERENCES and EXTENSIONS which are enabled at the setup step to
|
| + // avoid auto-creating root folders and failing the test below
|
| + // that verifies the number of children at the root.
|
| DisableDatatype(PREFERENCES);
|
| + DisableDatatype(EXTENSIONS);
|
|
|
| const FullModelTypeSet all_types = FullModelTypeSet::All();
|
| syncable::Id parent_id = ids_.NewServerId();
|
| @@ -3755,6 +3756,82 @@ TEST_F(SyncerTest, ConflictResolverMergesLocalDeleteAndServerUpdate) {
|
| }
|
| }
|
|
|
| +// This ensures that for extensions, we resolve the conflict of local updates
|
| +// and server deletes in favor of the server, to prevent extensions from
|
| +// being reinstalled after uninstall.
|
| +TEST_F(SyncerTest, ConflictResolverAcceptsServerDeleteForExtensions) {
|
| + ASSERT_TRUE(context_->GetEnabledTypes().Has(EXTENSIONS));
|
| +
|
| + // Create an extension entry.
|
| + int64_t metahandle;
|
| + {
|
| + WriteTransaction trans(FROM_HERE, UNITTEST, directory());
|
| + MutableEntry extension(
|
| + &trans, CREATE, EXTENSIONS, trans.root_id(), "extension_name");
|
| + ASSERT_TRUE(extension.good());
|
| + sync_pb::EntitySpecifics specifics;
|
| + AddDefaultFieldValue(EXTENSIONS, &specifics);
|
| + extension.PutSpecifics(specifics);
|
| + EXPECT_FALSE(extension.GetIsUnappliedUpdate());
|
| + EXPECT_FALSE(extension.GetId().ServerKnows());
|
| + metahandle = extension.GetMetahandle();
|
| + extension.PutIsUnsynced(true);
|
| + }
|
| +
|
| + // Make sure the server has received the new item.
|
| + SyncShareNudge();
|
| + syncable::Id id;
|
| + {
|
| + syncable::ReadTransaction trans(FROM_HERE, directory());
|
| + Entry entry(&trans, GET_BY_HANDLE, metahandle);
|
| +
|
| + EXPECT_EQ(metahandle, entry.GetMetahandle());
|
| + EXPECT_FALSE(entry.GetIsDel());
|
| + EXPECT_FALSE(entry.GetServerIsDel());
|
| + EXPECT_GE(entry.GetBaseVersion(), 0);
|
| + EXPECT_EQ(entry.GetBaseVersion(), entry.GetServerVersion());
|
| + EXPECT_FALSE(entry.GetIsUnsynced());
|
| + EXPECT_FALSE(entry.GetIsUnappliedUpdate());
|
| + id = entry.GetId();
|
| + }
|
| +
|
| +
|
| + // Simulate another client deleting the item.
|
| + {
|
| + syncable::ReadTransaction trans(FROM_HERE, directory());
|
| + Entry entry(&trans, GET_BY_HANDLE, metahandle);
|
| + mock_server_->AddUpdateTombstone(id, EXTENSIONS);
|
| + }
|
| +
|
| + // Create a local update, which should cause a conflict with the delete that
|
| + // we just pushed to the server.
|
| + {
|
| + WriteTransaction trans(FROM_HERE, UNITTEST, directory());
|
| + MutableEntry extension(&trans, GET_BY_HANDLE, metahandle);
|
| + ASSERT_TRUE(extension.good());
|
| + sync_pb::EntitySpecifics specifics;
|
| + AddDefaultFieldValue(EXTENSIONS, &specifics);
|
| + specifics.mutable_extension()->set_disable_reasons(2);
|
| + extension.PutSpecifics(specifics);
|
| + EXPECT_FALSE(extension.GetIsUnappliedUpdate());
|
| + extension.PutIsUnsynced(true);
|
| + }
|
| +
|
| + // Run a sync, and expect the item to be deleted.
|
| + SyncShareNudge();
|
| + {
|
| + syncable::ReadTransaction trans(FROM_HERE, directory());
|
| + Entry entry(&trans, GET_BY_HANDLE, metahandle);
|
| + EXPECT_EQ(metahandle, entry.GetMetahandle());
|
| + EXPECT_TRUE(entry.GetIsDel());
|
| + EXPECT_TRUE(entry.GetServerIsDel());
|
| + EXPECT_FALSE(entry.GetIsUnsynced());
|
| + EXPECT_FALSE(entry.GetIsUnappliedUpdate());
|
| + EXPECT_GE(entry.GetBaseVersion(), 0);
|
| + EXPECT_GE(entry.GetServerVersion(), 0);
|
| + }
|
| +}
|
| +
|
| // See what happens if the IS_DIR bit gets flipped. This can cause us
|
| // all kinds of disasters.
|
| TEST_F(SyncerTest, UpdateFlipsTheFolderBit) {
|
|
|