1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(akalin): This file is basically just a unit test for 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// BookmarkChangeProcessor. Write unit tests for 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// BookmarkModelAssociator separately. 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <stack> 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <vector> 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_path.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_util.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/message_loop.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string16.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_number_conversions.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/utf_string_conversions.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/bookmarks/bookmark_model.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/abstract_profile_sync_service_test.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/syncapi.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/glue/bookmark_change_processor.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/glue/bookmark_model_associator.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/syncable/directory_manager.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/test/sync/engine/test_id_factory.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/test/sync/engine/test_user_share.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/test/testing_profile.h" 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h" 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "testing/gmock/include/gmock/gmock.h" 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "testing/gtest/include/gtest/gtest.h" 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace browser_sync { 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing testing::_; 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing testing::InvokeWithoutArgs; 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing testing::Mock; 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing testing::StrictMock; 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass TestBookmarkModelAssociator : public BookmarkModelAssociator { 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBookmarkModelAssociator( 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BookmarkModel* bookmark_model, 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::UserShare* user_share, 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnrecoverableErrorHandler* unrecoverable_error_handler) 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : BookmarkModelAssociator(bookmark_model, user_share, 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unrecoverable_error_handler), 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_share_(user_share) {} 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(akalin): This logic lazily creates any tagged node that is 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // requested. A better way would be to have utility functions to 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // create sync nodes from some bookmark structure and to use that. 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id) { 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring tag_wide; 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!UTF8ToWide(tag.c_str(), tag.length(), &tag_wide)) { 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED() << "Unable to convert UTF8 to wide for string: " << tag; 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool root_exists = false; 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelType type = model_type(); 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(user_share_); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode uber_root(&trans); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen uber_root.InitByRootLookup(); 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode root(&trans); 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen root_exists = root.InitByTagLookup( 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileSyncServiceTestHelper::GetTagForType(type)); 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!root_exists) { 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool created = ProfileSyncServiceTestHelper::CreateRoot( 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen type, 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_share_, 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &id_factory_); 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!created) 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(user_share_); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode root(&trans); 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(root.InitByTagLookup( 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileSyncServiceTestHelper::GetTagForType(type))); 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // First, try to find a node with the title among the root's children. 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This will be the case if we are testing model persistence, and 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // are reloading a sync repository created earlier in the test. 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 last_child_id = sync_api::kInvalidId; 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int64 id = root.GetFirstChildId(); id != sync_api::kInvalidId; /***/) { 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode child(&trans); 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child.InitByIdLookup(id); 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen last_child_id = id; 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tag_wide == child.GetTitle()) { 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *sync_id = id; 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen id = child.GetSuccessorId(); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode predecessor_node(&trans); 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode* predecessor = NULL; 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (last_child_id != sync_api::kInvalidId) { 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen predecessor_node.InitByIdLookup(last_child_id); 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen predecessor = &predecessor_node; 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode node(&trans); 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create new fake tagged nodes at the end of the ordering. 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.InitByCreation(type, root, predecessor); 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetIsFolder(true); 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetTitle(tag_wide); 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetExternalId(0); 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *sync_id = node.GetId(); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::UserShare* user_share_; 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::TestIdFactory id_factory_; 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// FakeServerChange constructs a list of sync_api::ChangeRecords while modifying 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// the sync model, and can pass the ChangeRecord list to a 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// sync_api::SyncObserver (i.e., the ProfileSyncService) to test the client 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// change-application behavior. 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests using FakeServerChange should be careful to avoid back-references, 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// since FakeServerChange will send the edits in the order specified. 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass FakeServerChange { 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit FakeServerChange(sync_api::WriteTransaction* trans) : trans_(trans) { 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Pretend that the server told the syncer to add a bookmark object. 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 Add(const std::wstring& title, 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& url, 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool is_folder, 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 parent_id, 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 predecessor_id) { 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode parent(trans_); 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(parent.InitByIdLookup(parent_id)); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode node(trans_); 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (predecessor_id == 0) { 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.InitByCreation(syncable::BOOKMARKS, parent, NULL)); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode predecessor(trans_); 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(predecessor.InitByIdLookup(predecessor_id)); 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(predecessor.GetParentId(), parent.GetId()); 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.InitByCreation(syncable::BOOKMARKS, parent, 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &predecessor)); 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(node.GetPredecessorId(), predecessor_id); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(node.GetParentId(), parent_id); 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetIsFolder(is_folder); 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetTitle(title); 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!is_folder) 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetURL(GURL(url)); 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::SyncManager::ChangeRecord record; 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record.action = sync_api::SyncManager::ChangeRecord::ACTION_ADD; 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record.id = node.GetId(); 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen changes_.push_back(record); 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return node.GetId(); 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add a bookmark folder. 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 AddFolder(const std::wstring& title, 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 parent_id, 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 predecessor_id) { 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return Add(title, std::string(), true, parent_id, predecessor_id); 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add a bookmark. 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 AddURL(const std::wstring& title, 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& url, 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 parent_id, 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 predecessor_id) { 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return Add(title, url, false, parent_id, predecessor_id); 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Pretend that the server told the syncer to delete an object. 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void Delete(int64 id) { 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Delete the sync node. 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode node(trans_); 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.InitByIdLookup(id)); 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(node.GetFirstChildId()); 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.Remove(); 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Verify the deletion. 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode node(trans_); 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(node.InitByIdLookup(id)); 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::SyncManager::ChangeRecord record; 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record.action = sync_api::SyncManager::ChangeRecord::ACTION_DELETE; 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record.id = id; 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Deletions are always first in the changelist, but we can't actually do 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // WriteNode::Remove() on the node until its children are moved. So, as 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a practical matter, users of FakeServerChange must move or delete 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // children before parents. Thus, we must insert the deletion record 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // at the front of the vector. 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen changes_.insert(changes_.begin(), record); 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set a new title value, and return the old value. 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring ModifyTitle(int64 id, const std::wstring& new_title) { 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode node(trans_); 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.InitByIdLookup(id)); 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring old_title = node.GetTitle(); 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.SetTitle(new_title); 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetModified(id); 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return old_title; 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set a new parent and predecessor value. Return the old parent id. 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We could return the old predecessor id, but it turns out not to be 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // very useful for assertions. 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 ModifyPosition(int64 id, int64 parent_id, int64 predecessor_id) { 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode parent(trans_); 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(parent.InitByIdLookup(parent_id)); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode node(trans_); 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.InitByIdLookup(id)); 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 old_parent_id = node.GetParentId(); 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (predecessor_id == 0) { 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.SetPosition(parent, NULL)); 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode predecessor(trans_); 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(predecessor.InitByIdLookup(predecessor_id)); 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(predecessor.GetParentId(), parent.GetId()); 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(node.SetPosition(parent, &predecessor)); 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetModified(id); 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return old_parent_id; 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Pass the fake change list to |service|. 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ApplyPendingChanges(ChangeProcessor* processor) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen processor->ApplyChangesFromSyncModel(trans_, 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen changes_.size() ? &changes_[0] : NULL, changes_.size()); 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<sync_api::SyncManager::ChangeRecord>& changes() { 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return changes_; 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Helper function to push an ACTION_UPDATE record onto the back 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // of the changelist. 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void SetModified(int64 id) { 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Coalesce multi-property edits. 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!changes_.empty() && changes_.back().id == id && 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen changes_.back().action == 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::SyncManager::ChangeRecord::ACTION_UPDATE) 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::SyncManager::ChangeRecord record; 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record.action = sync_api::SyncManager::ChangeRecord::ACTION_UPDATE; 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record.id = id; 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen changes_.push_back(record); 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The transaction on which everything happens. 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction *trans_; 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The change list we construct. 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<sync_api::SyncManager::ChangeRecord> changes_; 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass MockUnrecoverableErrorHandler : public UnrecoverableErrorHandler { 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD2(OnUnrecoverableError, 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void(const tracked_objects::Location&, const std::string&)); 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass ProfileSyncServiceBookmarkTest : public testing::Test { 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen protected: 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enum LoadOption { LOAD_FROM_STORAGE, DELETE_EXISTING_STORAGE }; 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enum SaveOption { SAVE_TO_STORAGE, DONT_SAVE_TO_STORAGE }; 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileSyncServiceBookmarkTest() 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : ui_thread_(BrowserThread::UI, &message_loop_), 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_thread_(BrowserThread::FILE, &message_loop_), 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_(NULL) { 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual ~ProfileSyncServiceBookmarkTest() { 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnloadBookmarkModel(); 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void SetUp() { 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen test_user_share_.SetUp(); 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void TearDown() { 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen test_user_share_.TearDown(); 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Load (or re-load) the bookmark model. |load| controls use of the 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // bookmarks file on disk. |save| controls whether the newly loaded 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // bookmark model will write out a bookmark file as it goes. 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void LoadBookmarkModel(LoadOption load, SaveOption save) { 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool delete_bookmarks = load == DELETE_EXISTING_STORAGE; 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_.CreateBookmarkModel(delete_bookmarks); 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_ = profile_.GetBookmarkModel(); 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Wait for the bookmarks model to load. 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_.BlockUntilBookmarkModelLoaded(); 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This noticeably speeds up the unit tests that request it. 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (save == DONT_SAVE_TO_STORAGE) 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->ClearStore(); 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen message_loop_.RunAllPending(); 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void StartSync() { 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set up model associator. 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_.reset(new TestBookmarkModelAssociator( 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_.GetBookmarkModel(), 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen test_user_share_.user_share(), 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &mock_unrecoverable_error_handler_)); 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(model_associator_->AssociateModels()); 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoop::current()->RunAllPending(); 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set up change processor. 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen change_processor_.reset( 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new BookmarkChangeProcessor(model_associator_.get(), 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &mock_unrecoverable_error_handler_)); 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen change_processor_->Start(&profile_, test_user_share_.user_share()); 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void StopSync() { 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen change_processor_->Stop(); 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen change_processor_.reset(); 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(model_associator_->DisassociateModels()); 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_.reset(); 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen message_loop_.RunAllPending(); 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(akalin): Actually close the database and flush it to disk 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // (and make StartSync reload from disk). This would require 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // refactoring TestUserShare. 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void UnloadBookmarkModel() { 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_.CreateBookmarkModel(false /* delete_bookmarks */); 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_ = NULL; 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen message_loop_.RunAllPending(); 349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool InitSyncNodeFromChromeNode(const BookmarkNode* bnode, 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::BaseNode* sync_node) { 353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return model_associator_->InitSyncNodeFromChromeId(bnode->id(), 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_node); 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectSyncerNodeMatching(sync_api::BaseTransaction* trans, 358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bnode) { 359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode gnode(trans); 360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(InitSyncNodeFromChromeNode(bnode, &gnode)); 361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Non-root node titles and parents must match. 362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (bnode != model_->GetBookmarkBarNode() && 363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bnode != model_->other_node()) { 364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(bnode->GetTitle(), WideToUTF16Hack(gnode.GetTitle())); 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ( 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetChromeNodeFromSyncId(gnode.GetParentId()), 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bnode->parent()); 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(bnode->is_folder(), gnode.GetIsFolder()); 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (bnode->is_url()) 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(bnode->GetURL(), gnode.GetURL()); 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check for position matches. 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int browser_index = bnode->parent()->GetIndexOf(bnode); 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (browser_index == 0) { 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(gnode.GetPredecessorId(), 0); 377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bprev = 379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bnode->parent()->GetChild(browser_index - 1); 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode gprev(trans); 381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(InitSyncNodeFromChromeNode(bprev, &gprev)); 382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(gnode.GetPredecessorId(), gprev.GetId()); 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(gnode.GetParentId(), gprev.GetParentId()); 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (browser_index == bnode->parent()->child_count() - 1) { 386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(gnode.GetSuccessorId(), 0); 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bnext = 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bnode->parent()->GetChild(browser_index + 1); 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode gnext(trans); 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(InitSyncNodeFromChromeNode(bnext, &gnext)); 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(gnode.GetSuccessorId(), gnext.GetId()); 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(gnode.GetParentId(), gnext.GetParentId()); 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (bnode->child_count()) { 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(gnode.GetFirstChildId()); 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectSyncerNodeMatching(const BookmarkNode* bnode) { 401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadTransaction trans(test_user_share_.user_share()); 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(&trans, bnode); 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBrowserNodeMatching(sync_api::BaseTransaction* trans, 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 sync_id) { 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(sync_id); 408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bnode = 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetChromeNodeFromSyncId(sync_id); 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(bnode); 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 id = model_associator_->GetSyncIdFromChromeId(bnode->id()); 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(id, sync_id); 413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(trans, bnode); 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBrowserNodeUnknown(int64 sync_id) { 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(model_associator_->GetChromeNodeFromSyncId(sync_id)); 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBrowserNodeKnown(int64 sync_id) { 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(model_associator_->GetChromeNodeFromSyncId(sync_id)); 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectSyncerNodeKnown(const BookmarkNode* node) { 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 sync_id = model_associator_->GetSyncIdFromChromeId(node->id()); 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_NE(sync_id, sync_api::kInvalidId); 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectSyncerNodeUnknown(const BookmarkNode* node) { 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 sync_id = model_associator_->GetSyncIdFromChromeId(node->id()); 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(sync_id, sync_api::kInvalidId); 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBrowserNodeTitle(int64 sync_id, const std::wstring& title) { 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bnode = 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetChromeNodeFromSyncId(sync_id); 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(bnode); 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(bnode->GetTitle(), WideToUTF16Hack(title)); 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBrowserNodeURL(int64 sync_id, const std::string& url) { 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bnode = 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetChromeNodeFromSyncId(sync_id); 444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(bnode); 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(GURL(url), bnode->GetURL()); 446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBrowserNodeParent(int64 sync_id, int64 parent_sync_id) { 449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* node = 450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetChromeNodeFromSyncId(sync_id); 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(node); 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* parent = 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetChromeNodeFromSyncId(parent_sync_id); 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(parent); 455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(node->parent(), parent); 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectModelMatch(sync_api::BaseTransaction* trans) { 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* root = model_->root_node(); 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(root->GetIndexOf(model_->GetBookmarkBarNode()), 0); 461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(root->GetIndexOf(model_->other_node()), 1); 462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::stack<int64> stack; 464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen stack.push(bookmark_bar_id()); 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (!stack.empty()) { 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 id = stack.top(); 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen stack.pop(); 468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!id) continue; 469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeMatching(trans, id); 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode gnode(trans); 473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(gnode.InitByIdLookup(id)); 474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen stack.push(gnode.GetFirstChildId()); 475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen stack.push(gnode.GetSuccessorId()); 476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectModelMatch() { 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadTransaction trans(test_user_share_.user_share()); 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 other_bookmarks_id() { 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->GetSyncIdFromChromeId(model_->other_node()->id()); 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 bookmark_bar_id() { 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return model_associator_->GetSyncIdFromChromeId( 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->GetBookmarkBarNode()->id()); 492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Used by both |ui_thread_| and |file_thread_|. 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoop message_loop_; 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread ui_thread_; 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Needed by |model_|. 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread file_thread_; 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestingProfile profile_; 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<TestBookmarkModelAssociator> model_associator_; 503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen protected: 505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BookmarkModel* model_; 506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestUserShare test_user_share_; 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<BookmarkChangeProcessor> change_processor_; 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StrictMock<MockUnrecoverableErrorHandler> mock_unrecoverable_error_handler_; 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, InitialState) { 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(other_bookmarks_id()); 516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(bookmark_bar_id()); 517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, BookmarkModelOperations) { 522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test addition. 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder = 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), 0, ASCIIToUTF16("foobar")); 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(folder); 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder2 = 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(folder, 0, ASCIIToUTF16("nested")); 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(folder2); 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* url1 = model_->AddURL( 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen folder, 0, ASCIIToUTF16("Internets #1 Pies Site"), 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL("http://www.easypie.com/")); 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(url1); 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* url2 = model_->AddURL( 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen folder, 1, ASCIIToUTF16("Airplanes"), GURL("http://www.easyjet.com/")); 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(url2); 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test modification. 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->SetTitle(url2, ASCIIToUTF16("EasyJet")); 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(url1, folder2, 0); 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(folder2, model_->GetBookmarkBarNode(), 0); 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->SetTitle(folder2, ASCIIToUTF16("Not Nested")); 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(folder, folder2, 0); 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->SetTitle(folder, ASCIIToUTF16("who's nested now?")); 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Copy(url2, model_->GetBookmarkBarNode(), 0); 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test deletion. 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Delete a single item. 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(url2->parent(), url2->parent()->GetIndexOf(url2)); 563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Delete an item with several children. 565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(folder2->parent(), 566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen folder2->parent()->GetIndexOf(folder2)); 567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, ServerChangeProcessing) { 571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(test_user_share_.user_share()); 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange adds(&trans); 577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f1 = adds.AddFolder(L"Server Folder B", bookmark_bar_id(), 0); 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f2 = adds.AddFolder(L"Server Folder A", bookmark_bar_id(), f1); 579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u1 = adds.AddURL(L"Some old site", "ftp://nifty.andrew.cmu.edu/", 580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bookmark_bar_id(), f2); 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u2 = adds.AddURL(L"Nifty", "ftp://nifty.andrew.cmu.edu/", f1, 0); 582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // u3 is a duplicate URL 583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u3 = adds.AddURL(L"Nifty2", "ftp://nifty.andrew.cmu.edu/", f1, u2); 584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // u4 is a duplicate title, different URL. 585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.AddURL(L"Some old site", "http://slog.thestranger.com/", 586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bookmark_bar_id(), u1); 587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // u5 tests an empty-string title. 588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string javascript_url( 589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "javascript:(function(){var w=window.open(" \ 590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "'about:blank','gnotesWin','location=0,menubar=0," \ 591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "scrollbars=0,status=0,toolbar=0,width=300," \ 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "height=300,resizable');});"); 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.AddURL(L"", javascript_url, other_bookmarks_id(), 0); 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<sync_api::SyncManager::ChangeRecord>::const_iterator it; 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The bookmark model shouldn't yet have seen any of the nodes of |adds|. 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeUnknown(it->id); 599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.ApplyPendingChanges(change_processor_.get()); 601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure the bookmark model received all of the nodes in |adds|. 603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeMatching(&trans, it->id); 605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Part two: test modifications. 608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange mods(&trans); 609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mess with u2, and move it into empty folder f2 610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(ncarter): Determine if we allow ModifyURL ops or not. 611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /* std::wstring u2_old_url = mods.ModifyURL(u2, L"http://www.google.com"); */ 612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring u2_old_title = mods.ModifyTitle(u2, L"The Google"); 613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u2_old_parent = mods.ModifyPosition(u2, f2, 0); 614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now move f1 after u2. 616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring f1_old_title = mods.ModifyTitle(f1, L"Server Folder C"); 617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f1_old_parent = mods.ModifyPosition(f1, f2, u2); 618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Then add u3 after f1. 620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u3_old_parent = mods.ModifyPosition(u3, f2, f1); 621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test that the property changes have not yet taken effect. 623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeTitle(u2, u2_old_title); 624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /* ExpectBrowserNodeURL(u2, u2_old_url); */ 625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeParent(u2, u2_old_parent); 626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeTitle(f1, f1_old_title); 628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeParent(f1, f1_old_parent); 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeParent(u3, u3_old_parent); 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Apply the changes. 633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mods.ApplyPendingChanges(change_processor_.get()); 634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check for successful application. 636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (it = mods.changes().begin(); it != mods.changes().end(); ++it) 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeMatching(&trans, it->id); 638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Part 3: Test URL deletion. 641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange dels(&trans); 642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dels.Delete(u2); 643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dels.Delete(u3); 644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeKnown(u2); 646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeKnown(u3); 647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dels.ApplyPendingChanges(change_processor_.get()); 649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 650ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeUnknown(u2); 651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeUnknown(u3); 652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests a specific case in ApplyModelChanges where we move the 656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// children out from under a parent, and then delete the parent 657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// in the same changelist. The delete shows up first in the changelist, 658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// requiring the children to be moved to a temporary location. 659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, ServerChangeRequiringFosterParent) { 660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(test_user_share_.user_share()); 664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Stress the immediate children of other_node because that's where 666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // ApplyModelChanges puts a temporary foster parent node. 667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string url("http://dev.chromium.org/"); 668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange adds(&trans); 669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f0 = other_bookmarks_id(); // + other_node 670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f1 = adds.AddFolder(L"f1", f0, 0); // + f1 671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f2 = adds.AddFolder(L"f2", f1, 0); // + f2 672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u3 = adds.AddURL( L"u3", url, f2, 0); // + u3 NOLINT 673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u4 = adds.AddURL( L"u4", url, f2, u3); // + u4 NOLINT 674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u5 = adds.AddURL( L"u5", url, f1, f2); // + u5 NOLINT 675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 f6 = adds.AddFolder(L"f6", f1, u5); // + f6 676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 u7 = adds.AddURL( L"u7", url, f0, f1); // + u7 NOLINT 677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<sync_api::SyncManager::ChangeRecord>::const_iterator it; 679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The bookmark model shouldn't yet have seen any of the nodes of |adds|. 680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeUnknown(it->id); 682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.ApplyPendingChanges(change_processor_.get()); 684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure the bookmark model received all of the nodes in |adds|. 686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (it = adds.changes().begin(); it != adds.changes().end(); ++it) 687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBrowserNodeMatching(&trans, it->id); 688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We have to do the moves before the deletions, but FakeServerChange will 691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // put the deletion at the front of the changelist. 692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange ops(&trans); 693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ModifyPosition(f6, other_bookmarks_id(), 0); 694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ModifyPosition(u3, other_bookmarks_id(), f1); // Prev == f1 is OK here. 695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ModifyPosition(f2, other_bookmarks_id(), u7); 696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ModifyPosition(u7, f2, 0); 697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ModifyPosition(u4, other_bookmarks_id(), f2); 698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ModifyPosition(u5, f6, 0); 699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.Delete(f1); 700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ops.ApplyPendingChanges(change_processor_.get()); 702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Simulate a server change record containing a valid but non-canonical URL. 707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, ServerChangeWithNonCanonicalURL) { 708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(test_user_share_.user_share()); 713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange adds(&trans); 715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string url("http://dev.chromium.org"); 716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_NE(GURL(url).spec(), url); 717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.AddURL(L"u1", url, other_bookmarks_id(), 0); 718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.ApplyPendingChanges(change_processor_.get()); 720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(model_->other_node()->child_count() == 1); 722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now reboot the sync service, forcing a merge step. 726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // There should still be just the one bookmark. 731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(model_->other_node()->child_count() == 1); 732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Simulate a server change record containing an invalid URL (per GURL). 736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(ncarter): Disabled due to crashes. Fix bug 1677563. 737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, DISABLED_ServerChangeWithInvalidURL) { 738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int child_count = 0; 742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(test_user_share_.user_share()); 744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FakeServerChange adds(&trans); 746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string url("x"); 747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(GURL(url).is_valid()); 748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.AddURL(L"u1", url, other_bookmarks_id(), 0); 749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen adds.ApplyPendingChanges(change_processor_.get()); 751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We're lenient about what should happen -- the model could wind up with 753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the node or without it; but things should be consistent, and we 754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // shouldn't crash. 755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_count = model_->other_node()->child_count(); 756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(child_count == 0 || child_count == 1); 757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(&trans); 758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now reboot the sync service, forcing a merge step. 761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Things ought not to have changed. 766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(model_->other_node()->child_count(), child_count); 767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Test strings that might pose a problem if the titles ever became used as 772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// file names in the sync backend. 773ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, CornerCaseNames) { 774ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(ncarter): Bug 1570238 explains the failure of this test. 775ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 777ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const char* names[] = { 779ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The empty string. 780ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "", 781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Illegal Windows filenames. 782ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", 783ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", 784ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", 785ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Current/parent directory markers. 786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ".", "..", "...", 787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Files created automatically by the Windows shell. 788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "Thumbs.db", ".DS_Store", 789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Names including Win32-illegal characters, and path separators. 790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "foo/bar", "foo\\bar", "foo?bar", "foo:bar", "foo|bar", "foo\"bar", 791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "foo'bar", "foo<bar", "foo>bar", "foo%bar", "foo*bar", "foo]bar", 792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "foo[bar", 793ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create both folders and bookmarks using each name. 795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL url("http://www.doublemint.com"); 796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < arraysize(names); ++i) { 797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), 0, ASCIIToUTF16(names[i])); 798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddURL(model_->other_node(), 0, ASCIIToUTF16(names[i]), url); 799ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 800ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 801ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Verify that the browser model matches the sync model. 802ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(model_->other_node()->child_count() == 2*arraysize(names)); 803ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 804ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 805ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 806ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Stress the internal representation of position by sparse numbers. We want 807ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// to repeatedly bisect the range of available positions, to force the 808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// syncer code to renumber its ranges. Pick a number big enough so that it 809ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// would exhaust 32bits of room between items a couple of times. 810ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, RepeatedMiddleInsertion) { 811ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 812ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 813ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const int kTimesToInsert = 256; 815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 816ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create two book-end nodes to insert between. 817ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), 0, ASCIIToUTF16("Alpha")); 818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("Omega")); 819ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int count = 2; 820ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test insertion in first half of range by repeatedly inserting in second 822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // position. 823ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < kTimesToInsert; ++i) { 824ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen string16 title = ASCIIToUTF16("Pre-insertion ") + base::IntToString16(i); 825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), 1, title); 826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen count++; 827ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 828ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 829ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test insertion in second half of range by repeatedly inserting in 830ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // second-to-last position. 831ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < kTimesToInsert; ++i) { 832ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen string16 title = ASCIIToUTF16("Post-insertion ") + base::IntToString16(i); 833ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), count - 1, title); 834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen count++; 835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Verify that the browser model matches the sync model. 838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(model_->other_node()->child_count(), count); 839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 840ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 841ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Introduce a consistency violation into the model, and see that it 843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// puts itself into a lame, error state. 844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, UnrecoverableErrorSuspendsService) { 845ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(mock_unrecoverable_error_handler_, 846ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnUnrecoverableError(_, _)); 847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add a node which will be the target of the consistency violation. 852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* node = 853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(model_->other_node(), 0, ASCIIToUTF16("node")); 854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeMatching(node); 855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now destroy the syncer node as if we were the ProfileSyncService without 857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // updating the ProfileSyncService state. This should introduce 858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // inconsistency between the two models. 859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(test_user_share_.user_share()); 861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode sync_node(&trans); 862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(InitSyncNodeFromChromeNode(node, &sync_node)); 863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_node.Remove(); 864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The models don't match at this point, but the ProfileSyncService 866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // doesn't know it yet. 867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectSyncerNodeKnown(node); 868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add a child to the inconsistent node. This should cause detection of the 870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // problem and the syncer should stop processing changes. 871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(node, 0, ASCIIToUTF16("nested")); 872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 873ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 874ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// See what happens if we run model association when there are two exact URL 875ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// duplicate bookmarks. The BookmarkModelAssociator should not fall over when 876ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// this happens. 877ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTest, MergeDuplicates) { 878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("Dup"), 882ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL("http://dup.com/")); 883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("Dup"), 884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL("http://dup.com/")); 885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(2, model_->other_node()->child_count()); 887ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 888ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Restart the sync service to trigger model association. 889ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 890ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 891ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 892ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(2, model_->other_node()->child_count()); 893ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 895ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct TestData { 897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const wchar_t* title; 898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const char* url; 899ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 900ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 901ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(ncarter): Integrate the existing TestNode/PopulateNodeFromString code 902ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// in the bookmark model unittest, to make it simpler to set up test data 903ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// here (and reduce the amount of duplication among tests), and to reduce the 904ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// duplication. 905ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass ProfileSyncServiceBookmarkTestWithData 906ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : public ProfileSyncServiceBookmarkTest { 907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen protected: 908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Populates or compares children of the given bookmark node from/with the 909ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // given test data array with the given size. 910ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void PopulateFromTestData(const BookmarkNode* node, 911ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const TestData* data, 912ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int size); 913ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void CompareWithTestData(const BookmarkNode* node, 914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const TestData* data, 915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int size); 916ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 917ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectBookmarkModelMatchesTestData(); 918ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void WriteTestDataToBookmarkModel(); 919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 920ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 922ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 923ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Constants for bookmark model that looks like: 924ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |-- Bookmark bar 925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- u2, http://www.u2.com/ 926ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f1 927ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | | |-- f1u4, http://www.f1u4.com/ 928ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | | |-- f1u2, http://www.f1u2.com/ 929ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | | |-- f1u3, http://www.f1u3.com/ 930ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | | +-- f1u1, http://www.f1u1.com/ 931ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- u1, http://www.u1.com/ 932ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | +-- f2 933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f2u2, http://www.f2u2.com/ 934ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f2u4, http://www.f2u4.com/ 935ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f2u3, http://www.f2u3.com/ 936ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | +-- f2u1, http://www.f2u1.com/ 937ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// +-- Other bookmarks 938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |-- f3 939ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f3u4, http://www.f3u4.com/ 940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f3u2, http://www.f3u2.com/ 941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f3u3, http://www.f3u3.com/ 942ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | +-- f3u1, http://www.f3u1.com/ 943ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |-- u4, http://www.u4.com/ 944ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |-- u3, http://www.u3.com/ 945ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// --- f4 946ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f4u1, http://www.f4u1.com/ 947ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f4u2, http://www.f4u2.com/ 948ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | |-- f4u3, http://www.f4u3.com/ 949ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | +-- f4u4, http://www.f4u4.com/ 950ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |-- dup 951ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// | +-- dupu1, http://www.dupu1.com/ 952ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// +-- dup 953ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// +-- dupu2, http://www.dupu1.com/ 954ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// 955ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kBookmarkBarChildren[] = { 956ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"u2", "http://www.u2.com/" }, 957ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f1", NULL }, 958ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"u1", "http://www.u1.com/" }, 959ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f2", NULL }, 960ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 961ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kF1Children[] = { 962ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f1u4", "http://www.f1u4.com/" }, 963ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f1u2", "http://www.f1u2.com/" }, 964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f1u3", "http://www.f1u3.com/" }, 965ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f1u1", "http://www.f1u1.com/" }, 966ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 967ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kF2Children[] = { 968ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f2u2", "http://www.f2u2.com/" }, 969ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f2u4", "http://www.f2u4.com/" }, 970ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f2u3", "http://www.f2u3.com/" }, 971ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f2u1", "http://www.f2u1.com/" }, 972ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 973ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 974ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kOtherBookmarkChildren[] = { 975ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f3", NULL }, 976ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"u4", "http://www.u4.com/" }, 977ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"u3", "http://www.u3.com/" }, 978ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f4", NULL }, 979ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"dup", NULL }, 980ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"dup", NULL }, 981ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 982ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kF3Children[] = { 983ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f3u4", "http://www.f3u4.com/" }, 984ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f3u2", "http://www.f3u2.com/" }, 985ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f3u3", "http://www.f3u3.com/" }, 986ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f3u1", "http://www.f3u1.com/" }, 987ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 988ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kF4Children[] = { 989ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f4u1", "http://www.f4u1.com/" }, 990ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f4u2", "http://www.f4u2.com/" }, 991ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f4u3", "http://www.f4u3.com/" }, 992ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"f4u4", "http://www.f4u4.com/" }, 993ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 994ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kDup1Children[] = { 995ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"dupu1", "http://www.dupu1.com/" }, 996ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 997ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic TestData kDup2Children[] = { 998ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { L"dupu2", "http://www.dupu2.com/" }, 999ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 1000ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1001ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // anonymous namespace. 1002ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1003ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileSyncServiceBookmarkTestWithData::PopulateFromTestData( 1004ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* node, const TestData* data, int size) { 1005ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(node); 1006ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(data); 1007ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(node->is_folder()); 1008ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < size; ++i) { 1009ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const TestData& item = data[i]; 1010ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (item.url) { 1011ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddURL(node, i, WideToUTF16Hack(item.title), GURL(item.url)); 1012ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 1013ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddFolder(node, i, WideToUTF16Hack(item.title)); 1014ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1015ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1016ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1017ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1018ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileSyncServiceBookmarkTestWithData::CompareWithTestData( 1019ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* node, const TestData* data, int size) { 1020ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(node); 1021ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(data); 1022ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(node->is_folder()); 1023ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(size, node->child_count()); 1024ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < size; ++i) { 1025ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* child_node = node->GetChild(i); 1026ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const TestData& item = data[i]; 1027ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(child_node->GetTitle(), WideToUTF16Hack(item.title)); 1028ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (item.url) { 1029ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(child_node->is_folder()); 1030ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(child_node->is_url()); 1031ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(child_node->GetURL(), GURL(item.url)); 1032ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 1033ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(child_node->is_folder()); 1034ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(child_node->is_url()); 1035ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1036ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1037ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1038ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1039ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(munjal): We should implement some way of generating random data and can 1040ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// use the same seed to generate the same sequence. 1041ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileSyncServiceBookmarkTestWithData::WriteTestDataToBookmarkModel() { 1042ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bookmarks_bar_node = model_->GetBookmarkBarNode(); 1043ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(bookmarks_bar_node, 1044ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kBookmarkBarChildren, 1045ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arraysize(kBookmarkBarChildren)); 1046ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1047ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(bookmarks_bar_node->child_count(), 4); 1048ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f1_node = bookmarks_bar_node->GetChild(1); 1049ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(f1_node, kF1Children, arraysize(kF1Children)); 1050ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f2_node = bookmarks_bar_node->GetChild(3); 1051ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(f2_node, kF2Children, arraysize(kF2Children)); 1052ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1053ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* other_bookmarks_node = model_->other_node(); 1054ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(other_bookmarks_node, 1055ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kOtherBookmarkChildren, 1056ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arraysize(kOtherBookmarkChildren)); 1057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1058ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(other_bookmarks_node->child_count(), 6); 1059ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f3_node = other_bookmarks_node->GetChild(0); 1060ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(f3_node, kF3Children, arraysize(kF3Children)); 1061ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f4_node = other_bookmarks_node->GetChild(3); 1062ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(f4_node, kF4Children, arraysize(kF4Children)); 1063ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* dup_node = other_bookmarks_node->GetChild(4); 1064ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(dup_node, kDup1Children, arraysize(kDup1Children)); 1065ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dup_node = other_bookmarks_node->GetChild(5); 1066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PopulateFromTestData(dup_node, kDup2Children, arraysize(kDup2Children)); 1067ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1069ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1070ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1071ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileSyncServiceBookmarkTestWithData:: 1072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData() { 1073ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bookmark_bar_node = model_->GetBookmarkBarNode(); 1074ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(bookmark_bar_node, 1075ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kBookmarkBarChildren, 1076ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arraysize(kBookmarkBarChildren)); 1077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(bookmark_bar_node->child_count(), 4); 1079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f1_node = bookmark_bar_node->GetChild(1); 1080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(f1_node, kF1Children, arraysize(kF1Children)); 1081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f2_node = bookmark_bar_node->GetChild(3); 1082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(f2_node, kF2Children, arraysize(kF2Children)); 1083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1084ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* other_bookmarks_node = model_->other_node(); 1085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(other_bookmarks_node, 1086ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kOtherBookmarkChildren, 1087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arraysize(kOtherBookmarkChildren)); 1088ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(other_bookmarks_node->child_count(), 6); 1090ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f3_node = other_bookmarks_node->GetChild(0); 1091ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(f3_node, kF3Children, arraysize(kF3Children)); 1092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f4_node = other_bookmarks_node->GetChild(3); 1093ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(f4_node, kF4Children, arraysize(kF4Children)); 1094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* dup_node = other_bookmarks_node->GetChild(4); 1095ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(dup_node, kDup1Children, arraysize(kDup1Children)); 1096ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dup_node = other_bookmarks_node->GetChild(5); 1097ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompareWithTestData(dup_node, kDup2Children, arraysize(kDup2Children)); 1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1099ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests persistence of the profile sync service by unloading the 1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// database and then reloading it from disk. 1102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, Persistence) { 1103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 1104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Force both models to discard their data and reload from disk. This 1111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // simulates what would happen if the browser were to shutdown normally, 1112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // and then relaunch. 1113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnloadBookmarkModel(); 1115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE); 1116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // With the BookmarkModel contents verified, ExpectModelMatch will 1121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // verify the contents of the sync model. 1122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests the merge case when the BookmarkModel is non-empty but the 1126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// sync model is empty. This corresponds to uploading browser 1127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// bookmarks to an initially empty, new account. 1128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, MergeWithEmptySyncModel) { 1129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Don't start the sync service until we've populated the bookmark model. 1130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 1131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Restart sync. This should trigger a merge step during 1135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // initialization -- we expect the browser bookmarks to be written 1136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to the sync service during this call. 1137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Verify that the bookmark model hasn't changed, and that the sync model 1140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // matches it exactly. 1141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests the merge case when the BookmarkModel is empty but the sync model is 1146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// non-empty. This corresponds (somewhat) to a clean install of the browser, 1147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// with no bookmarks, connecting to a sync account that has some bookmarks. 1148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, MergeWithEmptyBookmarkModel) { 1149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Force the databse to unload and write itself to disk. 1157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Blow away the bookmark model -- it should be empty afterwards. 1160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnloadBookmarkModel(); 1161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(model_->GetBookmarkBarNode()->child_count(), 0); 1163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(model_->other_node()->child_count(), 0); 1164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now restart the sync service. Starting it should populate the bookmark 1166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // model -- test for consistency. 1167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests the merge cases when both the models are expected to be identical 1173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// after the merge. 1174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, MergeExpectedIdenticalModels) { 1175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 1176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnloadBookmarkModel(); 1181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // At this point both the bookmark model and the server should have the 1183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // exact same data and it should match the test data. 1184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE); 1185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnloadBookmarkModel(); 1190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now reorder some bookmarks in the bookmark model and then merge. Make 1192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // sure we get the order of the server after merge. 1193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE); 1194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bookmark_bar = model_->GetBookmarkBarNode(); 1196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(bookmark_bar); 1197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(bookmark_bar->child_count(), 1); 1198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(bookmark_bar->GetChild(0), bookmark_bar, 1); 1199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests the merge cases when both the models are expected to be identical 1205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// after the merge. 1206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, MergeModelsWithSomeExtras) { 1207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Remove some nodes and reorder some nodes. 1212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bookmark_bar_node = model_->GetBookmarkBarNode(); 1213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int remove_index = 2; 1214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 1215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* child_node = bookmark_bar_node->GetChild(remove_index); 1216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node); 1217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node->is_url()); 1218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(bookmark_bar_node, remove_index); 1219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 1220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_node = bookmark_bar_node->GetChild(remove_index); 1221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node); 1222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node->is_folder()); 1223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(bookmark_bar_node, remove_index); 1224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* other_node = model_->other_node(); 1226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(other_node->child_count(), 1); 1227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* f3_node = other_node->GetChild(0); 1228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(f3_node); 1229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(f3_node->is_folder()); 1230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen remove_index = 2; 1231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(f3_node->child_count(), remove_index); 1232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(f3_node, remove_index); 1233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(f3_node->child_count(), remove_index); 1234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(f3_node, remove_index); 1235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Remove some nodes and reorder some nodes. 1245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bookmark_bar_node = model_->GetBookmarkBarNode(); 1246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen remove_index = 0; 1247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 1248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_node = bookmark_bar_node->GetChild(remove_index); 1249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node); 1250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node->is_url()); 1251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(bookmark_bar_node, remove_index); 1252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(bookmark_bar_node->child_count(), remove_index); 1253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_node = bookmark_bar_node->GetChild(remove_index); 1254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node); 1255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(child_node->is_folder()); 1256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(bookmark_bar_node, remove_index); 1257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(bookmark_bar_node->child_count(), 2); 1259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(bookmark_bar_node->GetChild(0), bookmark_bar_node, 1); 1260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen other_node = model_->other_node(); 1262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(other_node->child_count(), 1); 1263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen f3_node = other_node->GetChild(0); 1264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(f3_node); 1265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(f3_node->is_folder()); 1266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen remove_index = 0; 1267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(f3_node->child_count(), remove_index); 1268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(f3_node, remove_index); 1269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GT(f3_node->child_count(), remove_index); 1270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Remove(f3_node, remove_index); 1271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_GE(other_node->child_count(), 4); 1273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(other_node->GetChild(0), other_node, 1); 1274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->Move(other_node->GetChild(2), other_node, 3); 1275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // After the merge, the model should match the test data. 1280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests that when persisted model associations are used, things work fine. 1284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, ModelAssociationPersistence) { 1285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Force sync to shut down and write itself to disk. 1290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now restart sync. This time it should use the persistent 1292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // associations. 1293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Tests that when persisted model associations are used, things work fine. 1298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, 1299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelAssociationInvalidPersistence) { 1300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Force sync to shut down and write itself to disk. 1305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Change the bookmark model before restarting sync service to simulate 1307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the situation where bookmark model is different from sync model and 1308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // make sure model associator correctly rebuilds associations. 1309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* bookmark_bar_node = model_->GetBookmarkBarNode(); 1310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->AddURL(bookmark_bar_node, 0, ASCIIToUTF16("xtra"), 1311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL("http://www.xtra.com")); 1312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now restart sync. This time it will try to use the persistent 1313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // associations and realize that they are invalid and hence will rebuild 1314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // associations. 1315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, SortChildren) { 1320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE); 1321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Write test data to bookmark model and verify that the models match. 1324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder_added = model_->other_node()->GetChild(0); 1326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(folder_added); 1327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(folder_added->is_folder()); 1328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Sort the other-bookmarks children and expect that hte models match. 1332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_->SortChildren(folder_added); 1333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// See what happens if we enable sync but then delete the "Sync Data" 1337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// folder. 1338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ProfileSyncServiceBookmarkTestWithData, 1339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RecoverAfterDeletingSyncDataDirectory) { 1340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE); 1341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTestDataToBookmarkModel(); 1344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopSync(); 1346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Nuke the sync DB and reload. 1348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen test_user_share_.TearDown(); 1349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen test_user_share_.SetUp(); 1350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartSync(); 1352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure we're back in sync. In real life, the user would need 1354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to reauthenticate before this happens, but in the test, authentication 1355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is sidestepped. 1356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectBookmarkModelMatchesTestData(); 1357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectModelMatch(); 1358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 1361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace browser_sync 1363