1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <string> 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/base_paths.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_util.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/hash_tables.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/path_service.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string16.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/string_split.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_codec.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_utils.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_notifications.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/test/model_test_utils.h" 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/test/testing_browser_process_test.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/test/testing_profile.h" 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h" 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h" 3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/models/tree_node_iterator.h" 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/models/tree_node_model.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper to get a mutable bookmark node. 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic BookmarkNode* AsMutable(const BookmarkNode* node) { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return const_cast<BookmarkNode*>(node); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SwapDateAdded(BookmarkNode* n1, BookmarkNode* n2) { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time tmp = n1->date_added(); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n1->set_date_added(n2->date_added()); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n2->set_date_added(tmp); 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // anonymous namespace 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass BookmarkModelTest : public TestingBrowserProcessTest, 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public BookmarkModelObserver { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct ObserverDetails { 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ObserverDetails() { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Set(NULL, NULL, -1, -1); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Set(const BookmarkNode* node1, 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node2, 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index1, 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index2) { 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this->node1 = node1; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this->node2 = node2; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this->index1 = index1; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this->index2 = index2; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void AssertEquals(const BookmarkNode* node1, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node2, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index1, 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index2) { 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(this->node1 == node1); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(this->node2 == node2); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(index1, this->index1); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(index2, this->index2); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node1; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node2; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index1; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index2; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModelTest() : model(NULL) { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.AddObserver(this); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Loaded(BookmarkModel* model) { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We never load from the db, so that this should never get invoked. 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeMoved(BookmarkModel* model, 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* old_parent, 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int old_index, 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* new_parent, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index) { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch moved_count++; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.Set(old_parent, new_parent, old_index, new_index); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeAdded(BookmarkModel* model, 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch added_count++; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.Set(parent, NULL, index, -1); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeRemoved(BookmarkModel* model, 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int old_index, 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) { 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch removed_count++; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.Set(parent, NULL, old_index, -1); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeChanged(BookmarkModel* model, 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) { 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_count++; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.Set(node, NULL, -1, -1); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reordered_count_++; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void BookmarkNodeFaviconLoaded(BookmarkModel* model, 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We never attempt to load favicons, so that this method never 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // gets invoked. 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ClearCounts() { 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reordered_count_ = moved_count = added_count = removed_count = 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_count = 0; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void AssertObserverCount(int added_count, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int moved_count, 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int removed_count, 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int changed_count, 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int reordered_count) { 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(added_count, this->added_count); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(moved_count, this->moved_count); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(removed_count, this->removed_count); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(changed_count, this->changed_count); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(reordered_count, reordered_count_); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModel model; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int moved_count; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int added_count; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int removed_count; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int changed_count; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int reordered_count_; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ObserverDetails observer_details; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, InitialState) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* bb_node = model.GetBookmarkBarNode(); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(bb_node != NULL); 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(0, bb_node->child_count()); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(BookmarkNode::BOOKMARK_BAR, bb_node->type()); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* other_node = model.other_node(); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(other_node != NULL); 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(0, other_node->child_count()); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(BookmarkNode::OTHER_NODE, other_node->type()); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(bb_node->id() != other_node->id()); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, AddURL) { 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com"); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* new_node = model.AddURL(root, 0, title, url); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(1, 0, 0, 0, 0); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(root, NULL, 0, -1); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(1, root->child_count()); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(title, new_node->GetTitle()); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(url == new_node->GetURL()); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(BookmarkNode::URL, new_node->type()); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(new_node == model.GetMostRecentlyAddedNodeForURL(url)); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(new_node->id() != root->id() && 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_node->id() != model.other_node()->id()); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(BookmarkModelTest, AddFolder) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* new_node = model.AddFolder(root, 0, title); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(1, 0, 0, 0, 0); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(root, NULL, 0, -1); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(1, root->child_count()); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(title, new_node->GetTitle()); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(BookmarkNode::FOLDER, new_node->type()); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(new_node->id() != root->id() && 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_node->id() != model.other_node()->id()); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add another folder, just to make sure folder_ids are incremented correctly. 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.AddFolder(root, 0, title); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(1, 0, 0, 0, 0); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(root, NULL, 0, -1); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, RemoveURL) { 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com"); 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.AddURL(root, 0, title, url); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Remove(root, 0); 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(0, root->child_count()); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 0, 1, 0, 0); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(root, NULL, 0, -1); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure there is no mapping for the URL. 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(model.GetMostRecentlyAddedNodeForURL(url) == NULL); 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(BookmarkModelTest, RemoveFolder) { 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder = model.AddFolder(root, 0, ASCIIToUTF16("foo")); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a URL as a child. 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com"); 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.AddURL(folder, 0, title, url); 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now remove the folder. 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Remove(root, 0); 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(0, root->child_count()); 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 0, 1, 0, 0); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(root, NULL, 0, -1); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure there is no mapping for the URL. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(model.GetMostRecentlyAddedNodeForURL(url) == NULL); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, SetTitle) { 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 title(ASCIIToUTF16("foo")); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com"); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = model.AddURL(root, 0, title, url); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick title = ASCIIToUTF16("foo2"); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.SetTitle(node, title); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 0, 0, 1, 0); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(node, NULL, -1, -1); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(title, node->GetTitle()); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, SetURL) { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url("http://foo.com"); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = model.AddURL(root, 0, title, url); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url = GURL("http://foo2.com"); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.SetURL(node, url); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 0, 0, 1, 0); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(node, NULL, -1, -1); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(url, node->GetURL()); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, Move) { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com"); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = model.AddURL(root, 0, title, url); 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder1 = model.AddFolder(root, 0, ASCIIToUTF16("foo")); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.Move(node, folder1, 0); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 1, 0, 0, 0); 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen observer_details.AssertEquals(root, folder1, 1, 0); 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(folder1 == node->parent()); 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(1, root->child_count()); 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(folder1, root->GetChild(0)); 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(1, folder1->child_count()); 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(node, folder1->GetChild(0)); 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // And remove the folder. 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Remove(root, 0); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 0, 1, 0, 0); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch observer_details.AssertEquals(root, NULL, 0, -1); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(model.GetMostRecentlyAddedNodeForURL(url) == NULL); 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(0, root->child_count()); 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, Copy) { 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* root = model.GetBookmarkBarNode(); 3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static const std::string model_string("a 1:[ b c ] d 2:[ e f g ] h "); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_test_utils::AddNodesFromModelString(model, root, model_string); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Validate initial model. 3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string actualModelString = model_test_utils::ModelStringFromNode(root); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(model_string, actualModelString); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy 'd' to be after '1:b': URL item from bar to folder. 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* nodeToCopy = root->GetChild(2); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* destination = root->GetChild(1); 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Copy(nodeToCopy, destination, 1); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString = model_test_utils::ModelStringFromNode(root); 3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ("a 1:[ b d c ] d 2:[ e f g ] h ", actualModelString); 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy '1:d' to be after 'a': URL item from folder to bar. 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder = root->GetChild(1); 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nodeToCopy = folder->GetChild(1); 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Copy(nodeToCopy, root, 1); 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString = model_test_utils::ModelStringFromNode(root); 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ("a d 1:[ b d c ] d 2:[ e f g ] h ", actualModelString); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy '1' to be after '2:e': Folder from bar to folder. 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodeToCopy = root->GetChild(2); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch destination = root->GetChild(4); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Copy(nodeToCopy, destination, 1); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString = model_test_utils::ModelStringFromNode(root); 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f g ] h ", actualModelString); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy '2:1' to be after '2:f': Folder within same folder. 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen folder = root->GetChild(4); 353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nodeToCopy = folder->GetChild(1); 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.Copy(nodeToCopy, folder, 3); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString = model_test_utils::ModelStringFromNode(root); 3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h ", 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy first 'd' to be after 'h': URL item within the bar. 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodeToCopy = root->GetChild(1); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Copy(nodeToCopy, root, 6); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString = model_test_utils::ModelStringFromNode(root); 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ", 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString); 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy '2' to be after 'a': Folder within the bar. 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodeToCopy = root->GetChild(4); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.Copy(nodeToCopy, root, 1); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString = model_test_utils::ModelStringFromNode(root); 3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ("a 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] d 1:[ b d c ] " 3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ", 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actualModelString); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that adding a URL to a folder updates the last modified time. 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, ParentForNewNodes) { 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(model.GetBookmarkBarNode(), model.GetParentForNewNodes()); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16 title(ASCIIToUTF16("foo")); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com"); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.AddURL(model.other_node(), 0, title, url); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(model.other_node(), model.GetParentForNewNodes()); 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Make sure recently modified stays in sync when adding a URL. 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(BookmarkModelTest, MostRecentlyModifiedFolders) { 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add a folder. 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const BookmarkNode* folder = model.AddFolder(model.other_node(), 0, 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASCIIToUTF16("foo")); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a URL to it. 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.AddURL(folder, 0, ASCIIToUTF16("blah"), GURL("http://foo.com")); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure folder is in the most recently modified. 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<const BookmarkNode*> most_recent_folders = 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bookmark_utils::GetMostRecentlyModifiedFolders(&model, 1); 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(1U, most_recent_folders.size()); 398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(folder, most_recent_folders[0]); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Nuke the folder and do another fetch, making sure folder isn't in the 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // returned list. 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.Remove(folder->parent(), 0); 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen most_recent_folders = 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bookmark_utils::GetMostRecentlyModifiedFolders(&model, 1); 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(1U, most_recent_folders.size()); 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(most_recent_folders[0] != folder); 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Make sure MostRecentlyAddedEntries stays in sync. 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, MostRecentlyAddedEntries) { 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a couple of nodes such that the following holds for the time of the 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // nodes: n1 > n2 > n3 > n4. 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time base_time = Time::Now(); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* n1 = AsMutable(model.AddURL(model.GetBookmarkBarNode(), 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, 4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToUTF16("blah"), 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("http://foo.com/0"))); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* n2 = AsMutable(model.AddURL(model.GetBookmarkBarNode(), 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, 4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToUTF16("blah"), 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("http://foo.com/1"))); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* n3 = AsMutable(model.AddURL(model.GetBookmarkBarNode(), 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2, 4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToUTF16("blah"), 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("http://foo.com/2"))); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* n4 = AsMutable(model.AddURL(model.GetBookmarkBarNode(), 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3, 4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToUTF16("blah"), 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("http://foo.com/3"))); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n1->set_date_added(base_time + TimeDelta::FromDays(4)); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n2->set_date_added(base_time + TimeDelta::FromDays(3)); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n3->set_date_added(base_time + TimeDelta::FromDays(2)); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n4->set_date_added(base_time + TimeDelta::FromDays(1)); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure order is honored. 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*> recently_added; 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_utils::GetMostRecentlyAddedEntries(&model, 2, &recently_added); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(2U, recently_added.size()); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(n1 == recently_added[0]); 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(n2 == recently_added[1]); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // swap 1 and 2, then check again. 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch recently_added.clear(); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SwapDateAdded(n1, n2); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_utils::GetMostRecentlyAddedEntries(&model, 4, &recently_added); 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(4U, recently_added.size()); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(n2 == recently_added[0]); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(n1 == recently_added[1]); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(n3 == recently_added[2]); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(n4 == recently_added[3]); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Makes sure GetMostRecentlyAddedNodeForURL stays in sync. 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, GetMostRecentlyAddedNodeForURL) { 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a couple of nodes such that the following holds for the time of the 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // nodes: n1 > n2 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time base_time = Time::Now(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com/0"); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* n1 = AsMutable(model.AddURL( 4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.GetBookmarkBarNode(), 0, ASCIIToUTF16("blah"), url)); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* n2 = AsMutable(model.AddURL( 4623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.GetBookmarkBarNode(), 1, ASCIIToUTF16("blah"), url)); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n1->set_date_added(base_time + TimeDelta::FromDays(4)); 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n2->set_date_added(base_time + TimeDelta::FromDays(3)); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure order is honored. 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(n1, model.GetMostRecentlyAddedNodeForURL(url)); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // swap 1 and 2, then check again. 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SwapDateAdded(n1, n2); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(n2, model.GetMostRecentlyAddedNodeForURL(url)); 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Makes sure GetBookmarks removes duplicates. 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, GetBookmarksWithDups) { 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com/0"); 4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.AddURL(model.GetBookmarkBarNode(), 0, ASCIIToUTF16("blah"), url); 4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.AddURL(model.GetBookmarkBarNode(), 1, ASCIIToUTF16("blah"), url); 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<GURL> urls; 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.GetBookmarks(&urls); 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1U, urls.size()); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(urls[0] == url); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_F(BookmarkModelTest, HasBookmarks) { 4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const GURL url("http://foo.com/"); 4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.AddURL(model.GetBookmarkBarNode(), 0, ASCIIToUTF16("bar"), url); 4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_TRUE(model.HasBookmarks()); 4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// NotificationObserver implementation used in verifying we've received the 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// NOTIFY_URLS_STARRED method correctly. 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass StarredListener : public NotificationObserver { 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StarredListener() : notification_count_(0), details_(false) { 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::URLS_STARRED, Source<Profile>(NULL)); 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Observe(NotificationType type, 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NotificationType::URLS_STARRED) { 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch notification_count_++; 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details_ = *(Details<history::URLsStarredDetails>(details).ptr()); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Number of times NOTIFY_URLS_STARRED has been observed. 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int notification_count_; 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Details from the last NOTIFY_URLS_STARRED. 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::URLsStarredDetails details_; 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(StarredListener); 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Makes sure NOTIFY_URLS_STARRED is sent correctly. 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, NotifyURLsStarred) { 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StarredListener listener; 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL url("http://foo.com/0"); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* n1 = model.AddURL( 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.GetBookmarkBarNode(), 0, ASCIIToUTF16("blah"), url); 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Starred notification should be sent. 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, listener.notification_count_); 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(listener.details_.starred); 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(1U, listener.details_.changed_urls.size()); 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(url == *(listener.details_.changed_urls.begin())); 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch listener.notification_count_ = 0; 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch listener.details_.changed_urls.clear(); 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add another bookmark for the same URL. This should not send any 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notification. 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* n2 = model.AddURL( 5443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model.GetBookmarkBarNode(), 1, ASCIIToUTF16("blah"), url); 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, listener.notification_count_); 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove n2. 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.Remove(n2->parent(), 1); 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch n2 = NULL; 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Shouldn't have received any notification as n1 still exists with the same 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URL. 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, listener.notification_count_); 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(model.GetMostRecentlyAddedNodeForURL(url) == n1); 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove n1. 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model.Remove(n1->parent(), 0); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now we should get the notification. 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, listener.notification_count_); 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_FALSE(listener.details_.starred); 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(1U, listener.details_.changed_urls.size()); 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(url == *(listener.details_.changed_urls.begin())); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// See comment in PopulateNodeFromString. 57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentypedef ui::TreeNodeWithValue<BookmarkNode::Type> TestNode; 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Does the work of PopulateNodeFromString. index gives the index of the current 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// element in description to process. 5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void PopulateNodeImpl(const std::vector<std::string>& description, 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t* index, 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode* parent) { 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (*index < description.size()) { 5793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& element = description[*index]; 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*index)++; 5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (element == "[") { 582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create a new folder and recurse to add all the children. 583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Folders are given a unique named by way of an ever increasing integer 584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // value. The folders need not have a name, but one is assigned to help 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in debugging. 586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static int next_folder_id = 1; 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode* new_node = 588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new TestNode(base::IntToString16(next_folder_id++), 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode::FOLDER); 590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent->Add(new_node, parent->child_count()); 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateNodeImpl(description, index, new_node); 5923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (element == "]") { 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // End the current folder. 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a new URL. 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // All tokens must be space separated. If there is a [ or ] in the name it 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // likely means a space was forgotten. 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(element.find('[') == std::string::npos); 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(element.find(']') == std::string::npos); 602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent->Add(new TestNode(UTF8ToUTF16(element), BookmarkNode::URL), 603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent->child_count()); 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Creates and adds nodes to parent based on description. description consists 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of the following tokens (all space separated): 610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// [ : creates a new USER_FOLDER node. All elements following the [ until the 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// next balanced ] is encountered are added as children to the node. 612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ] : closes the last folder created by [ so that any further nodes are added 613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// to the current folders parent. 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// text: creates a new URL node. 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For example, "a [b] c" creates the following nodes: 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a 1 c 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// | 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// b 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// In words: a node of type URL with the title a, followed by a folder node with 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the title 1 having the single child of type url with name b, followed by 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the url node with the title c. 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// NOTE: each name must be unique, and folders are assigned a unique title by 624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// way of an increasing integer. 6253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void PopulateNodeFromString(const std::string& description, 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode* parent) { 6273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<std::string> elements; 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t index = 0; 6294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::SplitStringAlongWhitespace(description, &elements); 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateNodeImpl(elements, &index, parent); 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Populates the BookmarkNode with the children of parent. 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void PopulateBookmarkNode(TestNode* parent, 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModel* model, 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* bb_node) { 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < parent->child_count(); ++i) { 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode* child = parent->GetChild(i); 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (child->value == BookmarkNode::FOLDER) { 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* new_bb_node = 641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model->AddFolder(bb_node, i, child->GetTitle()); 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateBookmarkNode(child, model, new_bb_node); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->AddURL(bb_node, i, child->GetTitle(), 6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL("http://" + UTF16ToASCII(child->GetTitle()))); 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test class that creates a BookmarkModel with a real history backend. 653dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass BookmarkModelTestWithProfile : public TestingBrowserProcessTest, 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public BookmarkModelObserver { 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModelTestWithProfile() 657731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : ui_thread_(BrowserThread::UI, &message_loop_), 658731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick file_thread_(BrowserThread::FILE, &message_loop_) {} 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SetUp() { 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void TearDown() { 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_.reset(NULL); 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The profile. 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<TestingProfile> profile_; 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Verifies the contents of the bookmark bar node match the contents of the 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TestNode. 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void VerifyModelMatchesNode(TestNode* expected, const BookmarkNode* actual) { 674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(expected->child_count(), actual->child_count()); 675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < expected->child_count(); ++i) { 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode* expected_child = expected->GetChild(i); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* actual_child = actual->GetChild(i); 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(expected_child->GetTitle(), actual_child->GetTitle()); 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (expected_child->value == BookmarkNode::FOLDER) { 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(actual_child->type() == BookmarkNode::FOLDER); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Recurse throught children. 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyModelMatchesNode(expected_child, actual_child); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasFatalFailure()) 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No need to check the URL, just the title is enough. 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(actual_child->type() == BookmarkNode::URL); 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void VerifyNoDuplicateIDs(BookmarkModel* model) { 69372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::TreeNodeIterator<const BookmarkNode> it(model->root_node()); 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::hash_set<int64> ids; 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (it.has_next()) 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(ids.insert(it.Next()->id()).second); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BlockTillBookmarkModelLoaded() { 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bb_model_ = profile_->GetBookmarkModel(); 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bb_model_->IsLoaded()) 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillLoaded(bb_model_); 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bb_model_->AddObserver(this); 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Destroys the current profile, creates a new one and creates the history 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // service. 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void RecreateProfile() { 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Need to shutdown the old one before creating a new one. 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_.reset(NULL); 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_.reset(new TestingProfile()); 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateHistoryService(true, false); 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModel* bb_model_; 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Blocks until the BookmarkModel has finished loading. 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void BlockTillLoaded(BookmarkModel* model) { 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->AddObserver(this); 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Run(); 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // BookmarkModelObserver methods. 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Loaded(BookmarkModel* model) { 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Balances the call in BlockTillLoaded. 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Quit(); 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeMoved(BookmarkModel* model, 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* old_parent, 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int old_index, 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* new_parent, 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index) {} 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeAdded(BookmarkModel* model, 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) {} 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeRemoved(BookmarkModel* model, 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int old_index, 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) {} 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeChanged(BookmarkModel* model, 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) {} 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) {} 746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void BookmarkNodeFaviconLoaded(BookmarkModel* model, 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node) {} 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForUI message_loop_; 750731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread ui_thread_; 751731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread file_thread_; 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Creates a set of nodes in the bookmark bar model, then recreates the 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// bookmark bar model which triggers loading from the db and checks the loaded 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// structure to make sure it is what we first created. 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTestWithProfile, CreateAndRestore) { 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct TestData { 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Structure of the children of the bookmark bar model node. 7603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string bbn_contents; 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Structure of the children of the other node. 7623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string other_contents; 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } data[] = { 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See PopulateNodeFromString for a description of these strings. 7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { "", "" }, 7663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { "a", "b" }, 7673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { "a [ b ]", "" }, 7683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { "", "[ b ] a [ c [ d e [ f ] ] ]" }, 7693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { "a [ b ]", "" }, 7703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { "a b c [ d e [ f ] ]", "g h i [ j k [ l ] ]"}, 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Recreate the profile. We need to reset with NULL first so that the last 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // HistoryService releases the locks on the files it creates and we can 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // delete them. 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_.reset(NULL); 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_.reset(new TestingProfile()); 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateBookmarkModel(true); 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateHistoryService(true, false); 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillBookmarkModelLoaded(); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode bbn; 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateNodeFromString(data[i].bbn_contents, &bbn); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateBookmarkNode(&bbn, bb_model_, bb_model_->GetBookmarkBarNode()); 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode other; 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateNodeFromString(data[i].other_contents, &other); 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateBookmarkNode(&other, bb_model_, bb_model_->other_node()); 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateBookmarkModel(false); 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillBookmarkModelLoaded(); 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyModelMatchesNode(&bbn, bb_model_->GetBookmarkBarNode()); 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyModelMatchesNode(&other, bb_model_->other_node()); 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyNoDuplicateIDs(bb_model_); 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test class that creates a BookmarkModel with a real history backend. 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BookmarkModelTestWithProfile2 : public BookmarkModelTestWithProfile { 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SetUp() { 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_.reset(new TestingProfile()); 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Verifies the state of the model matches that of the state in the saved 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // history file. 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void VerifyExpectedState() { 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Here's the structure we expect: 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bbn 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // www.google.com - Google 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // F1 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // http://www.google.com/intl/en/ads/ - Google Advertising 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // F11 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // http://www.google.com/services/ - Google Business Solutions 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // other 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OF1 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // http://www.google.com/intl/en/about.html - About Google 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* bbn = bb_model_->GetBookmarkBarNode(); 821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(2, bbn->child_count()); 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* child = bbn->GetChild(0); 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(BookmarkNode::URL, child->type()); 8253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("Google"), child->GetTitle()); 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->GetURL() == GURL("http://www.google.com")); 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child = bbn->GetChild(1); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->is_folder()); 8303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("F1"), child->GetTitle()); 831ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(2, child->child_count()); 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent = child; 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child = parent->GetChild(0); 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(BookmarkNode::URL, child->type()); 8363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("Google Advertising"), child->GetTitle()); 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->GetURL() == GURL("http://www.google.com/intl/en/ads/")); 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child = parent->GetChild(1); 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->is_folder()); 8413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("F11"), child->GetTitle()); 842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(1, child->child_count()); 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent = child; 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child = parent->GetChild(0); 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(BookmarkNode::URL, child->type()); 8473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("Google Business Solutions"), child->GetTitle()); 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->GetURL() == GURL("http://www.google.com/services/")); 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent = bb_model_->other_node(); 851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(2, parent->child_count()); 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child = parent->GetChild(0); 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->is_folder()); 8553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("OF1"), child->GetTitle()); 856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_EQ(0, child->child_count()); 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child = parent->GetChild(1); 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_EQ(BookmarkNode::URL, child->type()); 8603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_EQ(ASCIIToUTF16("About Google"), child->GetTitle()); 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(child->GetURL() == 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("http://www.google.com/intl/en/about.html")); 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(bb_model_->IsBookmarked(GURL("http://www.google.com"))); 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void VerifyUniqueIDs() { 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<int64> ids; 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_unique = true; 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUniqueIDImpl(bb_model_->GetBookmarkBarNode(), &ids, &has_unique); 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUniqueIDImpl(bb_model_->other_node(), &ids, &has_unique); 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(has_unique); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void VerifyUniqueIDImpl(const BookmarkNode* node, 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<int64>* ids, 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* has_unique) { 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!*has_unique) 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ids->count(node->id()) != 0) { 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *has_unique = false; 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ids->insert(node->id()); 886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < node->child_count(); ++i) { 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUniqueIDImpl(node->GetChild(i), ids, has_unique); 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!*has_unique) 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests migrating bookmarks from db into file. This copies an old history db 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// file containing bookmarks and make sure they are loaded correctly and 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// persisted correctly. 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTestWithProfile2, MigrateFromDBToFileTest) { 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy db file over that contains starred table. 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath old_history_path; 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PathService::Get(chrome::DIR_TEST_DATA, &old_history_path); 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_history_path = old_history_path.AppendASCII("bookmarks"); 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_history_path = old_history_path.AppendASCII("History_with_starred"); 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath new_history_path = profile_->GetPath(); 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::Delete(new_history_path, true); 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::CreateDirectory(new_history_path); 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath new_history_file = new_history_path.Append( 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kHistoryFilename); 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(file_util::CopyFile(old_history_path, new_history_file)); 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create the history service making sure it doesn't blow away the file we 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // just copied. 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateHistoryService(false, false); 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateBookmarkModel(true); 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillBookmarkModelLoaded(); 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure we loaded OK. 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyExpectedState(); 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasFatalFailure()) 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure the ids are unique. 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUniqueIDs(); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasFatalFailure()) 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create again. This time we shouldn't load from history at all. 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateBookmarkModel(false); 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillBookmarkModelLoaded(); 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure we loaded OK. 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyExpectedState(); 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasFatalFailure()) 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUniqueIDs(); 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasFatalFailure()) 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Recreate the history service (with a clean db). Do this just to make sure 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we're loading correctly from the bookmarks file. 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateHistoryService(true, false); 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateBookmarkModel(false); 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillBookmarkModelLoaded(); 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyExpectedState(); 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUniqueIDs(); 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Simple test that removes a bookmark. This test exercises the code paths in 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// History that block till bookmark bar model is loaded. 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTestWithProfile2, RemoveNotification) { 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateHistoryService(false, false); 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->CreateBookmarkModel(true); 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlockTillBookmarkModelLoaded(); 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a URL. 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url("http://www.google.com"); 9573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bb_model_->SetURLStarred(url, string16(), true); 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->AddPage( 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url, NULL, 1, GURL(), PageTransition::TYPED, 9613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick history::RedirectList(), history::SOURCE_BROWSED, false); 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This won't actually delete the URL, rather it'll empty out the visits. 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This triggers blocking on the BookmarkModel. 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->DeleteURL(url); 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(BookmarkModelTest, Sort) { 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Populate the bookmark bar node with nodes for 'B', 'a', 'd' and 'C'. 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 'C' and 'a' are folders. 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestNode bbn; 9723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PopulateNodeFromString("B [ a ] d [ a ]", &bbn); 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent = model.GetBookmarkBarNode(); 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PopulateBookmarkNode(&bbn, &model, parent); 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* child1 = AsMutable(parent->GetChild(1)); 977ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child1->set_title(ASCIIToUTF16("a")); 978ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete child1->Remove(child1->GetChild(0)); 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkNode* child3 = AsMutable(parent->GetChild(3)); 980ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child3->set_title(ASCIIToUTF16("C")); 981ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete child3->Remove(child3->GetChild(0)); 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearCounts(); 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sort the children of the bookmark bar node. 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model.SortChildren(parent); 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure we were notified. 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AssertObserverCount(0, 0, 0, 0, 1); 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure the order matches (remember, 'a' and 'C' are folders and 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // come first). 9933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ(parent->GetChild(0)->GetTitle(), ASCIIToUTF16("a")); 9943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ(parent->GetChild(1)->GetTitle(), ASCIIToUTF16("C")); 9953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ(parent->GetChild(2)->GetTitle(), ASCIIToUTF16("B")); 9963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EXPECT_EQ(parent->GetChild(3)->GetTitle(), ASCIIToUTF16("d")); 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 998