OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // TODO(akalin): This file is basically just a unit test for | 5 // TODO(akalin): This file is basically just a unit test for |
6 // BookmarkChangeProcessor. Write unit tests for | 6 // BookmarkChangeProcessor. Write unit tests for |
7 // BookmarkModelAssociator separately. | 7 // BookmarkModelAssociator separately. |
8 | 8 |
| 9 #include <map> |
| 10 #include <queue> |
9 #include <stack> | 11 #include <stack> |
10 #include <vector> | 12 #include <vector> |
11 | 13 |
12 #include "base/command_line.h" | 14 #include "base/command_line.h" |
13 #include "base/file_path.h" | 15 #include "base/file_path.h" |
14 #include "base/file_util.h" | 16 #include "base/file_util.h" |
15 #include "base/location.h" | 17 #include "base/location.h" |
16 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
17 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
18 #include "base/string16.h" | 20 #include "base/string16.h" |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 } | 554 } |
553 | 555 |
554 private: | 556 private: |
555 // Used by both |ui_thread_| and |file_thread_|. | 557 // Used by both |ui_thread_| and |file_thread_|. |
556 MessageLoop message_loop_; | 558 MessageLoop message_loop_; |
557 content::TestBrowserThread ui_thread_; | 559 content::TestBrowserThread ui_thread_; |
558 // Needed by |model_|. | 560 // Needed by |model_|. |
559 content::TestBrowserThread file_thread_; | 561 content::TestBrowserThread file_thread_; |
560 | 562 |
561 TestingProfile profile_; | 563 TestingProfile profile_; |
562 scoped_ptr<TestBookmarkModelAssociator> model_associator_; | |
563 | 564 |
564 protected: | 565 protected: |
565 BookmarkModel* model_; | 566 BookmarkModel* model_; |
566 syncer::TestUserShare test_user_share_; | 567 syncer::TestUserShare test_user_share_; |
567 scoped_ptr<BookmarkChangeProcessor> change_processor_; | 568 scoped_ptr<BookmarkChangeProcessor> change_processor_; |
| 569 scoped_ptr<TestBookmarkModelAssociator> model_associator_; |
568 StrictMock<DataTypeErrorHandlerMock> mock_error_handler_; | 570 StrictMock<DataTypeErrorHandlerMock> mock_error_handler_; |
569 }; | 571 }; |
570 | 572 |
571 TEST_F(ProfileSyncServiceBookmarkTest, InitialState) { | 573 TEST_F(ProfileSyncServiceBookmarkTest, InitialState) { |
572 LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); | 574 LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); |
573 StartSync(); | 575 StartSync(); |
574 | 576 |
575 EXPECT_TRUE(other_bookmarks_id()); | 577 EXPECT_TRUE(other_bookmarks_id()); |
576 EXPECT_TRUE(bookmark_bar_id()); | 578 EXPECT_TRUE(bookmark_bar_id()); |
577 EXPECT_TRUE(mobile_bookmarks_id()); | 579 EXPECT_TRUE(mobile_bookmarks_id()); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 | 971 |
970 EXPECT_EQ(2, model_->other_node()->child_count()); | 972 EXPECT_EQ(2, model_->other_node()->child_count()); |
971 ExpectModelMatch(); | 973 ExpectModelMatch(); |
972 } | 974 } |
973 | 975 |
974 struct TestData { | 976 struct TestData { |
975 const wchar_t* title; | 977 const wchar_t* title; |
976 const char* url; | 978 const char* url; |
977 }; | 979 }; |
978 | 980 |
| 981 // Map from bookmark node ID to its version. |
| 982 typedef std::map<int64, int64> BookmarkNodeVersionMap; |
| 983 |
979 // TODO(ncarter): Integrate the existing TestNode/PopulateNodeFromString code | 984 // TODO(ncarter): Integrate the existing TestNode/PopulateNodeFromString code |
980 // in the bookmark model unittest, to make it simpler to set up test data | 985 // in the bookmark model unittest, to make it simpler to set up test data |
981 // here (and reduce the amount of duplication among tests), and to reduce the | 986 // here (and reduce the amount of duplication among tests), and to reduce the |
982 // duplication. | 987 // duplication. |
983 class ProfileSyncServiceBookmarkTestWithData | 988 class ProfileSyncServiceBookmarkTestWithData |
984 : public ProfileSyncServiceBookmarkTest { | 989 : public ProfileSyncServiceBookmarkTest { |
985 public: | 990 public: |
986 ProfileSyncServiceBookmarkTestWithData(); | 991 ProfileSyncServiceBookmarkTestWithData(); |
987 | 992 |
988 protected: | 993 protected: |
989 // Populates or compares children of the given bookmark node from/with the | 994 // Populates or compares children of the given bookmark node from/with the |
990 // given test data array with the given size. |running_count| is updated as | 995 // given test data array with the given size. |running_count| is updated as |
991 // urls are added. It is used to set the creation date (or test the creation | 996 // urls are added. It is used to set the creation date (or test the creation |
992 // date for CompareWithTestData()). | 997 // date for CompareWithTestData()). |
993 void PopulateFromTestData(const BookmarkNode* node, | 998 void PopulateFromTestData(const BookmarkNode* node, |
994 const TestData* data, | 999 const TestData* data, |
995 int size, | 1000 int size, |
996 int* running_count); | 1001 int* running_count); |
997 void CompareWithTestData(const BookmarkNode* node, | 1002 void CompareWithTestData(const BookmarkNode* node, |
998 const TestData* data, | 1003 const TestData* data, |
999 int size, | 1004 int size, |
1000 int* running_count); | 1005 int* running_count); |
1001 | 1006 |
1002 void ExpectBookmarkModelMatchesTestData(); | 1007 void ExpectBookmarkModelMatchesTestData(); |
1003 void WriteTestDataToBookmarkModel(); | 1008 void WriteTestDataToBookmarkModel(); |
1004 | 1009 |
| 1010 // Verify transaction versions of bookmark nodes and sync nodes are equal |
| 1011 // recursively. If node is in |version_expected|, versions should match |
| 1012 // there, too. |
| 1013 void ExpectTransactionVersionMatch( |
| 1014 const BookmarkNode* node, |
| 1015 const BookmarkNodeVersionMap& version_expected); |
| 1016 |
1005 private: | 1017 private: |
1006 const base::Time start_time_; | 1018 const base::Time start_time_; |
1007 | 1019 |
1008 DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceBookmarkTestWithData); | 1020 DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceBookmarkTestWithData); |
1009 }; | 1021 }; |
1010 | 1022 |
1011 namespace { | 1023 namespace { |
1012 | 1024 |
1013 // Constants for bookmark model that looks like: | 1025 // Constants for bookmark model that looks like: |
1014 // |-- Bookmark bar | 1026 // |-- Bookmark bar |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 DCHECK(node); | 1139 DCHECK(node); |
1128 DCHECK(data); | 1140 DCHECK(data); |
1129 DCHECK(node->is_folder()); | 1141 DCHECK(node->is_folder()); |
1130 for (int i = 0; i < size; ++i) { | 1142 for (int i = 0; i < size; ++i) { |
1131 const TestData& item = data[i]; | 1143 const TestData& item = data[i]; |
1132 if (item.url) { | 1144 if (item.url) { |
1133 const base::Time add_time = | 1145 const base::Time add_time = |
1134 start_time_ + base::TimeDelta::FromMinutes(*running_count); | 1146 start_time_ + base::TimeDelta::FromMinutes(*running_count); |
1135 model_->AddURLWithCreationTime(node, i, WideToUTF16Hack(item.title), | 1147 model_->AddURLWithCreationTime(node, i, WideToUTF16Hack(item.title), |
1136 GURL(item.url), add_time); | 1148 GURL(item.url), add_time); |
1137 (*running_count)++; | |
1138 } else { | 1149 } else { |
1139 model_->AddFolder(node, i, WideToUTF16Hack(item.title)); | 1150 model_->AddFolder(node, i, WideToUTF16Hack(item.title)); |
1140 } | 1151 } |
| 1152 (*running_count)++; |
1141 } | 1153 } |
1142 } | 1154 } |
1143 | 1155 |
1144 void ProfileSyncServiceBookmarkTestWithData::CompareWithTestData( | 1156 void ProfileSyncServiceBookmarkTestWithData::CompareWithTestData( |
1145 const BookmarkNode* node, | 1157 const BookmarkNode* node, |
1146 const TestData* data, | 1158 const TestData* data, |
1147 int size, | 1159 int size, |
1148 int* running_count) { | 1160 int* running_count) { |
1149 DCHECK(node); | 1161 DCHECK(node); |
1150 DCHECK(data); | 1162 DCHECK(data); |
1151 DCHECK(node->is_folder()); | 1163 DCHECK(node->is_folder()); |
1152 ASSERT_EQ(size, node->child_count()); | 1164 ASSERT_EQ(size, node->child_count()); |
1153 for (int i = 0; i < size; ++i) { | 1165 for (int i = 0; i < size; ++i) { |
1154 const BookmarkNode* child_node = node->GetChild(i); | 1166 const BookmarkNode* child_node = node->GetChild(i); |
1155 const TestData& item = data[i]; | 1167 const TestData& item = data[i]; |
1156 GURL url = GURL(item.url == NULL ? "" : item.url); | 1168 GURL url = GURL(item.url == NULL ? "" : item.url); |
1157 BookmarkNode test_node(url); | 1169 BookmarkNode test_node(url); |
1158 test_node.SetTitle(WideToUTF16Hack(item.title)); | 1170 test_node.SetTitle(WideToUTF16Hack(item.title)); |
1159 EXPECT_EQ(child_node->GetTitle(), test_node.GetTitle()); | 1171 EXPECT_EQ(child_node->GetTitle(), test_node.GetTitle()); |
1160 if (item.url) { | 1172 if (item.url) { |
1161 EXPECT_FALSE(child_node->is_folder()); | 1173 EXPECT_FALSE(child_node->is_folder()); |
1162 EXPECT_TRUE(child_node->is_url()); | 1174 EXPECT_TRUE(child_node->is_url()); |
1163 EXPECT_EQ(child_node->url(), test_node.url()); | 1175 EXPECT_EQ(child_node->url(), test_node.url()); |
1164 const base::Time expected_time = | 1176 const base::Time expected_time = |
1165 start_time_ + base::TimeDelta::FromMinutes(*running_count); | 1177 start_time_ + base::TimeDelta::FromMinutes(*running_count); |
1166 EXPECT_EQ(expected_time.ToInternalValue(), | 1178 EXPECT_EQ(expected_time.ToInternalValue(), |
1167 child_node->date_added().ToInternalValue()); | 1179 child_node->date_added().ToInternalValue()); |
1168 (*running_count)++; | |
1169 } else { | 1180 } else { |
1170 EXPECT_TRUE(child_node->is_folder()); | 1181 EXPECT_TRUE(child_node->is_folder()); |
1171 EXPECT_FALSE(child_node->is_url()); | 1182 EXPECT_FALSE(child_node->is_url()); |
1172 } | 1183 } |
| 1184 (*running_count)++; |
1173 } | 1185 } |
1174 } | 1186 } |
1175 | 1187 |
1176 // TODO(munjal): We should implement some way of generating random data and can | 1188 // TODO(munjal): We should implement some way of generating random data and can |
1177 // use the same seed to generate the same sequence. | 1189 // use the same seed to generate the same sequence. |
1178 void ProfileSyncServiceBookmarkTestWithData::WriteTestDataToBookmarkModel() { | 1190 void ProfileSyncServiceBookmarkTestWithData::WriteTestDataToBookmarkModel() { |
1179 const BookmarkNode* bookmarks_bar_node = model_->bookmark_bar_node(); | 1191 const BookmarkNode* bookmarks_bar_node = model_->bookmark_bar_node(); |
1180 int count = 0; | 1192 int count = 0; |
1181 PopulateFromTestData(bookmarks_bar_node, | 1193 PopulateFromTestData(bookmarks_bar_node, |
1182 kBookmarkBarChildren, | 1194 kBookmarkBarChildren, |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 updates.ApplyPendingChanges(change_processor_.get()); | 1600 updates.ApplyPendingChanges(change_processor_.get()); |
1589 | 1601 |
1590 const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(0); | 1602 const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(0); |
1591 ASSERT_TRUE(node); | 1603 ASSERT_TRUE(node); |
1592 EXPECT_TRUE(node->is_url()); | 1604 EXPECT_TRUE(node->is_url()); |
1593 EXPECT_EQ(WideToUTF16Hack(kTitle), node->GetTitle()); | 1605 EXPECT_EQ(WideToUTF16Hack(kTitle), node->GetTitle()); |
1594 EXPECT_EQ(kUrl, node->url().possibly_invalid_spec()); | 1606 EXPECT_EQ(kUrl, node->url().possibly_invalid_spec()); |
1595 EXPECT_EQ(node->date_added(), base::Time::FromInternalValue(30)); | 1607 EXPECT_EQ(node->date_added(), base::Time::FromInternalValue(30)); |
1596 } | 1608 } |
1597 | 1609 |
| 1610 // Output transaction versions of |node| and nodes under it to |node_versions|. |
| 1611 void GetTransactionVersions( |
| 1612 const BookmarkNode* root, |
| 1613 BookmarkNodeVersionMap* node_versions) { |
| 1614 node_versions->clear(); |
| 1615 std::queue<const BookmarkNode*> nodes; |
| 1616 nodes.push(root); |
| 1617 while (!nodes.empty()) { |
| 1618 const BookmarkNode* n = nodes.front(); |
| 1619 nodes.pop(); |
| 1620 |
| 1621 std::string version_str; |
| 1622 int64 version; |
| 1623 EXPECT_TRUE(n->GetMetaInfo(kBookmarkTransactionVersionKey, &version_str)); |
| 1624 EXPECT_TRUE(base::StringToInt64(version_str, &version)); |
| 1625 |
| 1626 (*node_versions)[n->id()] = version; |
| 1627 for (int i = 0; i < n->child_count(); ++i) |
| 1628 nodes.push(n->GetChild(i)); |
| 1629 } |
| 1630 } |
| 1631 |
| 1632 void ProfileSyncServiceBookmarkTestWithData::ExpectTransactionVersionMatch( |
| 1633 const BookmarkNode* node, |
| 1634 const BookmarkNodeVersionMap& version_expected) { |
| 1635 syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); |
| 1636 |
| 1637 BookmarkNodeVersionMap bnodes_versions; |
| 1638 GetTransactionVersions(node, &bnodes_versions); |
| 1639 for (BookmarkNodeVersionMap::const_iterator it = bnodes_versions.begin(); |
| 1640 it != bnodes_versions.end(); ++it) { |
| 1641 syncer::ReadNode sync_node(&trans); |
| 1642 ASSERT_TRUE(model_associator_->InitSyncNodeFromChromeId(it->first, |
| 1643 &sync_node)); |
| 1644 EXPECT_EQ(sync_node.GetEntry()->Get(syncer::syncable::TRANSACTION_VERSION), |
| 1645 it->second); |
| 1646 BookmarkNodeVersionMap::const_iterator expected_ver_it = |
| 1647 version_expected.find(it->first); |
| 1648 if (expected_ver_it != version_expected.end()) |
| 1649 EXPECT_EQ(expected_ver_it->second, it->second); |
| 1650 } |
| 1651 } |
| 1652 |
| 1653 // Test transaction versions of model and nodes are incremented after changes |
| 1654 // are applied. |
| 1655 TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateTransactionVersion) { |
| 1656 LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); |
| 1657 StartSync(); |
| 1658 WriteTestDataToBookmarkModel(); |
| 1659 MessageLoop::current()->RunUntilIdle(); |
| 1660 |
| 1661 BookmarkNodeVersionMap initial_versions; |
| 1662 |
| 1663 // Verify transaction versions in sync model and bookmark model (saved as |
| 1664 // transaction version of root node) are equal after |
| 1665 // WriteTestDataToBookmarkModel() created bookmarks. |
| 1666 { |
| 1667 syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); |
| 1668 EXPECT_GT(trans.GetModelVersion(syncer::BOOKMARKS), 0); |
| 1669 GetTransactionVersions(model_->root_node(), &initial_versions); |
| 1670 EXPECT_EQ(trans.GetModelVersion(syncer::BOOKMARKS), |
| 1671 initial_versions[model_->root_node()->id()]); |
| 1672 } |
| 1673 ExpectTransactionVersionMatch(model_->bookmark_bar_node(), |
| 1674 BookmarkNodeVersionMap()); |
| 1675 ExpectTransactionVersionMatch(model_->other_node(), |
| 1676 BookmarkNodeVersionMap()); |
| 1677 ExpectTransactionVersionMatch(model_->mobile_node(), |
| 1678 BookmarkNodeVersionMap()); |
| 1679 |
| 1680 // Verify model version is incremented and bookmark node versions remain |
| 1681 // the same. |
| 1682 const BookmarkNode* bookmark_bar = model_->bookmark_bar_node(); |
| 1683 model_->Remove(bookmark_bar, 0); |
| 1684 MessageLoop::current()->RunUntilIdle(); |
| 1685 BookmarkNodeVersionMap new_versions; |
| 1686 GetTransactionVersions(model_->root_node(), &new_versions); |
| 1687 EXPECT_EQ(initial_versions[model_->root_node()->id()] + 1, |
| 1688 new_versions[model_->root_node()->id()]); |
| 1689 // HACK(haitaol): siblings of removed node are actually updated in sync model |
| 1690 // because of NEXT_ID/PREV_ID. After switching to ordinal, |
| 1691 // siblings will not get updated and the hack below can be |
| 1692 // removed. |
| 1693 model_->SetNodeMetaInfo(bookmark_bar->GetChild(0), |
| 1694 kBookmarkTransactionVersionKey, "43"); |
| 1695 initial_versions[bookmark_bar->GetChild(0)->id()] = 43; |
| 1696 ExpectTransactionVersionMatch(model_->bookmark_bar_node(), initial_versions); |
| 1697 ExpectTransactionVersionMatch(model_->other_node(), initial_versions); |
| 1698 ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions); |
| 1699 |
| 1700 // Verify model version and version of changed bookmark are incremented and |
| 1701 // versions of others remain same. |
| 1702 const BookmarkNode* changed_bookmark = |
| 1703 model_->bookmark_bar_node()->GetChild(0); |
| 1704 model_->SetTitle(changed_bookmark, WideToUTF16Hack(L"test")); |
| 1705 MessageLoop::current()->RunUntilIdle(); |
| 1706 GetTransactionVersions(model_->root_node(), &new_versions); |
| 1707 EXPECT_EQ(initial_versions[model_->root_node()->id()] + 2, |
| 1708 new_versions[model_->root_node()->id()]); |
| 1709 EXPECT_EQ(initial_versions[changed_bookmark->id()] + 1, |
| 1710 new_versions[changed_bookmark->id()]); |
| 1711 initial_versions.erase(changed_bookmark->id()); |
| 1712 ExpectTransactionVersionMatch(model_->bookmark_bar_node(), initial_versions); |
| 1713 ExpectTransactionVersionMatch(model_->other_node(), initial_versions); |
| 1714 ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions); |
| 1715 } |
| 1716 |
1598 } // namespace | 1717 } // namespace |
1599 | 1718 |
1600 } // namespace browser_sync | 1719 } // namespace browser_sync |
OLD | NEW |