15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(akalin): This file is basically just a unit test for 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BookmarkChangeProcessor. Write unit tests for 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BookmarkModelAssociator separately. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stack> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h" 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client.h" 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/bookmark_change_processor.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/bookmark_model_associator.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h" 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/base_bookmark_model_observer.h" 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h" 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/test/bookmark_test_helpers.h" 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/sync_driver/data_type_error_handler.h" 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/sync_driver/data_type_error_handler_mock.h" 376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/sync_error.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/change_record.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/read_node.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/read_transaction.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/test/test_user_share.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/write_node.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/write_transaction.h" 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "sync/internal_api/syncapi_internal.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/mutable_entry.h" // TODO(tim): Remove. Bug 131130. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::BaseNode; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::InvokeWithoutArgs; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Mock; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::StrictMock; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_ANDROID) || defined(OS_IOS) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const bool kExpectMobileBookmarks = true; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const bool kExpectMobileBookmarks = false; 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif // defined(OS_ANDROID) || defined(OS_IOS) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FakeServerChange constructs a list of syncer::ChangeRecords while modifying 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the sync model, and can pass the ChangeRecord list to a 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// syncer::SyncObserver (i.e., the ProfileSyncService) to test the client 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// change-application behavior. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests using FakeServerChange should be careful to avoid back-references, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// since FakeServerChange will send the edits in the order specified. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FakeServerChange { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit FakeServerChange(syncer::WriteTransaction* trans) : trans_(trans) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pretend that the server told the syncer to add a bookmark object. 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 AddWithMetaInfo(const std::string& title, 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& url, 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info_map, 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool is_folder, 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_id, 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 predecessor_id) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode parent(trans_); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, parent.InitByIdLookup(parent_id)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteNode node(trans_); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (predecessor_id == 0) { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(node.InitBookmarkByCreation(parent, NULL)); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode predecessor(trans_); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, predecessor.InitByIdLookup(predecessor_id)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(predecessor.GetParentId(), parent.GetId()); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(node.InitBookmarkByCreation(parent, &predecessor)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(node.GetPredecessorId(), predecessor_id); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(node.GetParentId(), parent_id); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetIsFolder(is_folder); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetTitle(title); 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::BookmarkSpecifics specifics(node.GetBookmarkSpecifics()); 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!is_folder) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.set_url(url); 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (meta_info_map) 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SetNodeMetaInfo(*meta_info_map, &specifics); 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node.SetBookmarkSpecifics(specifics); 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecord record; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) record.action = syncer::ChangeRecord::ACTION_ADD; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) record.id = node.GetId(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes_.push_back(record); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node.GetId(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 Add(const std::string& title, 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& url, 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool is_folder, 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_id, 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 predecessor_id) { 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return AddWithMetaInfo(title, url, NULL, is_folder, parent_id, 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) predecessor_id); 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a bookmark folder. 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 AddFolder(const std::string& title, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 parent_id, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 predecessor_id) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Add(title, std::string(), true, parent_id, predecessor_id); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 AddFolderWithMetaInfo(const std::string& title, 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info_map, 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_id, 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 predecessor_id) { 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return AddWithMetaInfo(title, std::string(), meta_info_map, true, parent_id, 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) predecessor_id); 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a bookmark. 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 AddURL(const std::string& title, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 parent_id, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 predecessor_id) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Add(title, url, false, parent_id, predecessor_id); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 AddURLWithMetaInfo(const std::string& title, 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& url, 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info_map, 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_id, 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 predecessor_id) { 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return AddWithMetaInfo(title, url, meta_info_map, false, parent_id, 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) predecessor_id); 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pretend that the server told the syncer to delete an object. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Delete(int64 id) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the sync node. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteNode node(trans_); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(id)); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (node.GetIsFolder()) 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(node.GetFirstChildId()); 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) node.GetMutableEntryForTest()->PutServerIsDel(true); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.Tombstone(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify the deletion. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode node(trans_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_IS_DEL, node.InitByIdLookup(id)); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecord record; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) record.action = syncer::ChangeRecord::ACTION_DELETE; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) record.id = id; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deletions are always first in the changelist, but we can't actually do 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WriteNode::Remove() on the node until its children are moved. So, as 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a practical matter, users of FakeServerChange must move or delete 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // children before parents. Thus, we must insert the deletion record 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // at the front of the vector. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes_.insert(changes_.begin(), record); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set a new title value, and return the old value. 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string ModifyTitle(int64 id, const std::string& new_title) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteNode node(trans_); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(id)); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_title = node.GetTitle(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetTitle(new_title); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModified(id); 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return old_title; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set a new parent and predecessor value. Return the old parent id. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We could return the old predecessor id, but it turns out not to be 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // very useful for assertions. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 ModifyPosition(int64 id, int64 parent_id, int64 predecessor_id) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode parent(trans_); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, parent.InitByIdLookup(parent_id)); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteNode node(trans_); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(id)); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 old_parent_id = node.GetParentId(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (predecessor_id == 0) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(node.SetPosition(parent, NULL)); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode predecessor(trans_); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, predecessor.InitByIdLookup(predecessor_id)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(predecessor.GetParentId(), parent.GetId()); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(node.SetPosition(parent, &predecessor)); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModified(id); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return old_parent_id; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ModifyCreationTime(int64 id, int64 creation_time_us) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteNode node(trans_); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(id)); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::BookmarkSpecifics specifics = node.GetBookmarkSpecifics(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) specifics.set_creation_time_us(creation_time_us); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetBookmarkSpecifics(specifics); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModified(id); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void ModifyMetaInfo(int64 id, 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode::MetaInfoMap& meta_info_map) { 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncer::WriteNode node(trans_); 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(id)); 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::BookmarkSpecifics specifics = node.GetBookmarkSpecifics(); 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SetNodeMetaInfo(meta_info_map, &specifics); 227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node.SetBookmarkSpecifics(specifics); 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SetModified(id); 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pass the fake change list to |service|. 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void ApplyPendingChanges(sync_driver::ChangeProcessor* processor) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processor->ApplyChangesFromSyncModel( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_, 0, syncer::ImmutableChangeRecordList(&changes_)); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncer::ChangeRecordList& changes() { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return changes_; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helper function to push an ACTION_UPDATE record onto the back 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the changelist. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetModified(int64 id) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Coalesce multi-property edits. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!changes_.empty() && changes_.back().id == id && 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes_.back().action == 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecord::ACTION_UPDATE) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecord record; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) record.action = syncer::ChangeRecord::ACTION_UPDATE; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) record.id = id; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes_.push_back(record); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void SetNodeMetaInfo(const BookmarkNode::MetaInfoMap& meta_info_map, 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::BookmarkSpecifics* specifics) { 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) specifics->clear_meta_info(); 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (BookmarkNode::MetaInfoMap::const_iterator it = 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) meta_info_map.begin(); it != meta_info_map.end(); ++it) { 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::MetaInfo* meta_info = specifics->add_meta_info(); 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) meta_info->set_key(it->first); 263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) meta_info->set_value(it->second); 264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The transaction on which everything happens. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction *trans_; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The change list we construct. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecordList changes_; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensiveChangesBookmarkModelObserver : public BaseBookmarkModelObserver { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ExtensiveChangesBookmarkModelObserver() 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : started_count_(0), 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_count_at_started_(0), 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_count_(0) {} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ExtensiveBookmarkChangesBeginning( 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model) OVERRIDE { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++started_count_; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_count_at_started_ = completed_count_; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ExtensiveBookmarkChangesEnded(BookmarkModel* model) OVERRIDE { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++completed_count_; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void BookmarkModelChanged() OVERRIDE {} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int get_started() const { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return started_count_; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int get_completed_count_at_started() const { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return completed_count_at_started_; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int get_completed() const { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return completed_count_; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int started_count_; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int completed_count_at_started_; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int completed_count_; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensiveChangesBookmarkModelObserver); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileSyncServiceBookmarkTest : public testing::Test { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum LoadOption { LOAD_FROM_STORAGE, DELETE_EXISTING_STORAGE }; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum SaveOption { SAVE_TO_STORAGE, DONT_SAVE_TO_STORAGE }; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileSyncServiceBookmarkTest() 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : model_(NULL), 3226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) thread_bundle_(content::TestBrowserThreadBundle::DEFAULT), 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_(syncer::BOOKMARKS), 3246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) syncer_merge_result_(syncer::BOOKMARKS) {} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ProfileSyncServiceBookmarkTest() { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadBookmarkModel(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_user_share_.SetUp(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_user_share_.TearDown(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool CanSyncNode(const BookmarkNode* node) { 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return model_->client()->CanSyncNode(node); 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Inserts a folder directly to the share. 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Do not use this after model association is complete. 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This function differs from the AddFolder() function declared elsewhere in 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // this file in that it only affects the sync model. It would be invalid to 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // change the sync model directly after ModelAssociation. This function can 34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // be invoked prior to model association to set up first-time sync model 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // association scenarios. 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int64 AddFolderToShare(syncer::WriteTransaction* trans, std::string title) { 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(model_associator_); 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Be sure to call CreatePermanentBookmarkNodes(), otherwise this will fail. 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syncer::ReadNode bookmark_bar(trans); 35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, 35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bookmark_bar.InitByTagLookupForBookmarks("bookmark_bar")); 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syncer::WriteNode node(trans); 36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(node.InitBookmarkByCreation(bookmark_bar, NULL)); 36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) node.SetIsFolder(true); 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch node.SetTitle(title); 36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return node.GetId(); 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Inserts a bookmark directly to the share. 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Do not use this after model association is complete. 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // 37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This function differs from the AddURL() function declared elsewhere in this 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // file in that it only affects the sync model. It would be invalid to change 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the sync model directly after ModelAssociation. This function can be 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // invoked prior to model association to set up first-time sync model 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // association scenarios. 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int64 AddBookmarkToShare(syncer::WriteTransaction *trans, 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int64 parent_id, 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string title) { 37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(model_associator_); 37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syncer::ReadNode parent(trans); 38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, parent.InitByIdLookup(parent_id)); 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sync_pb::BookmarkSpecifics specifics; 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) specifics.set_url("http://www.google.com/search?q=" + title); 38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) specifics.set_title(title); 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syncer::WriteNode node(trans); 38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(node.InitBookmarkByCreation(parent, NULL)); 38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) node.SetIsFolder(false); 3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch node.SetTitle(title); 39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) node.SetBookmarkSpecifics(specifics); 39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return node.GetId(); 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load (or re-load) the bookmark model. |load| controls use of the 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmarks file on disk. |save| controls whether the newly loaded 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmark model will write out a bookmark file as it goes. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void LoadBookmarkModel(LoadOption load, SaveOption save) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool delete_bookmarks = load == DELETE_EXISTING_STORAGE; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_.CreateBookmarkModel(delete_bookmarks); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_ = BookmarkModelFactory::GetForProfile(&profile_); 40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) test::WaitForBookmarkModelToLoad(model_); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This noticeably speeds up the unit tests that request it. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save == DONT_SAVE_TO_STORAGE) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->ClearStore(); 4076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int GetSyncBookmarkCount() { 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode node(&trans); 41346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (node.InitTypeRoot(syncer::BOOKMARKS) != syncer::BaseNode::INIT_OK) 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return node.GetTotalNodeCount(); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates the bookmark root node and the permanent nodes if they don't 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // already exist. 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool CreatePermanentBookmarkNodes() { 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool root_exists = false; 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type = syncer::BOOKMARKS; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_user_share_.user_share()); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode uber_root(&trans); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uber_root.InitByRootLookup(); 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode root(&trans); 43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) root_exists = (root.InitTypeRoot(type) == BaseNode::INIT_OK); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!root_exists) { 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!syncer::TestUserShare::CreateRoot(type, 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_user_share_.user_share())) 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kNumPermanentNodes = 3; 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string permanent_tags[kNumPermanentNodes] = { 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_IOS) 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "synced_bookmarks", 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "bookmark_bar", 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "other_bookmarks", 446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined(OS_IOS) 447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "synced_bookmarks", 448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode root(&trans); 45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, root.InitTypeRoot(type)); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Loop through creating permanent nodes as necessary. 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 last_child_id = syncer::kInvalidId; 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kNumPermanentNodes; ++i) { 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First check if the node already exists. This is for tests that involve 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // persistence and set up sync more than once. 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode lookup(&trans); 46046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (lookup.InitByTagLookupForBookmarks(permanent_tags[i]) == 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode::INIT_OK) { 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_child_id = lookup.GetId(); 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it doesn't exist, create the permanent node at the end of the 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ordering. 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode predecessor_node(&trans); 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ReadNode* predecessor = NULL; 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_child_id != syncer::kInvalidId) { 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(BaseNode::INIT_OK, 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) predecessor_node.InitByIdLookup(last_child_id)); 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) predecessor = &predecessor_node; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::WriteNode node(&trans); 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!node.InitBookmarkByCreation(root, predecessor)) 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.SetIsFolder(true); 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) node.GetMutableEntryForTest()->PutUniqueServerTag(permanent_tags[i]); 4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch node.SetTitle(permanent_tags[i]); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.SetExternalId(0); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_child_id = node.GetId(); 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool AssociateModels() { 488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!model_associator_); 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up model associator. 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_associator_.reset(new BookmarkModelAssociator( 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelFactory::GetForProfile(&profile_), 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &profile_, 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_user_share_.user_share(), 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &mock_error_handler_, 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kExpectMobileBookmarks)); 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_ = syncer::SyncMergeResult(syncer::BOOKMARKS); 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer_merge_result_ = syncer::SyncMergeResult(syncer::BOOKMARKS); 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int local_count_before = model_->root_node()->GetTotalNodeCount(); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int syncer_count_before = GetSyncBookmarkCount(); 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error = model_associator_->AssociateModels( 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &local_merge_result_, 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &syncer_merge_result_); 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (error.IsSet()) 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoop::current()->RunUntilIdle(); 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify the merge results were calculated properly. 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(local_count_before, 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_.num_items_before_association()); 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(syncer_count_before, 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer_merge_result_.num_items_before_association()); 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(local_merge_result_.num_items_after_association(), 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_.num_items_before_association() + 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_.num_items_added() - 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_.num_items_deleted()); 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(syncer_merge_result_.num_items_after_association(), 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer_merge_result_.num_items_before_association() + 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer_merge_result_.num_items_added() - 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer_merge_result_.num_items_deleted()); 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(model_->root_node()->GetTotalNodeCount(), 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_merge_result_.num_items_after_association()); 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(GetSyncBookmarkCount(), 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer_merge_result_.num_items_after_association()); 528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void StartSync() { 532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test_user_share_.Reload(); 533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(CreatePermanentBookmarkNodes()); 535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(AssociateModels()); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up change processor. 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) change_processor_.reset( 5390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new BookmarkChangeProcessor(&profile_, 5400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model_associator_.get(), 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &mock_error_handler_)); 5420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch change_processor_->Start(test_user_share_.user_share()); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopSync() { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) change_processor_.reset(); 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (model_associator_) { 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error = model_associator_->DisassociateModels(); 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(error.IsSet()); 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_.reset(); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(akalin): Actually close the database and flush it to disk 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (and make StartSync reload from disk). This would require 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // refactoring TestUserShare. 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UnloadBookmarkModel() { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_.CreateBookmarkModel(false /* delete_bookmarks */); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_ = NULL; 5636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool InitSyncNodeFromChromeNode(const BookmarkNode* bnode, 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::BaseNode* sync_node) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return model_associator_->InitSyncNodeFromChromeId(bnode->id(), 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_node); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectSyncerNodeMatching(syncer::BaseTransaction* trans, 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bnode) { 574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string truncated_title = base::UTF16ToUTF8(bnode->GetTitle()); 575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncer::SyncAPINameToServerName(truncated_title, &truncated_title); 576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TruncateUTF8ToByteSize(truncated_title, 255, &truncated_title); 577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncer::ServerNameToSyncAPIName(truncated_title, &truncated_title); 578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode gnode(trans); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(InitSyncNodeFromChromeNode(bnode, &gnode)); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-root node titles and parents must match. 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_->is_permanent_node(bnode)) { 583a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(truncated_title, gnode.GetTitle()); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ( 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetChromeNodeFromSyncId(gnode.GetParentId()), 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bnode->parent()); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(bnode->is_folder(), gnode.GetIsFolder()); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bnode->is_url()) 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(bnode->url(), GURL(gnode.GetBookmarkSpecifics().url())); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Check that meta info matches. 593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info_map = bnode->GetMetaInfoMap(); 594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::BookmarkSpecifics specifics = gnode.GetBookmarkSpecifics(); 595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!meta_info_map) { 596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(0, specifics.meta_info_size()); 597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(meta_info_map->size(), 599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<size_t>(specifics.meta_info_size())); 600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (int i = 0; i < specifics.meta_info_size(); i++) { 601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BookmarkNode::MetaInfoMap::const_iterator it = 602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) meta_info_map->find(specifics.meta_info(i).key()); 603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(it != meta_info_map->end()); 604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(it->second, specifics.meta_info(i).value()); 605a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 606a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 607a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for position matches. 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int browser_index = bnode->parent()->GetIndexOf(bnode); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_index == 0) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gnode.GetPredecessorId(), 0); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bprev = 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bnode->parent()->GetChild(browser_index - 1); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode gprev(trans); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(InitSyncNodeFromChromeNode(bprev, &gprev)); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gnode.GetPredecessorId(), gprev.GetId()); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gnode.GetParentId(), gprev.GetParentId()); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 620116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Note: the managed node is the last child of the root_node but isn't 621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // synced; if CanSyncNode() is false then there is no next node to sync. 622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const BookmarkNode* bnext = NULL; 623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (browser_index + 1 < bnode->parent()->child_count()) 624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bnext = bnode->parent()->GetChild(browser_index + 1); 625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!bnext || !CanSyncNode(bnext)) { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gnode.GetSuccessorId(), 0); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode gnext(trans); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(InitSyncNodeFromChromeNode(bnext, &gnext)); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gnode.GetSuccessorId(), gnext.GetId()); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gnode.GetParentId(), gnext.GetParentId()); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bnode->empty()) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(gnode.GetFirstChildId()); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectSyncerNodeMatching(const BookmarkNode* bnode) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(&trans, bnode); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectBrowserNodeMatching(syncer::BaseTransaction* trans, 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 sync_id) { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(sync_id); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bnode = 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetChromeNodeFromSyncId(sync_id); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(bnode); 648116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_TRUE(CanSyncNode(bnode)); 64946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id = model_associator_->GetSyncIdFromChromeId(bnode->id()); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(id, sync_id); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(trans, bnode); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectBrowserNodeUnknown(int64 sync_id) { 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(model_associator_->GetChromeNodeFromSyncId(sync_id)); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectBrowserNodeKnown(int64 sync_id) { 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(model_associator_->GetChromeNodeFromSyncId(sync_id)); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectSyncerNodeKnown(const BookmarkNode* node) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 sync_id = model_associator_->GetSyncIdFromChromeId(node->id()); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_NE(sync_id, syncer::kInvalidId); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectSyncerNodeUnknown(const BookmarkNode* node) { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 sync_id = model_associator_->GetSyncIdFromChromeId(node->id()); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(sync_id, syncer::kInvalidId); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void ExpectBrowserNodeTitle(int64 sync_id, const std::string& title) { 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bnode = 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetChromeNodeFromSyncId(sync_id); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(bnode); 6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(bnode->GetTitle(), base::UTF8ToUTF16(title)); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectBrowserNodeURL(int64 sync_id, const std::string& url) { 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bnode = 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetChromeNodeFromSyncId(sync_id); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(bnode); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(GURL(url), bnode->url()); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectBrowserNodeParent(int64 sync_id, int64 parent_sync_id) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetChromeNodeFromSyncId(sync_id); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(node); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetChromeNodeFromSyncId(parent_sync_id); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parent); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(node->parent(), parent); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectModelMatch(syncer::BaseTransaction* trans) { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* root = model_->root_node(); 699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_IOS) 700116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(root->GetIndexOf(model_->mobile_node()), 0); 701116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(root->GetIndexOf(model_->bookmark_bar_node()), 1); 702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(root->GetIndexOf(model_->other_node()), 2); 703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(root->GetIndexOf(model_->bookmark_bar_node()), 0); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(root->GetIndexOf(model_->other_node()), 1); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(root->GetIndexOf(model_->mobile_node()), 2); 707116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::stack<int64> stack; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack.push(bookmark_bar_id()); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!stack.empty()) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id = stack.top(); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack.pop(); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!id) continue; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeMatching(trans, id); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode gnode(trans); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(BaseNode::INIT_OK, gnode.InitByIdLookup(id)); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack.push(gnode.GetSuccessorId()); 721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (gnode.GetIsFolder()) 722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stack.push(gnode.GetFirstChildId()); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectModelMatch() { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 mobile_bookmarks_id() { 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetSyncIdFromChromeId(model_->mobile_node()->id()); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 other_bookmarks_id() { 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_associator_->GetSyncIdFromChromeId(model_->other_node()->id()); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 bookmark_bar_id() { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return model_associator_->GetSyncIdFromChromeId( 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->bookmark_bar_node()->id()); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestingProfile profile_; 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarkModel* model_; 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::TestUserShare test_user_share_; 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<BookmarkChangeProcessor> change_processor_; 7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) StrictMock<sync_driver::DataTypeErrorHandlerMock> mock_error_handler_; 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<BookmarkModelAssociator> model_associator_; 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 7556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) content::TestBrowserThreadBundle thread_bundle_; 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult local_merge_result_; 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult syncer_merge_result_; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, InitialState) { 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(other_bookmarks_id()); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bookmark_bar_id()); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(mobile_bookmarks_id()); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 77190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Populate the sync database then start model association. Sync's bookmarks 77290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// should end up being copied into the native model, resulting in a successful 77390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "ExpectModelMatch()". 77490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 77590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This code has some use for verifying correctness. It's also a very useful 77690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// for profiling bookmark ModelAssociation, an important part of some first-time 77790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// sync scenarios. Simply increase the kNumFolders and kNumBookmarksPerFolder 77890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// as desired, then run the test under a profiler to find hot spots in the model 77990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// association code. 78090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, InitialModelAssociate) { 78190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const int kNumBookmarksPerFolder = 10; 78290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const int kNumFolders = 10; 78390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 78490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreatePermanentBookmarkNodes(); 78590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 78690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { 78790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 78890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int i = 0; i < kNumFolders; ++i) { 78990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int64 folder_id = AddFolderToShare(&trans, 79090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::StringPrintf("folder%05d", i)); 79190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int j = 0; j < kNumBookmarksPerFolder; ++j) { 79290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AddBookmarkToShare(&trans, 79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) folder_id, 79490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::StringPrintf("bookmark%05d", j)); 79590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 79690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 79790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 79890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 79990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 80090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StartSync(); 80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 80290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExpectModelMatch(); 80390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, BookmarkModelOperations) { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test addition. 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* folder = 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(model_->other_node(), 0, base::ASCIIToUTF16("foobar")); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(folder); 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* folder2 = 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(folder, 0, base::ASCIIToUTF16("nested")); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(folder2); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* url1 = model_->AddURL( 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) folder, 0, base::ASCIIToUTF16("Internets #1 Pies Site"), 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://www.easypie.com/")); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(url1); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* url2 = model_->AddURL( 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) folder, 1, base::ASCIIToUTF16("Airplanes"), 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL("http://www.easyjet.com/")); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(url2); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test addition. 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* mobile_folder = 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(model_->mobile_node(), 0, base::ASCIIToUTF16("pie")); 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(mobile_folder); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test modification. 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->SetTitle(url2, base::ASCIIToUTF16("EasyJet")); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(url1, folder2, 0); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(folder2, model_->bookmark_bar_node(), 0); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->SetTitle(folder2, base::ASCIIToUTF16("Not Nested")); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(folder, folder2, 0); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->SetTitle(folder, base::ASCIIToUTF16("who's nested now?")); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Copy(url2, model_->bookmark_bar_node(), 0); 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->SetTitle(mobile_folder, base::ASCIIToUTF16("strawberry")); 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test deletion. 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete a single item. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(url2->parent(), url2->parent()->GetIndexOf(url2)); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete an item with several children. 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(folder2->parent(), 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) folder2->parent()->GetIndexOf(folder2)); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(model_->mobile_node(), 0); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, ServerChangeProcessing) { 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange adds(&trans); 8720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 f1 = adds.AddFolder("Server Folder B", bookmark_bar_id(), 0); 8730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 f2 = adds.AddFolder("Server Folder A", bookmark_bar_id(), f1); 8740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u1 = adds.AddURL("Some old site", "ftp://nifty.andrew.cmu.edu/", 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_bar_id(), f2); 8760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u2 = adds.AddURL("Nifty", "ftp://nifty.andrew.cmu.edu/", f1, 0); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // u3 is a duplicate URL 8780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u3 = adds.AddURL("Nifty2", "ftp://nifty.andrew.cmu.edu/", f1, u2); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // u4 is a duplicate title, different URL. 8800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch adds.AddURL("Some old site", "http://slog.thestranger.com/", 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_bar_id(), u1); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // u5 tests an empty-string title. 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string javascript_url( 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "javascript:(function(){var w=window.open(" \ 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "'about:blank','gnotesWin','location=0,menubar=0," \ 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "scrollbars=0,status=0,toolbar=0,width=300," \ 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "height=300,resizable');});"); 8880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch adds.AddURL(std::string(), javascript_url, other_bookmarks_id(), 0); 889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int64 u6 = adds.AddURL( 8900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch "Sync1", "http://www.syncable.edu/", mobile_bookmarks_id(), 0); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecordList::const_iterator it; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The bookmark model shouldn't yet have seen any of the nodes of |adds|. 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeUnknown(it->id); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the bookmark model received all of the nodes in |adds|. 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeMatching(&trans, it->id); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Part two: test modifications. 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange mods(&trans); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mess with u2, and move it into empty folder f2 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ncarter): Determine if we allow ModifyURL ops or not. 9080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch /* std::string u2_old_url = mods.ModifyURL(u2, "http://www.google.com"); */ 9090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string u2_old_title = mods.ModifyTitle(u2, "The Google"); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 u2_old_parent = mods.ModifyPosition(u2, f2, 0); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now move f1 after u2. 9130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string f1_old_title = mods.ModifyTitle(f1, "Server Folder C"); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 f1_old_parent = mods.ModifyPosition(f1, f2, u2); 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then add u3 after f1. 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 u3_old_parent = mods.ModifyPosition(u3, f2, f1); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string u6_old_title = mods.ModifyTitle(u6, "Mobile Folder A"); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that the property changes have not yet taken effect. 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeTitle(u2, u2_old_title); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ExpectBrowserNodeURL(u2, u2_old_url); */ 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeParent(u2, u2_old_parent); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeTitle(f1, f1_old_title); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeParent(f1, f1_old_parent); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeParent(u3, u3_old_parent); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeTitle(u6, u6_old_title); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Apply the changes. 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mods.ApplyPendingChanges(change_processor_.get()); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for successful application. 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = mods.changes().begin(); it != mods.changes().end(); ++it) 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeMatching(&trans, it->id); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Part 3: Test URL deletion. 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange dels(&trans); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dels.Delete(u2); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dels.Delete(u3); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dels.Delete(u6); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeKnown(u2); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeKnown(u3); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dels.ApplyPendingChanges(change_processor_.get()); 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeUnknown(u2); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeUnknown(u3); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeUnknown(u6); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests a specific case in ApplyModelChanges where we move the 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// children out from under a parent, and then delete the parent 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the same changelist. The delete shows up first in the changelist, 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requiring the children to be moved to a temporary location. 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, ServerChangeRequiringFosterParent) { 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stress the immediate children of other_node because that's where 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ApplyModelChanges puts a temporary foster parent node. 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url("http://dev.chromium.org/"); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange adds(&trans); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 f0 = other_bookmarks_id(); // + other_node 9730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 f1 = adds.AddFolder("f1", f0, 0); // + f1 9740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 f2 = adds.AddFolder("f2", f1, 0); // + f2 9750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u3 = adds.AddURL( "u3", url, f2, 0); // + u3 NOLINT 9760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u4 = adds.AddURL( "u4", url, f2, u3); // + u4 NOLINT 9770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u5 = adds.AddURL( "u5", url, f1, f2); // + u5 NOLINT 9780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 f6 = adds.AddFolder("f6", f1, u5); // + f6 9790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 u7 = adds.AddURL( "u7", url, f0, f1); // + u7 NOLINT 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ChangeRecordList::const_iterator it; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The bookmark model shouldn't yet have seen any of the nodes of |adds|. 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeUnknown(it->id); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the bookmark model received all of the nodes in |adds|. 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBrowserNodeMatching(&trans, it->id); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have to do the moves before the deletions, but FakeServerChange will 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // put the deletion at the front of the changelist. 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange ops(&trans); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ModifyPosition(f6, other_bookmarks_id(), 0); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ModifyPosition(u3, other_bookmarks_id(), f1); // Prev == f1 is OK here. 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ModifyPosition(f2, other_bookmarks_id(), u7); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ModifyPosition(u7, f2, 0); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ModifyPosition(u4, other_bookmarks_id(), f2); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ModifyPosition(u5, f6, 0); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.Delete(f1); 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops.ApplyPendingChanges(change_processor_.get()); 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simulate a server change record containing a valid but non-canonical URL. 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, ServerChangeWithNonCanonicalURL) { 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange adds(&trans); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url("http://dev.chromium.org"); 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_NE(GURL(url).spec(), url); 10200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch adds.AddURL("u1", url, other_bookmarks_id(), 0); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1024a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(1, model_->other_node()->child_count()); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now reboot the sync service, forcing a merge step. 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There should still be just the one bookmark. 1034a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(1, model_->other_node()->child_count()); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simulate a server change record containing an invalid URL (per GURL). 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(ncarter): Disabled due to crashes. Fix bug 1677563. 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, DISABLED_ServerChangeWithInvalidURL) { 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int child_count = 0; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange adds(&trans); 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url("x"); 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(GURL(url).is_valid()); 10510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch adds.AddURL("u1", url, other_bookmarks_id(), 0); 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're lenient about what should happen -- the model could wind up with 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the node or without it; but things should be consistent, and we 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shouldn't crash. 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_count = model_->other_node()->child_count(); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(child_count == 0 || child_count == 1); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(&trans); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now reboot the sync service, forcing a merge step. 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Things ought not to have changed. 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(model_->other_node()->child_count(), child_count); 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test strings that might pose a problem if the titles ever became used as 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file names in the sync backend. 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, CornerCaseNames) { 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ncarter): Bug 1570238 explains the failure of this test. 1078a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* names[] = { 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The empty string. 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "", 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Illegal Windows filenames. 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current/parent directory markers. 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ".", "..", "...", 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Files created automatically by the Windows shell. 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Thumbs.db", ".DS_Store", 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Names including Win32-illegal characters, and path separators. 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "foo/bar", "foo\\bar", "foo?bar", "foo:bar", "foo|bar", "foo\"bar", 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "foo'bar", "foo<bar", "foo>bar", "foo%bar", "foo*bar", "foo]bar", 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "foo[bar", 1096a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // A name with title > 255 characters 1097a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "012345678901234567890123456789012345678901234567890123456789012345678901" 1098a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "234567890123456789012345678901234567890123456789012345678901234567890123" 1099a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "456789012345678901234567890123456789012345678901234567890123456789012345" 1100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "678901234567890123456789012345678901234567890123456789012345678901234567" 1101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "890123456789" 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create both folders and bookmarks using each name. 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url("http://www.doublemint.com"); 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(names); ++i) { 11065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(model_->other_node(), 0, base::ASCIIToUTF16(names[i])); 11075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16(names[i]), url); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the browser model matches the sync model. 1111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(static_cast<size_t>(model_->other_node()->child_count()), 1112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2*arraysize(names)); 1113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExpectModelMatch(); 1114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Restart and re-associate. Verify things still match. 1116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopSync(); 1117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 1118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartSync(); 1119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(static_cast<size_t>(model_->other_node()->child_count()), 1120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2*arraysize(names)); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stress the internal representation of position by sparse numbers. We want 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to repeatedly bisect the range of available positions, to force the 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// syncer code to renumber its ranges. Pick a number big enough so that it 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would exhaust 32bits of room between items a couple of times. 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, RepeatedMiddleInsertion) { 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kTimesToInsert = 256; 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create two book-end nodes to insert between. 11355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(model_->other_node(), 0, base::ASCIIToUTF16("Alpha")); 11365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(model_->other_node(), 1, base::ASCIIToUTF16("Omega")); 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 2; 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test insertion in first half of range by repeatedly inserting in second 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position. 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kTimesToInsert; ++i) { 1142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 title = 11435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ASCIIToUTF16("Pre-insertion ") + base::IntToString16(i); 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddFolder(model_->other_node(), 1, title); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test insertion in second half of range by repeatedly inserting in 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // second-to-last position. 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kTimesToInsert; ++i) { 1151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 title = 11525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ASCIIToUTF16("Post-insertion ") + base::IntToString16(i); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddFolder(model_->other_node(), count - 1, title); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the browser model matches the sync model. 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(model_->other_node()->child_count(), count); 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Introduce a consistency violation into the model, and see that it 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// puts itself into a lame, error state. 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, UnrecoverableErrorSuspendsService) { 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(mock_error_handler_, 11666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnSingleDataTypeUnrecoverableError(_)); 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a node which will be the target of the consistency violation. 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = 11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(model_->other_node(), 0, base::ASCIIToUTF16("node")); 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeMatching(node); 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now destroy the syncer node as if we were the ProfileSyncService without 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // updating the ProfileSyncService state. This should introduce 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inconsistency between the two models. 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteNode sync_node(&trans); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(InitSyncNodeFromChromeNode(node, &sync_node)); 11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_node.Tombstone(); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The models don't match at this point, but the ProfileSyncService 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // doesn't know it yet. 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectSyncerNodeKnown(node); 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a child to the inconsistent node. This should cause detection of the 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // problem and the syncer should stop processing changes. 11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddFolder(node, 0, base::ASCIIToUTF16("nested")); 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See what happens if we run model association when there are two exact URL 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// duplicate bookmarks. The BookmarkModelAssociator should not fall over when 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this happens. 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, MergeDuplicates) { 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16("Dup"), 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://dup.com/")); 12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16("Dup"), 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://dup.com/")); 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, model_->other_node()->child_count()); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restart the sync service to trigger model association. 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, model_->other_node()->child_count()); 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, ApplySyncDeletesFromJournal) { 12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Initialize sync model and bookmark model as: 12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // URL 0 12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Folder 1 12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |-- URL 1 12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // +-- Folder 2 12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // +-- URL 2 12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 12242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 u0 = 0; 12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 f1 = 0; 12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 u1 = 0; 12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 f2 = 0; 12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 u2 = 0; 12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSync(); 12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int fixed_sync_bk_count = GetSyncBookmarkCount(); 12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FakeServerChange adds(&trans); 12340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch u0 = adds.AddURL("URL 0", "http://plus.google.com/", bookmark_bar_id(), 0); 12350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch f1 = adds.AddFolder("Folder 1", bookmark_bar_id(), u0); 12360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch u1 = adds.AddURL("URL 1", "http://www.google.com/", f1, 0); 12370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch f2 = adds.AddFolder("Folder 2", f1, u1); 12380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch u2 = adds.AddURL("URL 2", "http://mail.google.com/", f2, 0); 12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopSync(); 12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Reload bookmark model and disable model saving to make sync changes not 12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // persisted. 12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE); 12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(6, model_->bookmark_bar_node()->GetTotalNodeCount()); 12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(fixed_sync_bk_count + 5, GetSyncBookmarkCount()); 12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSync(); 12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove all folders/bookmarks except u3 added above. 12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FakeServerChange dels(&trans); 12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dels.Delete(u2); 12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dels.Delete(f2); 12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dels.Delete(u1); 12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dels.Delete(f1); 12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dels.ApplyPendingChanges(change_processor_.get()); 12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopSync(); 12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Bookmark bar itself and u0 remain. 12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(2, model_->bookmark_bar_node()->GetTotalNodeCount()); 12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Reload bookmarks including ones deleted in sync model from storage. 12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE); 12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(6, model_->bookmark_bar_node()->GetTotalNodeCount()); 12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add a bookmark under f1 when sync is off so that f1 will not be 12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // deleted even when f1 matches delete journal because it's not empty. 12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_->AddURL(model_->bookmark_bar_node()->GetChild(1), 12695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, base::UTF8ToUTF16("local"), GURL("http://www.youtube.com")); 12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Sync model has fixed bookmarks nodes and u3. 12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(fixed_sync_bk_count + 1, GetSyncBookmarkCount()); 12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSync(); 12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expect 4 bookmarks after model association because u2, f2, u1 are removed 12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // by delete journal, f1 is not removed by delete journal because it's 12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not empty due to www.youtube.com added above. 12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(4, model_->bookmark_bar_node()->GetTotalNodeCount()); 12775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(base::UTF8ToUTF16("URL 0"), 12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_->bookmark_bar_node()->GetChild(0)->GetTitle()); 12795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(base::UTF8ToUTF16("Folder 1"), 12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_->bookmark_bar_node()->GetChild(1)->GetTitle()); 12815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(base::UTF8ToUTF16("local"), 12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_->bookmark_bar_node()->GetChild(1)->GetChild(0)->GetTitle()); 12832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopSync(); 12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify purging of delete journals. 12862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete journals for u2, f2, u1 remains because they are used in last 12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // association. 12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(3u, test_user_share_.GetDeleteJournalSize()); 12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSync(); 12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopSync(); 12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Reload again and all delete journals should be gone because none is used 12922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in last association. 12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(test_user_share_.Reload()); 12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0u, test_user_share_.GetDeleteJournalSize()); 12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 12962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestData { 12980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const char* title; 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* url; 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map from bookmark node ID to its version. 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<int64, int64> BookmarkNodeVersionMap; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(ncarter): Integrate the existing TestNode/PopulateNodeFromString code 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the bookmark model unittest, to make it simpler to set up test data 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// here (and reduce the amount of duplication among tests), and to reduce the 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// duplication. 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileSyncServiceBookmarkTestWithData 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public ProfileSyncServiceBookmarkTest { 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileSyncServiceBookmarkTestWithData(); 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populates or compares children of the given bookmark node from/with the 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given test data array with the given size. |running_count| is updated as 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // urls are added. It is used to set the creation date (or test the creation 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // date for CompareWithTestData()). 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PopulateFromTestData(const BookmarkNode* node, 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TestData* data, 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size, 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* running_count); 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CompareWithTestData(const BookmarkNode* node, 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TestData* data, 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size, 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* running_count); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectBookmarkModelMatchesTestData(); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WriteTestDataToBookmarkModel(); 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 133146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Output transaction versions of |node| and nodes under it to 133246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // |node_versions|. 133346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void GetTransactionVersions(const BookmarkNode* root, 133446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BookmarkNodeVersionMap* node_versions); 133546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify transaction versions of bookmark nodes and sync nodes are equal 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recursively. If node is in |version_expected|, versions should match 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there, too. 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ExpectTransactionVersionMatch( 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNodeVersionMap& version_expected); 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Time start_time_; 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceBookmarkTestWithData); 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constants for bookmark model that looks like: 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |-- Bookmark bar 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- u2, http://www.u2.com/ 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f1 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f1u4, http://www.f1u4.com/ 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f1u2, http://www.f1u2.com/ 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f1u3, http://www.f1u3.com/ 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | +-- f1u1, http://www.f1u1.com/ 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- u1, http://www.u1.com/ 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | +-- f2 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f2u2, http://www.f2u2.com/ 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f2u4, http://www.f2u4.com/ 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f2u3, http://www.f2u3.com/ 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | +-- f2u1, http://www.f2u1.com/ 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// +-- Other bookmarks 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f3 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f3u4, http://www.f3u4.com/ 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f3u2, http://www.f3u2.com/ 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f3u3, http://www.f3u3.com/ 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | +-- f3u1, http://www.f3u1.com/ 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- u4, http://www.u4.com/ 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- u3, http://www.u3.com/ 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | --- f4 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f4u1, http://www.f4u1.com/ 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f4u2, http://www.f4u2.com/ 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | |-- f4u3, http://www.f4u3.com/ 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | +-- f4u4, http://www.f4u4.com/ 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- dup 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | +-- dupu1, http://www.dupu1.com/ 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | +-- dup 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | +-- dupu2, http://www.dupu1.com/ 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | +-- ls , http://www.ls.com/ 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// +-- Mobile bookmarks 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |-- f5 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f5u1, http://www.f5u1.com/ 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |-- f6 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f6u1, http://www.f6u1.com/ 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | |-- f6u2, http://www.f6u2.com/ 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// +-- u5, http://www.u5.com/ 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kBookmarkBarChildren[] = { 13930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "u2", "http://www.u2.com/" }, 13940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f1", NULL }, 13950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "u1", "http://www.u1.com/" }, 13960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f2", NULL }, 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kF1Children[] = { 13990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f1u4", "http://www.f1u4.com/" }, 14000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f1u2", "http://www.f1u2.com/" }, 14010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f1u3", "http://www.f1u3.com/" }, 14020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f1u1", "http://www.f1u1.com/" }, 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kF2Children[] = { 14050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f2u2", "http://www.f2u2.com/" }, 14060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f2u4", "http://www.f2u4.com/" }, 14070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f2u3", "http://www.f2u3.com/" }, 14080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f2u1", "http://www.f2u1.com/" }, 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kOtherBookmarkChildren[] = { 14120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f3", NULL }, 14130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "u4", "http://www.u4.com/" }, 14140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "u3", "http://www.u3.com/" }, 14150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f4", NULL }, 14160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "dup", NULL }, 14170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "dup", NULL }, 14180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { " ls ", "http://www.ls.com/" } 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kF3Children[] = { 14210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f3u4", "http://www.f3u4.com/" }, 14220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f3u2", "http://www.f3u2.com/" }, 14230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f3u3", "http://www.f3u3.com/" }, 14240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f3u1", "http://www.f3u1.com/" }, 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kF4Children[] = { 14270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f4u1", "http://www.f4u1.com/" }, 14280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f4u2", "http://www.f4u2.com/" }, 14290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f4u3", "http://www.f4u3.com/" }, 14300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f4u4", "http://www.f4u4.com/" }, 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kDup1Children[] = { 14330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "dupu1", "http://www.dupu1.com/" }, 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kDup2Children[] = { 14360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "dupu2", "http://www.dupu2.com/" }, 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kMobileBookmarkChildren[] = { 14400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f5", NULL }, 14410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f6", NULL }, 14420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "u5", "http://www.u5.com/" }, 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kF5Children[] = { 14450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f5u1", "http://www.f5u1.com/" }, 14460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f5u2", "http://www.f5u2.com/" }, 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TestData kF6Children[] = { 14490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f6u1", "http://www.f6u1.com/" }, 14500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { "f6u2", "http://www.f6u2.com/" }, 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // anonymous namespace. 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileSyncServiceBookmarkTestWithData:: 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileSyncServiceBookmarkTestWithData() 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : start_time_(base::Time::Now()) { 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceBookmarkTestWithData::PopulateFromTestData( 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TestData* data, 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size, 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* running_count) { 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node); 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node->is_folder()); 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < size; ++i) { 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TestData& item = data[i]; 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item.url) { 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Time add_time = 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time_ + base::TimeDelta::FromMinutes(*running_count); 14730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model_->AddURLWithCreationTimeAndMetaInfo(node, 14740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i, 14750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::UTF8ToUTF16(item.title), 14760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GURL(item.url), 14770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch add_time, 14780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NULL); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model_->AddFolder(node, i, base::UTF8ToUTF16(item.title)); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*running_count)++; 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceBookmarkTestWithData::CompareWithTestData( 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TestData* data, 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size, 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* running_count) { 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node->is_folder()); 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(size, node->child_count()); 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < size; ++i) { 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* child_node = node->GetChild(i); 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TestData& item = data[i]; 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = GURL(item.url == NULL ? "" : item.url); 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode test_node(url); 15000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch test_node.SetTitle(base::UTF8ToUTF16(item.title)); 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(child_node->GetTitle(), test_node.GetTitle()); 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item.url) { 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(child_node->is_folder()); 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(child_node->is_url()); 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(child_node->url(), test_node.url()); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Time expected_time = 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time_ + base::TimeDelta::FromMinutes(*running_count); 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_time.ToInternalValue(), 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_node->date_added().ToInternalValue()); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(child_node->is_folder()); 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(child_node->is_url()); 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*running_count)++; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(munjal): We should implement some way of generating random data and can 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use the same seed to generate the same sequence. 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceBookmarkTestWithData::WriteTestDataToBookmarkModel() { 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmarks_bar_node = model_->bookmark_bar_node(); 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(bookmarks_bar_node, 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBookmarkBarChildren, 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kBookmarkBarChildren), 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(bookmarks_bar_node->child_count(), 4); 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f1_node = bookmarks_bar_node->GetChild(1); 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(f1_node, kF1Children, arraysize(kF1Children), &count); 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f2_node = bookmarks_bar_node->GetChild(3); 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(f2_node, kF2Children, arraysize(kF2Children), &count); 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* other_bookmarks_node = model_->other_node(); 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(other_bookmarks_node, 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kOtherBookmarkChildren, 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kOtherBookmarkChildren), 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(other_bookmarks_node->child_count(), 6); 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f3_node = other_bookmarks_node->GetChild(0); 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(f3_node, kF3Children, arraysize(kF3Children), &count); 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f4_node = other_bookmarks_node->GetChild(3); 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(f4_node, kF4Children, arraysize(kF4Children), &count); 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* dup_node = other_bookmarks_node->GetChild(4); 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(dup_node, kDup1Children, arraysize(kDup1Children), 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dup_node = other_bookmarks_node->GetChild(5); 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(dup_node, kDup2Children, arraysize(kDup2Children), 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* mobile_bookmarks_node = model_->mobile_node(); 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(mobile_bookmarks_node, 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMobileBookmarkChildren, 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kMobileBookmarkChildren), 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(mobile_bookmarks_node->child_count(), 3); 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f5_node = mobile_bookmarks_node->GetChild(0); 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(f5_node, kF5Children, arraysize(kF5Children), &count); 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f6_node = mobile_bookmarks_node->GetChild(1); 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PopulateFromTestData(f6_node, kF6Children, arraysize(kF6Children), &count); 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceBookmarkTestWithData:: 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData() { 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmark_bar_node = model_->bookmark_bar_node(); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(bookmark_bar_node, 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBookmarkBarChildren, 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kBookmarkBarChildren), 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(bookmark_bar_node->child_count(), 4); 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f1_node = bookmark_bar_node->GetChild(1); 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(f1_node, kF1Children, arraysize(kF1Children), &count); 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f2_node = bookmark_bar_node->GetChild(3); 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(f2_node, kF2Children, arraysize(kF2Children), &count); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* other_bookmarks_node = model_->other_node(); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(other_bookmarks_node, 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kOtherBookmarkChildren, 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kOtherBookmarkChildren), 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(other_bookmarks_node->child_count(), 6); 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f3_node = other_bookmarks_node->GetChild(0); 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(f3_node, kF3Children, arraysize(kF3Children), &count); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f4_node = other_bookmarks_node->GetChild(3); 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(f4_node, kF4Children, arraysize(kF4Children), &count); 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* dup_node = other_bookmarks_node->GetChild(4); 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(dup_node, kDup1Children, arraysize(kDup1Children), 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dup_node = other_bookmarks_node->GetChild(5); 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(dup_node, kDup2Children, arraysize(kDup2Children), 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* mobile_bookmarks_node = model_->mobile_node(); 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(mobile_bookmarks_node, 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMobileBookmarkChildren, 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kMobileBookmarkChildren), 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(mobile_bookmarks_node->child_count(), 3); 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f5_node = mobile_bookmarks_node->GetChild(0); 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(f5_node, kF5Children, arraysize(kF5Children), &count); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f6_node = mobile_bookmarks_node->GetChild(1); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareWithTestData(f6_node, kF6Children, arraysize(kF6Children), &count); 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests persistence of the profile sync service by unloading the 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// database and then reloading it from disk. 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, Persistence) { 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force both models to discard their data and reload from disk. This 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // simulates what would happen if the browser were to shutdown normally, 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then relaunch. 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadBookmarkModel(); 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // With the BookmarkModel contents verified, ExpectModelMatch will 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // verify the contents of the sync model. 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the merge case when the BookmarkModel is non-empty but the 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync model is empty. This corresponds to uploading browser 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bookmarks to an initially empty, new account. 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, MergeWithEmptySyncModel) { 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't start the sync service until we've populated the bookmark model. 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restart sync. This should trigger a merge step during 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initialization -- we expect the browser bookmarks to be written 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the sync service during this call. 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the bookmark model hasn't changed, and that the sync model 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // matches it exactly. 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the merge case when the BookmarkModel is empty but the sync model is 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-empty. This corresponds (somewhat) to a clean install of the browser, 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with no bookmarks, connecting to a sync account that has some bookmarks. 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, MergeWithEmptyBookmarkModel) { 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force the databse to unload and write itself to disk. 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Blow away the bookmark model -- it should be empty afterwards. 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadBookmarkModel(); 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(model_->bookmark_bar_node()->child_count(), 0); 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(model_->other_node()->child_count(), 0); 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(model_->mobile_node()->child_count(), 0); 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now restart the sync service. Starting it should populate the bookmark 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // model -- test for consistency. 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the merge cases when both the models are expected to be identical 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after the merge. 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, MergeExpectedIdenticalModels) { 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadBookmarkModel(); 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At this point both the bookmark model and the server should have the 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exact same data and it should match the test data. 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadBookmarkModel(); 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now reorder some bookmarks in the bookmark model and then merge. Make 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sure we get the order of the server after merge. 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE); 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmark_bar = model_->bookmark_bar_node(); 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(bookmark_bar); 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(bookmark_bar->child_count(), 1); 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(bookmark_bar->GetChild(0), bookmark_bar, 1); 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the merge cases when both the models are expected to be identical 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after the merge. 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, MergeModelsWithSomeExtras) { 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove some nodes and reorder some nodes. 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmark_bar_node = model_->bookmark_bar_node(); 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remove_index = 2; 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* child_node = bookmark_bar_node->GetChild(remove_index); 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node); 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node->is_url()); 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(bookmark_bar_node, remove_index); 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_node = bookmark_bar_node->GetChild(remove_index); 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node); 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node->is_folder()); 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(bookmark_bar_node, remove_index); 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* other_node = model_->other_node(); 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(other_node->child_count(), 1); 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* f3_node = other_node->GetChild(0); 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(f3_node); 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(f3_node->is_folder()); 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove_index = 2; 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(f3_node->child_count(), remove_index); 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(f3_node, remove_index); 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(f3_node->child_count(), remove_index); 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(f3_node, remove_index); 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove some nodes and reorder some nodes. 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_bar_node = model_->bookmark_bar_node(); 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove_index = 0; 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_node = bookmark_bar_node->GetChild(remove_index); 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node); 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node->is_url()); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(bookmark_bar_node, remove_index); 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_node = bookmark_bar_node->GetChild(remove_index); 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node); 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node->is_folder()); 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(bookmark_bar_node, remove_index); 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(bookmark_bar_node->child_count(), 2); 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(bookmark_bar_node->GetChild(0), bookmark_bar_node, 1); 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_node = model_->other_node(); 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(other_node->child_count(), 1); 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f3_node = other_node->GetChild(0); 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(f3_node); 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(f3_node->is_folder()); 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove_index = 0; 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(f3_node->child_count(), remove_index); 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(f3_node, remove_index); 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(f3_node->child_count(), remove_index); 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(f3_node, remove_index); 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GE(other_node->child_count(), 4); 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(other_node->GetChild(0), other_node, 1); 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(other_node->GetChild(2), other_node, 3); 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After the merge, the model should match the test data. 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that when persisted model associations are used, things work fine. 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, ModelAssociationPersistence) { 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force sync to shut down and write itself to disk. 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now restart sync. This time it should use the persistent 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // associations. 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that when persisted model associations are used, things work fine. 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelAssociationInvalidPersistence) { 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force sync to shut down and write itself to disk. 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the bookmark model before restarting sync service to simulate 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the situation where bookmark model is different from sync model and 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make sure model associator correctly rebuilds associations. 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmark_bar_node = model_->bookmark_bar_node(); 18245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddURL(bookmark_bar_node, 0, base::ASCIIToUTF16("xtra"), 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://www.xtra.com")); 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now restart sync. This time it will try to use the persistent 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // associations and realize that they are invalid and hence will rebuild 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // associations. 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, SortChildren) { 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write test data to bookmark model and verify that the models match. 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* folder_added = model_->other_node()->GetChild(0); 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(folder_added); 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(folder_added->is_folder()); 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Sort the other-bookmarks children and expect that the models match. 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SortChildren(folder_added); 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See what happens if we enable sync but then delete the "Sync Data" 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// folder. 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecoverAfterDeletingSyncDataDirectory) { 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nuke the sync DB and reload. 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TearDown(); 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUp(); 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // First attempt fails due to a persistence error. 1866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(CreatePermanentBookmarkNodes()); 1867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(AssociateModels()); 1868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Second attempt succeeds due to the previous error resetting the native 1870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // transaction version. 1871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch model_associator_.reset(); 1872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(CreatePermanentBookmarkNodes()); 1873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(AssociateModels()); 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we're back in sync. In real life, the user would need 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to reauthenticate before this happens, but in the test, authentication 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is sidestepped. 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that the bookmark model is updated about whether the 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// associator is currently running. 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, AssociationState) { 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensiveChangesBookmarkModelObserver observer; 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(&observer); 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer.get_started()); 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer.get_completed_count_at_started()); 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer.get_completed()); 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(&observer); 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that the creation_time_us changes are applied in the local model at 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// association time and update time. 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateDateAdded) { 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start and stop sync in order to create bookmark nodes in the sync db. 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSync(); 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Modify the date_added field of a bookmark so it doesn't match with 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the sync data. 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmark_bar_node = model_->bookmark_bar_node(); 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remove_index = 2; 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* child_node = bookmark_bar_node->GetChild(remove_index); 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(child_node); 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(child_node->is_url()); 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetDateAdded(child_node, base::Time::FromInternalValue(10)); 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Everything should be back in sync after model association. 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectModelMatch(); 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now trigger a change while syncing. We add a new bookmark, sync it, then 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // updates it's creation time. 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange adds(&trans); 19290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string kTitle = "Some site"; 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string kUrl = "http://www.whatwhat.yeah/"; 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kCreationTime = 30; 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id = adds.AddURL(kTitle, kUrl, 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_bar_id(), 0); 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeServerChange updates(&trans); 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updates.ModifyCreationTime(id, kCreationTime); 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updates.ApplyPendingChanges(change_processor_.get()); 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(0); 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(node); 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(node->is_url()); 19420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(base::UTF8ToUTF16(kTitle), node->GetTitle()); 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kUrl, node->url().possibly_invalid_spec()); 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(node->date_added(), base::Time::FromInternalValue(30)); 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1947a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Tests that changes to the sync nodes meta info gets reflected in the local 1948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// bookmark model. 1949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateMetaInfoFromSync) { 1950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WriteTestDataToBookmarkModel(); 1952a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) StartSync(); 1953a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create bookmark nodes containing meta info. 1955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); 1956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FakeServerChange adds(&trans); 1957a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BookmarkNode::MetaInfoMap folder_meta_info; 1958a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) folder_meta_info["folder"] = "foldervalue"; 1959a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 folder_id = adds.AddFolderWithMetaInfo( 19600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch "folder title", &folder_meta_info, bookmark_bar_id(), 0); 1961a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BookmarkNode::MetaInfoMap node_meta_info; 1962a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node_meta_info["node"] = "nodevalue"; 1963a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node_meta_info["other"] = "othervalue"; 19640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 id = adds.AddURLWithMetaInfo("node title", "http://www.foo.com", 1965a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &node_meta_info, folder_id, 0); 1966a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) adds.ApplyPendingChanges(change_processor_.get()); 1967a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1968a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Verify that the nodes are created with the correct meta info. 1969a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_LT(0, model_->bookmark_bar_node()->child_count()); 1970a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode* folder_node = model_->bookmark_bar_node()->GetChild(0); 1971a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(folder_node->GetMetaInfoMap()); 1972a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(folder_meta_info, *folder_node->GetMetaInfoMap()); 1973a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_LT(0, folder_node->child_count()); 1974a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode* node = folder_node->GetChild(0); 1975a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(node->GetMetaInfoMap()); 1976a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(node_meta_info, *node->GetMetaInfoMap()); 1977a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1978a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Update meta info on nodes on server 1979a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FakeServerChange updates(&trans); 1980a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) folder_meta_info.erase("folder"); 1981a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) updates.ModifyMetaInfo(folder_id, folder_meta_info); 1982a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node_meta_info["node"] = "changednodevalue"; 1983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node_meta_info.erase("other"); 1984a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node_meta_info["newkey"] = "newkeyvalue"; 1985a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) updates.ModifyMetaInfo(id, node_meta_info); 1986a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) updates.ApplyPendingChanges(change_processor_.get()); 1987a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1988a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Confirm that the updated values are reflected in the bookmark nodes. 1989a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(folder_node->GetMetaInfoMap()); 1990a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(node->GetMetaInfoMap()); 1991a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(node_meta_info, *node->GetMetaInfoMap()); 1992a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1993a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1994a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Tests that changes to the local bookmark nodes meta info gets reflected in 1995a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// the sync nodes. 1996a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateMetaInfoFromModel) { 1997a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1998a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WriteTestDataToBookmarkModel(); 1999a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) StartSync(); 2000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ExpectBookmarkModelMatchesTestData(); 2001a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2002a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode* folder_node = 2003a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->AddFolder(model_->bookmark_bar_node(), 0, 20045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ASCIIToUTF16("folder title")); 2005a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const BookmarkNode* node = model_->AddURL(folder_node, 0, 20065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ASCIIToUTF16("node title"), 2007a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GURL("http://www.foo.com")); 2008a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ExpectModelMatch(); 2009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Add some meta info and verify sync model matches the changes. 2011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->SetNodeMetaInfo(folder_node, "folder", "foldervalue"); 2012a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->SetNodeMetaInfo(node, "node", "nodevalue"); 2013a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->SetNodeMetaInfo(node, "other", "othervalue"); 2014a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ExpectModelMatch(); 2015a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Change/delete existing meta info and verify. 2017a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->DeleteNodeMetaInfo(folder_node, "folder"); 2018a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->SetNodeMetaInfo(node, "node", "changednodevalue"); 2019a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->DeleteNodeMetaInfo(node, "other"); 2020a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model_->SetNodeMetaInfo(node, "newkey", "newkeyvalue"); 2021a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ExpectModelMatch(); 2022a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 2023a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 202446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ProfileSyncServiceBookmarkTestWithData::GetTransactionVersions( 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* root, 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap* node_versions) { 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node_versions->clear(); 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<const BookmarkNode*> nodes; 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.push(root); 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!nodes.empty()) { 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* n = nodes.front(); 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.pop(); 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2034f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 version = n->sync_transaction_version(); 2035f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_NE(BookmarkNode::kInvalidSyncTransactionVersion, version); 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*node_versions)[n->id()] = version; 203846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (int i = 0; i < n->child_count(); ++i) { 2039116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!CanSyncNode(n->GetChild(i))) 204046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.push(n->GetChild(i)); 204246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceBookmarkTestWithData::ExpectTransactionVersionMatch( 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNodeVersionMap& version_expected) { 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap bnodes_versions; 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTransactionVersions(node, &bnodes_versions); 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BookmarkNodeVersionMap::const_iterator it = bnodes_versions.begin(); 20542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != bnodes_versions.end(); ++it) { 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadNode sync_node(&trans); 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(model_associator_->InitSyncNodeFromChromeId(it->first, 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sync_node)); 2058d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_EQ(sync_node.GetEntry()->GetTransactionVersion(), it->second); 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap::const_iterator expected_ver_it = 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_expected.find(it->first); 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected_ver_it != version_expected.end()) 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_ver_it->second, it->second); 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test transaction versions of model and nodes are incremented after changes 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are applied. 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateTransactionVersion) { 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSync(); 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTestDataToBookmarkModel(); 207290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap initial_versions; 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify transaction versions in sync model and bookmark model (saved as 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction version of root node) are equal after 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WriteTestDataToBookmarkModel() created bookmarks. 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(trans.GetModelVersion(syncer::BOOKMARKS), 0); 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTransactionVersions(model_->root_node(), &initial_versions); 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(trans.GetModelVersion(syncer::BOOKMARKS), 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_versions[model_->root_node()->id()]); 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->bookmark_bar_node(), 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap()); 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->other_node(), 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap()); 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->mobile_node(), 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap()); 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify model version is incremented and bookmark node versions remain 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same. 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* bookmark_bar = model_->bookmark_bar_node(); 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Remove(bookmark_bar, 0); 209790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeVersionMap new_versions; 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTransactionVersions(model_->root_node(), &new_versions); 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(initial_versions[model_->root_node()->id()] + 1, 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_versions[model_->root_node()->id()]); 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->bookmark_bar_node(), initial_versions); 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->other_node(), initial_versions); 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions); 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify model version and version of changed bookmark are incremented and 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // versions of others remain same. 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* changed_bookmark = 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->bookmark_bar_node()->GetChild(0); 21105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->SetTitle(changed_bookmark, base::ASCIIToUTF16("test")); 211190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTransactionVersions(model_->root_node(), &new_versions); 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(initial_versions[model_->root_node()->id()] + 2, 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_versions[model_->root_node()->id()]); 2115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_LT(initial_versions[changed_bookmark->id()], 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_versions[changed_bookmark->id()]); 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_versions.erase(changed_bookmark->id()); 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->bookmark_bar_node(), initial_versions); 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->other_node(), initial_versions); 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpectTransactionVersionMatch(model_->mobile_node(), initial_versions); 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that sync persistence errors are detected and trigger a failed 2124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// association. 2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(ProfileSyncServiceBookmarkTestWithData, PersistenceError) { 2126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 2127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StartSync(); 2128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WriteTestDataToBookmarkModel(); 2129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoop::current()->RunUntilIdle(); 2130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BookmarkNodeVersionMap initial_versions; 2132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Verify transaction versions in sync model and bookmark model (saved as 2134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // transaction version of root node) are equal after 2135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // WriteTestDataToBookmarkModel() created bookmarks. 2136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch { 2137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); 2138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_GT(trans.GetModelVersion(syncer::BOOKMARKS), 0); 2139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetTransactionVersions(model_->root_node(), &initial_versions); 2140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(trans.GetModelVersion(syncer::BOOKMARKS), 2141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch initial_versions[model_->root_node()->id()]); 2142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ExpectTransactionVersionMatch(model_->bookmark_bar_node(), 2144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BookmarkNodeVersionMap()); 2145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ExpectTransactionVersionMatch(model_->other_node(), 2146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BookmarkNodeVersionMap()); 2147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ExpectTransactionVersionMatch(model_->mobile_node(), 2148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BookmarkNodeVersionMap()); 2149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Now shut down sync and artificially increment the native model's version. 2151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StopSync(); 2152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64 root_version = initial_versions[model_->root_node()->id()]; 2153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model_->SetNodeSyncTransactionVersion(model_->root_node(), root_version + 1); 2154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Upon association, bookmarks should fail to associate. 2156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(AssociateModels()); 2157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// It's possible for update/add calls from the bookmark model to be out of 2160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// order, or asynchronous. Handle that without triggering an error. 2161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(ProfileSyncServiceBookmarkTest, UpdateThenAdd) { 2162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 2163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StartSync(); 2164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(other_bookmarks_id()); 2166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(bookmark_bar_id()); 2167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(mobile_bookmarks_id()); 2168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExpectModelMatch(); 2170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Now destroy the change processor then add a bookmark, to simulate 2172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // missing the Update call. 2173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) change_processor_.reset(); 2174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const BookmarkNode* node = model_->AddURL(model_->bookmark_bar_node(), 2175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 0, 2176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ASCIIToUTF16("title"), 2177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GURL("http://www.url.com")); 2178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Recreate the change processor then update that bookmark. Sync should 2180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // receive the update call and gracefully treat that as if it were an add. 2181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) change_processor_.reset(new BookmarkChangeProcessor( 2182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &profile_, model_associator_.get(), &mock_error_handler_)); 2183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) change_processor_->Start(test_user_share_.user_share()); 2184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) model_->SetTitle(node, base::ASCIIToUTF16("title2")); 2185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExpectModelMatch(); 2186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Then simulate the add call arriving late. 2188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) change_processor_->BookmarkNodeAdded(model_, model_->bookmark_bar_node(), 0); 2189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExpectModelMatch(); 2190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 2191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace browser_sync 2195