summaryrefslogtreecommitdiffstats
path: root/sync/engine/syncer_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sync/engine/syncer_unittest.cc')
-rw-r--r--sync/engine/syncer_unittest.cc267
1 files changed, 234 insertions, 33 deletions
diff --git a/sync/engine/syncer_unittest.cc b/sync/engine/syncer_unittest.cc
index 46fa871..8d97d33 100644
--- a/sync/engine/syncer_unittest.cc
+++ b/sync/engine/syncer_unittest.cc
@@ -4448,6 +4448,217 @@ TEST_F(SyncerTest, GetKeyEmpty) {
}
}
+// Tests specifically related to bookmark (and therefore no client tags) sync
+// logic. Entities without client tags have custom logic in parts of the code,
+// and hence are not covered by e.g. the Undeletion tests below.
+class SyncerBookmarksTest : public SyncerTest {
+ public:
+ SyncerBookmarksTest() : metahandle_(syncable::kInvalidMetaHandle) {
+ }
+
+ void Create() {
+ WriteTransaction trans(FROM_HERE, UNITTEST, directory());
+ MutableEntry bookmark(
+ &trans, CREATE, BOOKMARKS, ids_.root(), "clientname");
+ ASSERT_TRUE(bookmark.good());
+ bookmark.PutIsUnsynced(true);
+ bookmark.PutSyncing(false);
+ bookmark.PutSpecifics(DefaultBookmarkSpecifics());
+ EXPECT_FALSE(bookmark.GetIsUnappliedUpdate());
+ EXPECT_FALSE(bookmark.GetId().ServerKnows());
+ metahandle_ = bookmark.GetMetahandle();
+ local_id_ = bookmark.GetId();
+ }
+
+ void Delete() {
+ WriteTransaction trans(FROM_HERE, UNITTEST, directory());
+ MutableEntry entry(&trans, GET_BY_HANDLE, metahandle_);
+ ASSERT_TRUE(entry.good());
+ EXPECT_EQ(metahandle_, entry.GetMetahandle());
+ // The order of setting IS_UNSYNCED vs IS_DEL matters. See
+ // WriteNode::Tombstone().
+ entry.PutIsUnsynced(true);
+ entry.PutIsDel(true);
+ entry.PutSyncing(false);
+ }
+
+ void Undelete() {
+ WriteTransaction trans(FROM_HERE, UNITTEST, directory());
+ MutableEntry entry(&trans, GET_BY_HANDLE, metahandle_);
+ ASSERT_TRUE(entry.good());
+ EXPECT_EQ(metahandle_, entry.GetMetahandle());
+ EXPECT_TRUE(entry.GetIsDel());
+ entry.PutIsDel(false);
+ entry.PutIsUnsynced(true);
+ entry.PutSyncing(false);
+ }
+
+ int64 GetMetahandleOfTag() {
+ syncable::ReadTransaction trans(FROM_HERE, directory());
+ Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+ EXPECT_TRUE(entry.good());
+ if (!entry.good()) {
+ return syncable::kInvalidMetaHandle;
+ }
+ return entry.GetMetahandle();
+ }
+
+ Id GetServerId() {
+ syncable::ReadTransaction trans(FROM_HERE, directory());
+ Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+ EXPECT_TRUE(entry.good());
+ if (!entry.good()) {
+ return Id();
+ }
+ return entry.GetId();
+ }
+
+ void ExpectUnsyncedCreation() {
+ 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()); // Never been committed.
+ EXPECT_LT(entry.GetBaseVersion(), 0);
+ EXPECT_TRUE(entry.GetIsUnsynced());
+ EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+ }
+
+ void ExpectUnsyncedUndeletion() {
+ syncable::ReadTransaction trans(FROM_HERE, directory());
+ Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+ EXPECT_EQ(metahandle_, entry.GetMetahandle());
+ EXPECT_FALSE(entry.GetIsDel());
+ EXPECT_TRUE(entry.GetServerIsDel());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
+ EXPECT_TRUE(entry.GetIsUnsynced());
+ EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+ EXPECT_TRUE(entry.GetId().ServerKnows());
+ }
+
+ void ExpectUnsyncedEdit() {
+ 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_TRUE(entry.GetIsUnsynced());
+ EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+ EXPECT_TRUE(entry.GetId().ServerKnows());
+ }
+
+ void ExpectUnsyncedDeletion() {
+ syncable::ReadTransaction trans(FROM_HERE, directory());
+ Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+ EXPECT_EQ(metahandle_, entry.GetMetahandle());
+ EXPECT_TRUE(entry.GetIsDel());
+ EXPECT_FALSE(entry.GetServerIsDel());
+ EXPECT_TRUE(entry.GetIsUnsynced());
+ EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
+ EXPECT_GE(entry.GetServerVersion(), 0);
+ }
+
+ void ExpectSyncedAndCreated() {
+ 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());
+ }
+
+ void ExpectSyncedAndDeleted() {
+ 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);
+ }
+
+ protected:
+ syncable::Id local_id_;
+ int64 metahandle_;
+};
+
+TEST_F(SyncerBookmarksTest, CreateSyncThenDeleteSync) {
+ Create();
+ ExpectUnsyncedCreation();
+ SyncShareNudge();
+ ExpectSyncedAndCreated();
+ Delete();
+ ExpectUnsyncedDeletion();
+ SyncShareNudge();
+ ExpectSyncedAndDeleted();
+}
+
+TEST_F(SyncerBookmarksTest, CreateThenDeleteBeforeSync) {
+ Create();
+ ExpectUnsyncedCreation();
+ Delete();
+
+ // Deleting before the initial commit should result in not needing to send
+ // the delete to the server. It will still be in an unsynced state, but with
+ // IS_UNSYNCED set to false.
+ {
+ syncable::ReadTransaction trans(FROM_HERE, directory());
+ Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+ EXPECT_EQ(metahandle_, entry.GetMetahandle());
+ EXPECT_TRUE(entry.GetIsDel());
+ EXPECT_FALSE(entry.GetServerIsDel());
+ EXPECT_FALSE(entry.GetIsUnsynced());
+ EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+ EXPECT_EQ(entry.GetBaseVersion(), -1);
+ EXPECT_EQ(entry.GetServerVersion(), 0);
+ }
+}
+
+TEST_F(SyncerBookmarksTest, LocalDeleteRemoteChangeConflict) {
+ Create();
+ ExpectUnsyncedCreation();
+ SyncShareNudge();
+ ExpectSyncedAndCreated();
+ Delete();
+ ExpectUnsyncedDeletion();
+
+ // Trigger a getupdates that modifies the bookmark. The update should be
+ // clobbered by the local delete.
+ mock_server_->AddUpdateBookmark(GetServerId(), Id(), "dummy", 10, 10,
+ local_cache_guid(), local_id_.GetServerId());
+
+ SyncShareNudge();
+ ExpectSyncedAndDeleted();
+}
+
+TEST_F(SyncerBookmarksTest, CreateThenDeleteDuringCommit) {
+ Create();
+ ExpectUnsyncedCreation();
+
+ // In the middle of the initial creation commit, perform a deletion.
+ // This should trigger performing two consecutive commit cycles, resulting
+ // in the bookmark being both deleted and synced.
+ mock_server_->SetMidCommitCallback(
+ base::Bind(&SyncerBookmarksTest::Delete, base::Unretained(this)));
+
+ SyncShareNudge();
+ ExpectSyncedAndDeleted();
+}
+
// Test what happens if a client deletes, then recreates, an object very
// quickly. It is possible that the deletion gets sent as a commit, and
// the undelete happens during the commit request. The principle here
@@ -4477,12 +4688,12 @@ class SyncerUndeletionTest : public SyncerTest {
void Create() {
WriteTransaction trans(FROM_HERE, UNITTEST, directory());
MutableEntry perm_folder(
- &trans, CREATE, BOOKMARKS, ids_.root(), "clientname");
+ &trans, CREATE, PREFERENCES, ids_.root(), "clientname");
ASSERT_TRUE(perm_folder.good());
perm_folder.PutUniqueClientTag(client_tag_);
perm_folder.PutIsUnsynced(true);
perm_folder.PutSyncing(false);
- perm_folder.PutSpecifics(DefaultBookmarkSpecifics());
+ perm_folder.PutSpecifics(DefaultPreferencesSpecifics());
EXPECT_FALSE(perm_folder.GetIsUnappliedUpdate());
EXPECT_FALSE(perm_folder.GetId().ServerKnows());
metahandle_ = perm_folder.GetMetahandle();
@@ -4494,8 +4705,10 @@ class SyncerUndeletionTest : public SyncerTest {
MutableEntry entry(&trans, GET_BY_CLIENT_TAG, client_tag_);
ASSERT_TRUE(entry.good());
EXPECT_EQ(metahandle_, entry.GetMetahandle());
- entry.PutIsDel(true);
+ // The order of setting IS_UNSYNCED vs IS_DEL matters. See
+ // WriteNode::Tombstone().
entry.PutIsUnsynced(true);
+ entry.PutIsDel(true);
entry.PutSyncing(false);
}
@@ -4527,7 +4740,7 @@ class SyncerUndeletionTest : public SyncerTest {
EXPECT_EQ(metahandle_, entry.GetMetahandle());
EXPECT_FALSE(entry.GetIsDel());
EXPECT_FALSE(entry.GetServerIsDel()); // Never been committed.
- EXPECT_GE(0, entry.GetBaseVersion());
+ EXPECT_LT(entry.GetBaseVersion(), 0);
EXPECT_TRUE(entry.GetIsUnsynced());
EXPECT_FALSE(entry.GetIsUnappliedUpdate());
}
@@ -4539,7 +4752,7 @@ class SyncerUndeletionTest : public SyncerTest {
EXPECT_EQ(metahandle_, entry.GetMetahandle());
EXPECT_FALSE(entry.GetIsDel());
EXPECT_TRUE(entry.GetServerIsDel());
- EXPECT_EQ(0, entry.GetBaseVersion());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
EXPECT_TRUE(entry.GetIsUnsynced());
EXPECT_FALSE(entry.GetIsUnappliedUpdate());
EXPECT_TRUE(entry.GetId().ServerKnows());
@@ -4552,7 +4765,7 @@ class SyncerUndeletionTest : public SyncerTest {
EXPECT_EQ(metahandle_, entry.GetMetahandle());
EXPECT_FALSE(entry.GetIsDel());
EXPECT_FALSE(entry.GetServerIsDel());
- EXPECT_LT(0, entry.GetBaseVersion());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
EXPECT_TRUE(entry.GetIsUnsynced());
EXPECT_FALSE(entry.GetIsUnappliedUpdate());
EXPECT_TRUE(entry.GetId().ServerKnows());
@@ -4567,8 +4780,8 @@ class SyncerUndeletionTest : public SyncerTest {
EXPECT_FALSE(entry.GetServerIsDel());
EXPECT_TRUE(entry.GetIsUnsynced());
EXPECT_FALSE(entry.GetIsUnappliedUpdate());
- EXPECT_LT(0, entry.GetBaseVersion());
- EXPECT_LT(0, entry.GetServerVersion());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
+ EXPECT_GE(entry.GetServerVersion(), 0);
}
void ExpectSyncedAndCreated() {
@@ -4578,7 +4791,7 @@ class SyncerUndeletionTest : public SyncerTest {
EXPECT_EQ(metahandle_, entry.GetMetahandle());
EXPECT_FALSE(entry.GetIsDel());
EXPECT_FALSE(entry.GetServerIsDel());
- EXPECT_LT(0, entry.GetBaseVersion());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
EXPECT_EQ(entry.GetBaseVersion(), entry.GetServerVersion());
EXPECT_FALSE(entry.GetIsUnsynced());
EXPECT_FALSE(entry.GetIsUnappliedUpdate());
@@ -4593,8 +4806,8 @@ class SyncerUndeletionTest : public SyncerTest {
EXPECT_TRUE(entry.GetServerIsDel());
EXPECT_FALSE(entry.GetIsUnsynced());
EXPECT_FALSE(entry.GetIsUnappliedUpdate());
- EXPECT_GE(0, entry.GetBaseVersion());
- EXPECT_GE(0, entry.GetServerVersion());
+ EXPECT_GE(entry.GetBaseVersion(), 0);
+ EXPECT_GE(entry.GetServerVersion(), 0);
}
protected:
@@ -4793,7 +5006,7 @@ TEST_F(SyncerUndeletionTest, UndeleteAfterOtherClientDeletes) {
{
syncable::ReadTransaction trans(FROM_HERE, directory());
Entry entry(&trans, GET_BY_HANDLE, metahandle_);
- mock_server_->AddUpdateTombstone(entry.GetId());
+ mock_server_->AddUpdateTombstone(entry.GetId(), PREFERENCES);
}
SyncShareNudge();
@@ -4835,7 +5048,7 @@ TEST_F(SyncerUndeletionTest, UndeleteAfterOtherClientDeletesImmediately) {
{
syncable::ReadTransaction trans(FROM_HERE, directory());
Entry entry(&trans, GET_BY_HANDLE, metahandle_);
- mock_server_->AddUpdateTombstone(entry.GetId());
+ mock_server_->AddUpdateTombstone(entry.GetId(), PREFERENCES);
}
SyncShareNudge();
@@ -4903,22 +5116,16 @@ TEST_F(SyncerUndeletionTest, OtherClientUndeletes) {
{
syncable::ReadTransaction trans(FROM_HERE, directory());
Entry entry(&trans, GET_BY_HANDLE, metahandle_);
- mock_server_->AddUpdateBookmark(
- entry.GetId(),
- entry.GetParentId(),
- "Thadeusz", 100, 1000,
- local_cache_guid(), local_id_.GetServerId());
+ mock_server_->AddUpdatePref(
+ entry.GetId().GetServerId(),
+ entry.GetParentId().GetServerId(),
+ client_tag_, 100, 1000);
}
mock_server_->SetLastUpdateClientTag(client_tag_);
SyncShareNudge();
EXPECT_EQ(0, session_->status_controller().TotalNumConflictingItems());
EXPECT_EQ(1, mock_server_->GetAndClearNumGetUpdatesRequests());
ExpectSyncedAndCreated();
- {
- syncable::ReadTransaction trans(FROM_HERE, directory());
- Entry entry(&trans, GET_BY_HANDLE, metahandle_);
- EXPECT_EQ("Thadeusz", entry.GetNonUniqueName());
- }
}
TEST_F(SyncerUndeletionTest, OtherClientUndeletesImmediately) {
@@ -4958,22 +5165,16 @@ TEST_F(SyncerUndeletionTest, OtherClientUndeletesImmediately) {
{
syncable::ReadTransaction trans(FROM_HERE, directory());
Entry entry(&trans, GET_BY_HANDLE, metahandle_);
- mock_server_->AddUpdateBookmark(
- entry.GetId(),
- entry.GetParentId(),
- "Thadeusz", 100, 1000,
- local_cache_guid(), local_id_.GetServerId());
+ mock_server_->AddUpdatePref(
+ entry.GetId().GetServerId(),
+ entry.GetParentId().GetServerId(),
+ client_tag_, 100, 1000);
}
mock_server_->SetLastUpdateClientTag(client_tag_);
SyncShareNudge();
EXPECT_EQ(0, session_->status_controller().TotalNumConflictingItems());
EXPECT_EQ(1, mock_server_->GetAndClearNumGetUpdatesRequests());
ExpectSyncedAndCreated();
- {
- syncable::ReadTransaction trans(FROM_HERE, directory());
- Entry entry(&trans, GET_BY_HANDLE, metahandle_);
- EXPECT_EQ("Thadeusz", entry.GetNonUniqueName());
- }
}
enum {