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:
StarredURLDatabaseTest()22 StarredURLDatabaseTest() {
23 }
24
AddPage(const GURL & url)25 void AddPage(const GURL& url) {
26 URLRow row(url);
27 row.set_visit_count(1);
28 EXPECT_TRUE(AddURL(row));
29 }
30
CompareEntryByID(const StarredEntry & entry)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
GetStarredEntryCount()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
CreateStarredEntry(StarredEntry * entry)54 StarID CreateStarredEntry(StarredEntry* entry) {
55 return StarredURLDatabase::CreateStarredEntry(entry);
56 }
57
GetStarredEntry(StarID star_id,StarredEntry * entry)58 bool GetStarredEntry(StarID star_id, StarredEntry* entry) {
59 return StarredURLDatabase::GetStarredEntry(star_id, entry);
60 }
61
EnsureStarredIntegrity()62 bool EnsureStarredIntegrity() {
63 return StarredURLDatabase::EnsureStarredIntegrity();
64 }
65
66 private:
67 // Test setup.
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 }
TearDown()88 void TearDown() {
89 db_.Close();
90 }
91
92 // Provided for URL/StarredURLDatabase.
GetDB()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
TEST_F(StarredURLDatabaseTest,FixOrphanedFolder)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
TEST_F(StarredURLDatabaseTest,FixOrphanedBookmarks)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
TEST_F(StarredURLDatabaseTest,FixFolderCycleDepth0)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
TEST_F(StarredURLDatabaseTest,FixFolderCycleDepth1)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
TEST_F(StarredURLDatabaseTest,FixVisualOrder)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
TEST_F(StarredURLDatabaseTest,FixDuplicateFolderIDs)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
TEST_F(StarredURLDatabaseTest,RemoveStarredEntriesWithEmptyURL)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