1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <vector> 6 7 #include "base/file_util.h" 8 #include "base/path_service.h" 9 #include "base/string_util.h" 10 #include "base/memory/scoped_temp_dir.h" 11 #include "base/utf_string_conversions.h" 12 #include "chrome/browser/history/history.h" 13 #include "chrome/browser/history/starred_url_database.h" 14 #include "chrome/common/chrome_paths.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace history { 18 19 class StarredURLDatabaseTest : public testing::Test, 20 public StarredURLDatabase { 21 public: 22 StarredURLDatabaseTest() { 23 } 24 25 void AddPage(const GURL& url) { 26 URLRow row(url); 27 row.set_visit_count(1); 28 EXPECT_TRUE(AddURL(row)); 29 } 30 31 void CompareEntryByID(const StarredEntry& entry) { 32 DCHECK(entry.id != 0); 33 StarredEntry db_value; 34 EXPECT_TRUE(GetStarredEntry(entry.id, &db_value)); 35 EXPECT_EQ(entry.id, db_value.id); 36 EXPECT_TRUE(entry.title == db_value.title); 37 EXPECT_EQ(entry.date_added.ToTimeT(), db_value.date_added.ToTimeT()); 38 EXPECT_EQ(entry.folder_id, db_value.folder_id); 39 EXPECT_EQ(entry.parent_folder_id, db_value.parent_folder_id); 40 EXPECT_EQ(entry.visual_order, db_value.visual_order); 41 EXPECT_EQ(entry.type, db_value.type); 42 EXPECT_EQ(entry.url_id, db_value.url_id); 43 if (entry.type == StarredEntry::URL) 44 EXPECT_TRUE(entry.url == db_value.url); 45 } 46 47 int GetStarredEntryCount() { 48 DCHECK(db_.is_open()); 49 std::vector<StarredEntry> entries; 50 GetAllStarredEntries(&entries); 51 return static_cast<int>(entries.size()); 52 } 53 54 StarID CreateStarredEntry(StarredEntry* entry) { 55 return StarredURLDatabase::CreateStarredEntry(entry); 56 } 57 58 bool GetStarredEntry(StarID star_id, StarredEntry* entry) { 59 return StarredURLDatabase::GetStarredEntry(star_id, entry); 60 } 61 62 bool EnsureStarredIntegrity() { 63 return StarredURLDatabase::EnsureStarredIntegrity(); 64 } 65 66 private: 67 // Test setup. 68 void SetUp() { 69 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 70 db_file_ = temp_dir_.path().AppendASCII("VisitTest.db"); 71 file_util::Delete(db_file_, false); 72 73 // Copy db file over that contains starred table. 74 FilePath old_history_path; 75 PathService::Get(chrome::DIR_TEST_DATA, &old_history_path); 76 old_history_path = old_history_path.AppendASCII("bookmarks"); 77 old_history_path = old_history_path.Append( 78 FILE_PATH_LITERAL("History_with_empty_starred")); 79 file_util::CopyFile(old_history_path, db_file_); 80 81 EXPECT_TRUE(db_.Open(db_file_)); 82 83 // Initialize the tables for this test. 84 CreateURLTable(false); 85 CreateMainURLIndex(); 86 EnsureStarredIntegrity(); 87 } 88 void TearDown() { 89 db_.Close(); 90 } 91 92 // Provided for URL/StarredURLDatabase. 93 virtual sql::Connection& GetDB() { 94 return db_; 95 } 96 97 ScopedTempDir temp_dir_; 98 FilePath db_file_; 99 sql::Connection db_; 100 }; 101 102 //----------------------------------------------------------------------------- 103 104 TEST_F(StarredURLDatabaseTest, FixOrphanedFolder) { 105 const int initial_count = GetStarredEntryCount(); 106 107 // Create a folder that isn't parented to the other/bookmark folders. 108 StarredEntry g_entry; 109 g_entry.type = StarredEntry::USER_FOLDER; 110 g_entry.parent_folder_id = 100; 111 g_entry.visual_order = 10; 112 g_entry.folder_id = 100; 113 CreateStarredEntry(&g_entry); 114 115 ASSERT_TRUE(EnsureStarredIntegrity()); 116 117 // Make sure no new entries were added. 118 ASSERT_EQ(initial_count + 1, GetStarredEntryCount()); 119 120 // Make sure the folder was moved to the bookmark bar folder. 121 ASSERT_TRUE(GetStarredEntry(g_entry.id, &g_entry)); 122 ASSERT_EQ(HistoryService::kBookmarkBarID, g_entry.parent_folder_id); 123 ASSERT_EQ(0, g_entry.visual_order); 124 } 125 126 TEST_F(StarredURLDatabaseTest, FixOrphanedBookmarks) { 127 const int initial_count = GetStarredEntryCount(); 128 129 // Create two bookmarks that aren't in a random folder no on the bookmark bar. 130 StarredEntry entry1; 131 entry1.parent_folder_id = 100; 132 entry1.visual_order = 10; 133 entry1.url = GURL("http://google.com/1"); 134 CreateStarredEntry(&entry1); 135 136 StarredEntry entry2; 137 entry2.parent_folder_id = 101; 138 entry2.visual_order = 20; 139 entry2.url = GURL("http://google.com/2"); 140 CreateStarredEntry(&entry2); 141 142 ASSERT_TRUE(EnsureStarredIntegrity()); 143 144 // Make sure no new entries were added. 145 ASSERT_EQ(initial_count + 2, GetStarredEntryCount()); 146 147 // Make sure the entries were moved to the bookmark bar and the visual order 148 // order was updated appropriately. 149 ASSERT_TRUE(GetStarredEntry(entry1.id, &entry1)); 150 ASSERT_EQ(HistoryService::kBookmarkBarID, entry1.parent_folder_id); 151 152 ASSERT_TRUE(GetStarredEntry(entry2.id, &entry2)); 153 ASSERT_EQ(HistoryService::kBookmarkBarID, entry2.parent_folder_id); 154 ASSERT_TRUE((entry1.visual_order == 0 && entry2.visual_order == 1) || 155 (entry1.visual_order == 1 && entry2.visual_order == 0)); 156 } 157 158 TEST_F(StarredURLDatabaseTest, FixFolderCycleDepth0) { 159 const int initial_count = GetStarredEntryCount(); 160 161 // Create a folder that is parented to itself. 162 StarredEntry entry1; 163 entry1.folder_id = entry1.parent_folder_id = 100; 164 entry1.visual_order = 10; 165 entry1.type = StarredEntry::USER_FOLDER; 166 CreateStarredEntry(&entry1); 167 168 ASSERT_TRUE(EnsureStarredIntegrity()); 169 170 // Make sure no new entries were added. 171 ASSERT_EQ(initial_count + 1, GetStarredEntryCount()); 172 173 // Make sure the folder were moved to the bookmark bar and the visual order 174 // order was updated appropriately. 175 ASSERT_TRUE(GetStarredEntry(entry1.id, &entry1)); 176 ASSERT_EQ(HistoryService::kBookmarkBarID, entry1.parent_folder_id); 177 ASSERT_EQ(0, entry1.visual_order); 178 } 179 180 TEST_F(StarredURLDatabaseTest, FixFolderCycleDepth1) { 181 const int initial_count = GetStarredEntryCount(); 182 183 StarredEntry entry1; 184 entry1.folder_id = 100; 185 entry1.parent_folder_id = 101; 186 entry1.visual_order = 10; 187 entry1.type = StarredEntry::USER_FOLDER; 188 CreateStarredEntry(&entry1); 189 190 StarredEntry entry2; 191 entry2.folder_id = 101; 192 entry2.parent_folder_id = 100; 193 entry2.visual_order = 11; 194 entry2.type = StarredEntry::USER_FOLDER; 195 CreateStarredEntry(&entry2); 196 197 ASSERT_TRUE(EnsureStarredIntegrity()); 198 199 // Make sure no new entries were added. 200 ASSERT_EQ(initial_count + 2, GetStarredEntryCount()); 201 202 // Because the folders caused a cycle, entry1 is moved the bookmark bar, which 203 // breaks the cycle. 204 ASSERT_TRUE(GetStarredEntry(entry1.id, &entry1)); 205 ASSERT_TRUE(GetStarredEntry(entry2.id, &entry2)); 206 ASSERT_EQ(HistoryService::kBookmarkBarID, entry1.parent_folder_id); 207 ASSERT_EQ(100, entry2.parent_folder_id); 208 ASSERT_EQ(0, entry1.visual_order); 209 ASSERT_EQ(0, entry2.visual_order); 210 } 211 212 TEST_F(StarredURLDatabaseTest, FixVisualOrder) { 213 const int initial_count = GetStarredEntryCount(); 214 215 // Star two urls. 216 StarredEntry entry1; 217 entry1.url = GURL("http://google.com/1"); 218 entry1.parent_folder_id = HistoryService::kBookmarkBarID; 219 entry1.visual_order = 5; 220 CreateStarredEntry(&entry1); 221 222 // Add url2 and star it. 223 StarredEntry entry2; 224 entry2.url = GURL("http://google.com/2"); 225 entry2.parent_folder_id = HistoryService::kBookmarkBarID; 226 entry2.visual_order = 10; 227 CreateStarredEntry(&entry2); 228 229 ASSERT_TRUE(EnsureStarredIntegrity()); 230 231 // Make sure no new entries were added. 232 ASSERT_EQ(initial_count + 2, GetStarredEntryCount()); 233 234 StarredEntry entry; 235 ASSERT_TRUE(GetStarredEntry(entry1.id, &entry)); 236 entry1.visual_order = 0; 237 CompareEntryByID(entry1); 238 239 ASSERT_TRUE(GetStarredEntry(entry2.id, &entry)); 240 entry2.visual_order = 1; 241 CompareEntryByID(entry2); 242 } 243 244 TEST_F(StarredURLDatabaseTest, FixDuplicateFolderIDs) { 245 const int initial_count = GetStarredEntryCount(); 246 247 // Create two folders with the same folder id. 248 StarredEntry entry1; 249 entry1.type = StarredEntry::USER_FOLDER; 250 entry1.folder_id = 10; 251 entry1.parent_folder_id = HistoryService::kBookmarkBarID; 252 CreateStarredEntry(&entry1); 253 StarredEntry entry2 = entry1; 254 CreateStarredEntry(&entry2); 255 256 ASSERT_TRUE(EnsureStarredIntegrity()); 257 258 // Make sure only one folder exists. 259 ASSERT_EQ(initial_count + 1, GetStarredEntryCount()); 260 261 StarredEntry entry; 262 ASSERT_TRUE(GetStarredEntry(entry1.id, &entry) || 263 GetStarredEntry(entry2.id, &entry)); 264 } 265 266 TEST_F(StarredURLDatabaseTest, RemoveStarredEntriesWithEmptyURL) { 267 const int initial_count = GetStarredEntryCount(); 268 269 StarredEntry entry; 270 entry.url = GURL("http://google.com"); 271 entry.title = UTF8ToUTF16("FOO"); 272 entry.parent_folder_id = HistoryService::kBookmarkBarID; 273 274 ASSERT_NE(0, CreateStarredEntry(&entry)); 275 276 // Remove the URL. 277 DeleteURLRow(entry.url_id); 278 279 // Fix up the table. 280 ASSERT_TRUE(EnsureStarredIntegrity()); 281 282 // The entry we just created should have been nuked. 283 ASSERT_EQ(initial_count, GetStarredEntryCount()); 284 } 285 286 } // namespace history 287