Index: chrome/browser/sync/profile_sync_service_bookmark_unittest.cc |
diff --git a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc |
index cf7e3813c50e30d008033ec4ffd3c9c41cc6328d..baaa9b98df79b5ad738f7008345ee0cba75f3a0d 100644 |
--- a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc |
+++ b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc |
@@ -6,6 +6,8 @@ |
// BookmarkChangeProcessor. Write unit tests for |
// BookmarkModelAssociator separately. |
+#include <map> |
+#include <queue> |
#include <stack> |
#include <vector> |
@@ -559,12 +561,12 @@ class ProfileSyncServiceBookmarkTest : public testing::Test { |
content::TestBrowserThread file_thread_; |
TestingProfile profile_; |
- scoped_ptr<TestBookmarkModelAssociator> model_associator_; |
protected: |
BookmarkModel* model_; |
syncer::TestUserShare test_user_share_; |
scoped_ptr<BookmarkChangeProcessor> change_processor_; |
+ scoped_ptr<TestBookmarkModelAssociator> model_associator_; |
StrictMock<DataTypeErrorHandlerMock> mock_error_handler_; |
}; |
@@ -976,6 +978,9 @@ struct TestData { |
const char* url; |
}; |
+// Map from bookmark node ID to its version. |
+typedef std::map<int64, int64> BookmarkNodeVersionMap; |
+ |
// TODO(ncarter): Integrate the existing TestNode/PopulateNodeFromString code |
// in the bookmark model unittest, to make it simpler to set up test data |
// here (and reduce the amount of duplication among tests), and to reduce the |
@@ -1002,6 +1007,13 @@ class ProfileSyncServiceBookmarkTestWithData |
void ExpectBookmarkModelMatchesTestData(); |
void WriteTestDataToBookmarkModel(); |
+ // Verify transaction versions of bookmark nodes and sync nodes are equal |
+ // recursively. If node is in |version_expected|, versions should match |
+ // there, too. |
+ void ExpectTransactionVersionMatch( |
+ const BookmarkNode* node, |
+ const BookmarkNodeVersionMap& version_expected); |
+ |
private: |
const base::Time start_time_; |
@@ -1134,10 +1146,10 @@ void ProfileSyncServiceBookmarkTestWithData::PopulateFromTestData( |
start_time_ + base::TimeDelta::FromMinutes(*running_count); |
model_->AddURLWithCreationTime(node, i, WideToUTF16Hack(item.title), |
GURL(item.url), add_time); |
- (*running_count)++; |
} else { |
model_->AddFolder(node, i, WideToUTF16Hack(item.title)); |
} |
+ (*running_count)++; |
} |
} |
@@ -1165,11 +1177,11 @@ void ProfileSyncServiceBookmarkTestWithData::CompareWithTestData( |
start_time_ + base::TimeDelta::FromMinutes(*running_count); |
EXPECT_EQ(expected_time.ToInternalValue(), |
child_node->date_added().ToInternalValue()); |
- (*running_count)++; |
} else { |
EXPECT_TRUE(child_node->is_folder()); |
EXPECT_FALSE(child_node->is_url()); |
} |
+ (*running_count)++; |
} |
} |
@@ -1595,6 +1607,113 @@ TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateDateAdded) { |
EXPECT_EQ(node->date_added(), base::Time::FromInternalValue(30)); |
} |
+// Output transaction versions of |node| and nodes under it to |node_versions|. |
+void GetTransactionVersions( |
+ const BookmarkNode* root, |
+ BookmarkNodeVersionMap* node_versions) { |
+ node_versions->clear(); |
+ std::queue<const BookmarkNode*> nodes; |
+ nodes.push(root); |
+ while (!nodes.empty()) { |
+ const BookmarkNode* n = nodes.front(); |
+ nodes.pop(); |
+ |
+ std::string version_str; |
+ int64 version; |
+ EXPECT_TRUE(n->GetMetaInfo(kBookmarkTransactionVersionKey, &version_str)); |
+ EXPECT_TRUE(base::StringToInt64(version_str, &version)); |
+ |
+ (*node_versions)[n->id()] = version; |
+ for (int i = 0; i < n->child_count(); ++i) |
+ nodes.push(n->GetChild(i)); |
+ } |
+} |
+ |
+void ProfileSyncServiceBookmarkTestWithData::ExpectTransactionVersionMatch( |
+ const BookmarkNode* node, |
+ const BookmarkNodeVersionMap& version_expected) { |
+ syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); |
+ |
+ BookmarkNodeVersionMap bnodes_versions; |
+ GetTransactionVersions(node, &bnodes_versions); |
+ for (BookmarkNodeVersionMap::const_iterator it = bnodes_versions.begin(); |
+ it != bnodes_versions.end(); ++it) { |
+ syncer::ReadNode sync_node(&trans); |
+ ASSERT_TRUE(model_associator_->InitSyncNodeFromChromeId(it->first, |
+ &sync_node)); |
+ EXPECT_EQ(sync_node.GetEntry()->Get(syncer::syncable::TRANSACTION_VERSION), |
+ it->second); |
+ BookmarkNodeVersionMap::const_iterator expected_ver_it = |
+ version_expected.find(it->first); |
+ if (expected_ver_it != version_expected.end()) |
+ EXPECT_EQ(expected_ver_it->second, it->second); |
+ } |
+} |
+ |
+// Test transaction versions of model and nodes are incremented after changes |
+// are applied. |
+TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateTransactionVersion) { |
+ LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); |
+ StartSync(); |
+ WriteTestDataToBookmarkModel(); |
+ MessageLoop::current()->RunUntilIdle(); |
+ |
+ BookmarkNodeVersionMap initial_versions; |
+ |
+ // Verify transaction versions in sync model and bookmark model (saved as |
+ // transaction version of root node) are equal after |
+ // WriteTestDataToBookmarkModel() created bookmarks. |
+ { |
+ syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); |
+ EXPECT_GT(trans.GetModelVersion(syncer::BOOKMARKS), 0); |
+ GetTransactionVersions(model_->root_node(), &initial_versions); |
+ EXPECT_EQ(trans.GetModelVersion(syncer::BOOKMARKS), |
+ initial_versions[model_->root_node()->id()]); |
+ } |
+ ExpectTransactionVersionMatch(model_->bookmark_bar_node(), |
+ BookmarkNodeVersionMap()); |
+ ExpectTransactionVersionMatch(model_->other_node(), |
+ BookmarkNodeVersionMap()); |
+ ExpectTransactionVersionMatch(model_->mobile_node(), |
+ BookmarkNodeVersionMap()); |
+ |
+ // Verify model version is incremented and bookmark node versions remain |
+ // the same. |
+ const BookmarkNode* bookmark_bar = model_->bookmark_bar_node(); |
+ model_->Remove(bookmark_bar, 0); |
+ MessageLoop::current()->RunUntilIdle(); |
+ BookmarkNodeVersionMap new_versions; |
+ GetTransactionVersions(model_->root_node(), &new_versions); |
+ EXPECT_EQ(initial_versions[model_->root_node()->id()] + 1, |
+ new_versions[model_->root_node()->id()]); |
+ // HACK(haitaol): siblings of removed node are actually updated in sync model |
+ // because of NEXT_ID/PREV_ID. After switching to ordinal, |
+ // siblings will not get updated and the hack below can be |
+ // removed. |
+ model_->SetNodeMetaInfo(bookmark_bar->GetChild(0), |
+ kBookmarkTransactionVersionKey, "43"); |
+ initial_versions[bookmark_bar->GetChild(0)->id()] = 43; |
+ ExpectTransactionVersionMatch(model_->bookmark_bar_node(), initial_versions); |
+ ExpectTransactionVersionMatch(model_->other_node(), initial_versions); |
+ ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions); |
+ |
+ // Verify model version and version of changed bookmark are incremented and |
+ // versions of others remain same. |
+ const BookmarkNode* changed_bookmark = |
+ model_->bookmark_bar_node()->GetChild(0); |
+ model_->SetTitle(changed_bookmark, WideToUTF16Hack(L"test")); |
+ MessageLoop::current()->RunUntilIdle(); |
+ GetTransactionVersions(model_->root_node(), &new_versions); |
+ EXPECT_EQ(initial_versions[model_->root_node()->id()] + 2, |
+ new_versions[model_->root_node()->id()]); |
+ EXPECT_EQ(initial_versions[changed_bookmark->id()] + 1, |
+ new_versions[changed_bookmark->id()]); |
+ initial_versions.erase(changed_bookmark->id()); |
+ ExpectTransactionVersionMatch(model_->bookmark_bar_node(), initial_versions); |
+ ExpectTransactionVersionMatch(model_->other_node(), initial_versions); |
+ ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions); |
+} |
+ |
} // namespace |
} // namespace browser_sync |