OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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 "base/string_util.h" | |
6 #include "chrome/browser/bookmarks/bookmark_bar_model.h" | |
7 #include "chrome/browser/bookmarks/bookmark_codec.h" | |
8 #include "chrome/common/chrome_constants.h" | |
9 #include "chrome/common/chrome_paths.h" | |
10 #include "chrome/test/testing_profile.h" | |
11 #include "chrome/views/tree_node_model.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 class BookmarkBarModelTest : public testing::Test, | |
15 public BookmarkBarModelObserver { | |
16 public: | |
17 struct ObserverDetails { | |
18 ObserverDetails() { | |
19 Set(NULL, NULL, -1, -1); | |
20 } | |
21 | |
22 void Set(BookmarkBarNode* node1, | |
23 BookmarkBarNode* node2, | |
24 int index1, | |
25 int index2) { | |
26 this->node1 = node1; | |
27 this->node2 = node2; | |
28 this->index1 = index1; | |
29 this->index2 = index2; | |
30 } | |
31 | |
32 void AssertEquals(BookmarkBarNode* node1, | |
33 BookmarkBarNode* node2, | |
34 int index1, | |
35 int index2) { | |
36 ASSERT_TRUE(this->node1 == node1); | |
37 ASSERT_TRUE(this->node2 == node2); | |
38 ASSERT_EQ(index1, this->index1); | |
39 ASSERT_EQ(index2, this->index2); | |
40 } | |
41 | |
42 BookmarkBarNode* node1; | |
43 BookmarkBarNode* node2; | |
44 int index1; | |
45 int index2; | |
46 }; | |
47 | |
48 BookmarkBarModelTest() : model(NULL) { | |
49 model.AddObserver(this); | |
50 ClearCounts(); | |
51 } | |
52 | |
53 | |
54 void Loaded(BookmarkBarModel* model) { | |
55 // We never load from the db, so that this should never get invoked. | |
56 NOTREACHED(); | |
57 } | |
58 | |
59 virtual void BookmarkNodeMoved(BookmarkBarModel* model, | |
60 BookmarkBarNode* old_parent, | |
61 int old_index, | |
62 BookmarkBarNode* new_parent, | |
63 int new_index) { | |
64 moved_count++; | |
65 observer_details.Set(old_parent, new_parent, old_index, new_index); | |
66 } | |
67 | |
68 virtual void BookmarkNodeAdded(BookmarkBarModel* model, | |
69 BookmarkBarNode* parent, | |
70 int index) { | |
71 added_count++; | |
72 observer_details.Set(parent, NULL, index, -1); | |
73 } | |
74 | |
75 virtual void BookmarkNodeRemoved(BookmarkBarModel* model, | |
76 BookmarkBarNode* parent, | |
77 int index) { | |
78 removed_count++; | |
79 observer_details.Set(parent, NULL, index, -1); | |
80 } | |
81 | |
82 virtual void BookmarkNodeChanged(BookmarkBarModel* model, | |
83 BookmarkBarNode* node) { | |
84 changed_count++; | |
85 observer_details.Set(node, NULL, -1, -1); | |
86 } | |
87 | |
88 virtual void BookmarkNodeFavIconLoaded(BookmarkBarModel* model, | |
89 BookmarkBarNode* node) { | |
90 // We never attempt to load favicons, so that this method never | |
91 // gets invoked. | |
92 } | |
93 | |
94 void ClearCounts() { | |
95 moved_count = added_count = removed_count = changed_count = 0; | |
96 } | |
97 | |
98 void AssertObserverCount(int added_count, | |
99 int moved_count, | |
100 int removed_count, | |
101 int changed_count) { | |
102 ASSERT_EQ(added_count, this->added_count); | |
103 ASSERT_EQ(moved_count, this->moved_count); | |
104 ASSERT_EQ(removed_count, this->removed_count); | |
105 ASSERT_EQ(changed_count, this->changed_count); | |
106 } | |
107 | |
108 void AssertNodesEqual(BookmarkBarNode* expected, BookmarkBarNode* actual) { | |
109 ASSERT_TRUE(expected); | |
110 ASSERT_TRUE(actual); | |
111 EXPECT_EQ(expected->GetTitle(), actual->GetTitle()); | |
112 EXPECT_EQ(expected->GetType(), actual->GetType()); | |
113 EXPECT_TRUE(expected->date_added() == actual->date_added()); | |
114 if (expected->GetType() == history::StarredEntry::URL) { | |
115 EXPECT_EQ(expected->GetURL(), actual->GetURL()); | |
116 } else { | |
117 EXPECT_TRUE(expected->date_group_modified() == | |
118 actual->date_group_modified()); | |
119 ASSERT_EQ(expected->GetChildCount(), actual->GetChildCount()); | |
120 for (int i = 0; i < expected->GetChildCount(); ++i) | |
121 AssertNodesEqual(expected->GetChild(i), actual->GetChild(i)); | |
122 } | |
123 } | |
124 | |
125 void AssertModelsEqual(BookmarkBarModel* expected, | |
126 BookmarkBarModel* actual) { | |
127 AssertNodesEqual(expected->GetBookmarkBarNode(), | |
128 actual->GetBookmarkBarNode()); | |
129 AssertNodesEqual(expected->other_node(), | |
130 actual->other_node()); | |
131 } | |
132 | |
133 BookmarkBarModel model; | |
134 | |
135 int moved_count; | |
136 | |
137 int added_count; | |
138 | |
139 int removed_count; | |
140 | |
141 int changed_count; | |
142 | |
143 ObserverDetails observer_details; | |
144 }; | |
145 | |
146 TEST_F(BookmarkBarModelTest, InitialState) { | |
147 BookmarkBarNode* bb_node = model.GetBookmarkBarNode(); | |
148 ASSERT_TRUE(bb_node != NULL); | |
149 EXPECT_EQ(0, bb_node->GetChildCount()); | |
150 EXPECT_EQ(history::StarredEntry::BOOKMARK_BAR, bb_node->GetType()); | |
151 | |
152 BookmarkBarNode* other_node = model.other_node(); | |
153 ASSERT_TRUE(other_node != NULL); | |
154 EXPECT_EQ(0, other_node->GetChildCount()); | |
155 EXPECT_EQ(history::StarredEntry::OTHER, other_node->GetType()); | |
156 | |
157 EXPECT_TRUE(bb_node->id() != other_node->id()); | |
158 } | |
159 | |
160 TEST_F(BookmarkBarModelTest, AddURL) { | |
161 BookmarkBarNode* root = model.GetBookmarkBarNode(); | |
162 const std::wstring title(L"foo"); | |
163 const GURL url("http://foo.com"); | |
164 | |
165 BookmarkBarNode* new_node = model.AddURL(root, 0, title, url); | |
166 AssertObserverCount(1, 0, 0, 0); | |
167 observer_details.AssertEquals(root, NULL, 0, -1); | |
168 | |
169 ASSERT_EQ(1, root->GetChildCount()); | |
170 ASSERT_EQ(title, new_node->GetTitle()); | |
171 ASSERT_TRUE(url == new_node->GetURL()); | |
172 ASSERT_EQ(history::StarredEntry::URL, new_node->GetType()); | |
173 ASSERT_TRUE(new_node == model.GetNodeByURL(url)); | |
174 | |
175 EXPECT_TRUE(new_node->id() != root->id() && | |
176 new_node->id() != model.other_node()->id()); | |
177 } | |
178 | |
179 TEST_F(BookmarkBarModelTest, AddGroup) { | |
180 BookmarkBarNode* root = model.GetBookmarkBarNode(); | |
181 const std::wstring title(L"foo"); | |
182 | |
183 BookmarkBarNode* new_node = model.AddGroup(root, 0, title); | |
184 AssertObserverCount(1, 0, 0, 0); | |
185 observer_details.AssertEquals(root, NULL, 0, -1); | |
186 | |
187 ASSERT_EQ(1, root->GetChildCount()); | |
188 ASSERT_EQ(title, new_node->GetTitle()); | |
189 ASSERT_EQ(history::StarredEntry::USER_GROUP, new_node->GetType()); | |
190 | |
191 EXPECT_TRUE(new_node->id() != root->id() && | |
192 new_node->id() != model.other_node()->id()); | |
193 | |
194 // Add another group, just to make sure group_ids are incremented correctly. | |
195 ClearCounts(); | |
196 BookmarkBarNode* new_node2 = model.AddGroup(root, 0, title); | |
197 AssertObserverCount(1, 0, 0, 0); | |
198 observer_details.AssertEquals(root, NULL, 0, -1); | |
199 } | |
200 | |
201 TEST_F(BookmarkBarModelTest, RemoveURL) { | |
202 BookmarkBarNode* root = model.GetBookmarkBarNode(); | |
203 const std::wstring title(L"foo"); | |
204 const GURL url("http://foo.com"); | |
205 BookmarkBarNode* new_node = model.AddURL(root, 0, title, url); | |
206 ClearCounts(); | |
207 | |
208 model.Remove(root, 0); | |
209 ASSERT_EQ(0, root->GetChildCount()); | |
210 AssertObserverCount(0, 0, 1, 0); | |
211 observer_details.AssertEquals(root, NULL, 0, -1); | |
212 | |
213 // Make sure there is no mapping for the URL. | |
214 ASSERT_TRUE(model.GetNodeByURL(url) == NULL); | |
215 } | |
216 | |
217 TEST_F(BookmarkBarModelTest, RemoveGroup) { | |
218 BookmarkBarNode* root = model.GetBookmarkBarNode(); | |
219 BookmarkBarNode* group = model.AddGroup(root, 0, L"foo"); | |
220 | |
221 ClearCounts(); | |
222 | |
223 // Add a URL as a child. | |
224 const std::wstring title(L"foo"); | |
225 const GURL url("http://foo.com"); | |
226 BookmarkBarNode* new_node = model.AddURL(group, 0, title, url); | |
227 | |
228 ClearCounts(); | |
229 | |
230 // Now remove the group. | |
231 model.Remove(root, 0); | |
232 ASSERT_EQ(0, root->GetChildCount()); | |
233 AssertObserverCount(0, 0, 1, 0); | |
234 observer_details.AssertEquals(root, NULL, 0, -1); | |
235 | |
236 // Make sure there is no mapping for the URL. | |
237 ASSERT_TRUE(model.GetNodeByURL(url) == NULL); | |
238 } | |
239 | |
240 TEST_F(BookmarkBarModelTest, SetTitle) { | |
241 BookmarkBarNode* root = model.GetBookmarkBarNode(); | |
242 std::wstring title(L"foo"); | |
243 const GURL url("http://foo.com"); | |
244 BookmarkBarNode* node = model.AddURL(root, 0, title, url); | |
245 | |
246 ClearCounts(); | |
247 | |
248 title = L"foo2"; | |
249 model.SetTitle(node, title); | |
250 AssertObserverCount(0, 0, 0, 1); | |
251 observer_details.AssertEquals(node, NULL, -1, -1); | |
252 EXPECT_EQ(title, node->GetTitle()); | |
253 } | |
254 | |
255 TEST_F(BookmarkBarModelTest, Move) { | |
256 BookmarkBarNode* root = model.GetBookmarkBarNode(); | |
257 std::wstring title(L"foo"); | |
258 const GURL url("http://foo.com"); | |
259 BookmarkBarNode* node = model.AddURL(root, 0, title, url); | |
260 BookmarkBarNode* group1 = model.AddGroup(root, 0, L"foo"); | |
261 ClearCounts(); | |
262 | |
263 model.Move(node, group1, 0); | |
264 | |
265 AssertObserverCount(0, 1, 0, 0); | |
266 observer_details.AssertEquals(root, group1, 1, 0); | |
267 EXPECT_TRUE(group1 == node->GetParent()); | |
268 EXPECT_EQ(1, root->GetChildCount()); | |
269 EXPECT_EQ(group1, root->GetChild(0)); | |
270 EXPECT_EQ(1, group1->GetChildCount()); | |
271 EXPECT_EQ(node, group1->GetChild(0)); | |
272 | |
273 // And remove the group. | |
274 ClearCounts(); | |
275 model.Remove(root, 0); | |
276 AssertObserverCount(0, 0, 1, 0); | |
277 observer_details.AssertEquals(root, NULL, 0, -1); | |
278 EXPECT_TRUE(model.GetNodeByURL(url) == NULL); | |
279 EXPECT_EQ(0, root->GetChildCount()); | |
280 } | |
281 | |
282 // Tests that adding a URL to a folder updates the last modified time. | |
283 TEST_F(BookmarkBarModelTest, ParentForNewNodes) { | |
284 ASSERT_EQ(model.GetBookmarkBarNode(), model.GetParentForNewNodes()); | |
285 | |
286 const std::wstring title(L"foo"); | |
287 const GURL url("http://foo.com"); | |
288 | |
289 BookmarkBarNode* new_node = | |
290 model.AddURL(model.other_node(), 0, title, url); | |
291 | |
292 ASSERT_EQ(model.other_node(), model.GetParentForNewNodes()); | |
293 } | |
294 | |
295 // Make sure recently modified stays in sync when adding a URL. | |
296 TEST_F(BookmarkBarModelTest, MostRecentlyModifiedGroups) { | |
297 // Add a group. | |
298 BookmarkBarNode* group = model.AddGroup(model.other_node(), 0, L"foo"); | |
299 // Add a URL to it. | |
300 model.AddURL(group, 0, L"blah", GURL("http://foo.com")); | |
301 | |
302 // Make sure group is in the most recently modified. | |
303 std::vector<BookmarkBarNode*> most_recent_groups = | |
304 model.GetMostRecentlyModifiedGroups(1); | |
305 ASSERT_EQ(1, most_recent_groups.size()); | |
306 ASSERT_EQ(group, most_recent_groups[0]); | |
307 | |
308 // Nuke the group and do another fetch, making sure group isn't in the | |
309 // returned list. | |
310 model.Remove(group->GetParent(), 0); | |
311 most_recent_groups = model.GetMostRecentlyModifiedGroups(1); | |
312 ASSERT_EQ(1, most_recent_groups.size()); | |
313 ASSERT_TRUE(most_recent_groups[0] != group); | |
314 } | |
315 | |
316 // Make sure MostRecentlyAddedEntries stays in sync. | |
317 TEST_F(BookmarkBarModelTest, MostRecentlyAddedEntries) { | |
318 // Add a couple of nodes such that the following holds for the time of the | |
319 // nodes: n1 > n2 > n3 > n4. | |
320 Time base_time = Time::Now(); | |
321 BookmarkBarNode* n1 = model.AddURL( | |
322 model.GetBookmarkBarNode(), 0, L"blah", GURL("http://foo.com/0")); | |
323 BookmarkBarNode* n2 = model.AddURL( | |
324 model.GetBookmarkBarNode(), 1, L"blah", GURL("http://foo.com/1")); | |
325 BookmarkBarNode* n3 = model.AddURL( | |
326 model.GetBookmarkBarNode(), 2, L"blah", GURL("http://foo.com/2")); | |
327 BookmarkBarNode* n4 = model.AddURL( | |
328 model.GetBookmarkBarNode(), 3, L"blah", GURL("http://foo.com/3")); | |
329 n1->date_added_ = base_time + TimeDelta::FromDays(4); | |
330 n2->date_added_ = base_time + TimeDelta::FromDays(3); | |
331 n3->date_added_ = base_time + TimeDelta::FromDays(2); | |
332 n4->date_added_ = base_time + TimeDelta::FromDays(1); | |
333 | |
334 // Make sure order is honored. | |
335 std::vector<BookmarkBarNode*> recently_added; | |
336 model.GetMostRecentlyAddedEntries(2, &recently_added); | |
337 ASSERT_EQ(2, recently_added.size()); | |
338 ASSERT_TRUE(n1 == recently_added[0]); | |
339 ASSERT_TRUE(n2 == recently_added[1]); | |
340 | |
341 // swap 1 and 2, then check again. | |
342 recently_added.clear(); | |
343 std::swap(n1->date_added_, n2->date_added_); | |
344 model.GetMostRecentlyAddedEntries(4, &recently_added); | |
345 ASSERT_EQ(4, recently_added.size()); | |
346 ASSERT_TRUE(n2 == recently_added[0]); | |
347 ASSERT_TRUE(n1 == recently_added[1]); | |
348 ASSERT_TRUE(n3 == recently_added[2]); | |
349 ASSERT_TRUE(n4 == recently_added[3]); | |
350 } | |
351 | |
352 // Makes sure GetBookmarksMatchingText works. | |
353 TEST_F(BookmarkBarModelTest, GetBookmarksMatchingText) { | |
354 // Add two urls with titles 'blah' and 'x' and one folder with the title | |
355 // 'blah'. | |
356 BookmarkBarNode* n1 = model.AddURL( | |
357 model.GetBookmarkBarNode(), 0, L"blah", GURL("http://foo.com/0")); | |
358 BookmarkBarNode* n2 = model.AddURL( | |
359 model.GetBookmarkBarNode(), 1, L"x", GURL("http://foo.com/1")); | |
360 model.AddGroup(model.GetBookmarkBarNode(), 2, L"blah"); | |
361 | |
362 // Make sure we don't get back the folder. | |
363 std::vector<BookmarkBarModel::TitleMatch> results; | |
364 model.GetBookmarksMatchingText(L"blah", 2, &results); | |
365 ASSERT_EQ(1U, results.size()); | |
366 EXPECT_EQ(n1, results[0].node); | |
367 results.clear(); | |
368 | |
369 model.GetBookmarksMatchingText(L"x", 2, &results); | |
370 ASSERT_EQ(1U, results.size()); | |
371 EXPECT_EQ(n2, results[0].node); | |
372 } | |
373 | |
374 namespace { | |
375 | |
376 // See comment in PopulateNodeFromString. | |
377 typedef ChromeViews::TreeNodeWithValue<history::StarredEntry::Type> TestNode; | |
378 | |
379 // Does the work of PopulateNodeFromString. index gives the index of the current | |
380 // element in description to process. | |
381 static void PopulateNodeImpl(const std::vector<std::wstring>& description, | |
382 size_t* index, | |
383 TestNode* parent) { | |
384 while (*index < description.size()) { | |
385 const std::wstring& element = description[*index]; | |
386 (*index)++; | |
387 if (element == L"[") { | |
388 // Create a new group and recurse to add all the children. | |
389 // Groups are given a unique named by way of an ever increasing integer | |
390 // value. The groups need not have a name, but one is assigned to help | |
391 // in debugging. | |
392 static int next_group_id = 1; | |
393 TestNode* new_node = | |
394 new TestNode(IntToWString(next_group_id++), | |
395 history::StarredEntry::USER_GROUP); | |
396 parent->Add(parent->GetChildCount(), new_node); | |
397 PopulateNodeImpl(description, index, new_node); | |
398 } else if (element == L"]") { | |
399 // End the current group. | |
400 return; | |
401 } else { | |
402 // Add a new URL. | |
403 | |
404 // All tokens must be space separated. If there is a [ or ] in the name it | |
405 // likely means a space was forgotten. | |
406 DCHECK(element.find('[') == std::string::npos); | |
407 DCHECK(element.find(']') == std::string::npos); | |
408 parent->Add(parent->GetChildCount(), | |
409 new TestNode(element, history::StarredEntry::URL)); | |
410 } | |
411 } | |
412 } | |
413 | |
414 // Creates and adds nodes to parent based on description. description consists | |
415 // of the following tokens (all space separated): | |
416 // [ : creates a new USER_GROUP node. All elements following the [ until the | |
417 // next balanced ] is encountered are added as children to the node. | |
418 // ] : closes the last group created by [ so that any further nodes are added | |
419 // to the current groups parent. | |
420 // text: creates a new URL node. | |
421 // For example, "a [b] c" creates the following nodes: | |
422 // a 1 c | |
423 // | | |
424 // b | |
425 // In words: a node of type URL with the title a, followed by a group node with | |
426 // the title 1 having the single child of type url with name b, followed by | |
427 // the url node with the title c. | |
428 // | |
429 // NOTE: each name must be unique, and groups are assigned a unique title by way | |
430 // of an increasing integer. | |
431 static void PopulateNodeFromString(const std::wstring& description, | |
432 TestNode* parent) { | |
433 std::vector<std::wstring> elements; | |
434 size_t index = 0; | |
435 SplitStringAlongWhitespace(description, &elements); | |
436 PopulateNodeImpl(elements, &index, parent); | |
437 } | |
438 | |
439 // Populates the BookmarkBarNode with the children of parent. | |
440 static void PopulateBookmarkBarNode(TestNode* parent, | |
441 BookmarkBarModel* model, | |
442 BookmarkBarNode* bb_node) { | |
443 for (int i = 0; i < parent->GetChildCount(); ++i) { | |
444 TestNode* child = parent->GetChild(i); | |
445 if (child->value == history::StarredEntry::USER_GROUP) { | |
446 BookmarkBarNode* new_bb_node = | |
447 model->AddGroup(bb_node, i, child->GetTitle()); | |
448 PopulateBookmarkBarNode(child, model, new_bb_node); | |
449 } else { | |
450 model->AddURL(bb_node, i, child->GetTitle(), | |
451 GURL("http://" + WideToASCII(child->GetTitle()))); | |
452 } | |
453 } | |
454 } | |
455 | |
456 } // namespace | |
457 | |
458 // Test class that creates a BookmarkBarModel with a real history backend. | |
459 class BookmarkBarModelTestWithProfile : public testing::Test, | |
460 public BookmarkBarModelObserver { | |
461 public: | |
462 virtual void SetUp() { | |
463 } | |
464 | |
465 virtual void TearDown() { | |
466 profile_.reset(NULL); | |
467 } | |
468 | |
469 // The profile. | |
470 scoped_ptr<TestingProfile> profile_; | |
471 | |
472 protected: | |
473 // Verifies the contents of the bookmark bar node match the contents of the | |
474 // TestNode. | |
475 void VerifyModelMatchesNode(TestNode* expected, BookmarkBarNode* actual) { | |
476 ASSERT_EQ(expected->GetChildCount(), actual->GetChildCount()); | |
477 for (int i = 0; i < expected->GetChildCount(); ++i) { | |
478 TestNode* expected_child = expected->GetChild(i); | |
479 BookmarkBarNode* actual_child = actual->GetChild(i); | |
480 ASSERT_EQ(expected_child->GetTitle(), actual_child->GetTitle()); | |
481 if (expected_child->value == history::StarredEntry::USER_GROUP) { | |
482 ASSERT_TRUE(actual_child->GetType() == | |
483 history::StarredEntry::USER_GROUP); | |
484 // Recurse throught children. | |
485 VerifyModelMatchesNode(expected_child, actual_child); | |
486 if (HasFatalFailure()) | |
487 return; | |
488 } else { | |
489 // No need to check the URL, just the title is enough. | |
490 ASSERT_TRUE(actual_child->GetType() == | |
491 history::StarredEntry::URL); | |
492 } | |
493 } | |
494 } | |
495 | |
496 void BlockTillBookmarkModelLoaded() { | |
497 bb_model_ = profile_->GetBookmarkBarModel(); | |
498 if (!bb_model_->IsLoaded()) | |
499 BlockTillLoaded(bb_model_); | |
500 else | |
501 bb_model_->AddObserver(this); | |
502 } | |
503 | |
504 // Destroys the current profile, creates a new one and creates the history | |
505 // service. | |
506 void RecreateProfile() { | |
507 // Need to shutdown the old one before creating a new one. | |
508 profile_.reset(NULL); | |
509 profile_.reset(new TestingProfile()); | |
510 profile_->CreateHistoryService(true); | |
511 } | |
512 | |
513 BookmarkBarModel* bb_model_; | |
514 | |
515 private: | |
516 // Blocks until the BookmarkBarModel has finished loading. | |
517 void BlockTillLoaded(BookmarkBarModel* model) { | |
518 model->AddObserver(this); | |
519 MessageLoop::current()->Run(); | |
520 } | |
521 | |
522 // BookmarkBarModelObserver methods. | |
523 virtual void Loaded(BookmarkBarModel* model) { | |
524 // Balances the call in BlockTillLoaded. | |
525 MessageLoop::current()->Quit(); | |
526 } | |
527 virtual void BookmarkNodeMoved(BookmarkBarModel* model, | |
528 BookmarkBarNode* old_parent, | |
529 int old_index, | |
530 BookmarkBarNode* new_parent, | |
531 int new_index) {} | |
532 virtual void BookmarkNodeAdded(BookmarkBarModel* model, | |
533 BookmarkBarNode* parent, | |
534 int index) {} | |
535 virtual void BookmarkNodeRemoved(BookmarkBarModel* model, | |
536 BookmarkBarNode* parent, | |
537 int index) {} | |
538 virtual void BookmarkNodeChanged(BookmarkBarModel* model, | |
539 BookmarkBarNode* node) {} | |
540 virtual void BookmarkNodeFavIconLoaded(BookmarkBarModel* model, | |
541 BookmarkBarNode* node) {} | |
542 | |
543 MessageLoopForUI message_loop_; | |
544 }; | |
545 | |
546 // Creates a set of nodes in the bookmark bar model, then recreates the | |
547 // bookmark bar model which triggers loading from the db and checks the loaded | |
548 // structure to make sure it is what we first created. | |
549 TEST_F(BookmarkBarModelTestWithProfile, CreateAndRestore) { | |
550 struct TestData { | |
551 // Structure of the children of the bookmark bar model node. | |
552 const std::wstring bbn_contents; | |
553 // Structure of the children of the other node. | |
554 const std::wstring other_contents; | |
555 } data[] = { | |
556 // See PopulateNodeFromString for a description of these strings. | |
557 { L"", L"" }, | |
558 { L"a", L"b" }, | |
559 { L"a [ b ]", L"" }, | |
560 { L"", L"[ b ] a [ c [ d e [ f ] ] ]" }, | |
561 { L"a [ b ]", L"" }, | |
562 { L"a b c [ d e [ f ] ]", L"g h i [ j k [ l ] ]"}, | |
563 }; | |
564 for (int i = 0; i < arraysize(data); ++i) { | |
565 // Recreate the profile. We need to reset with NULL first so that the last | |
566 // HistoryService releases the locks on the files it creates and we can | |
567 // delete them. | |
568 profile_.reset(NULL); | |
569 profile_.reset(new TestingProfile()); | |
570 profile_->CreateBookmarkBarModel(true); | |
571 profile_->CreateHistoryService(true); | |
572 BlockTillBookmarkModelLoaded(); | |
573 | |
574 TestNode bbn; | |
575 PopulateNodeFromString(data[i].bbn_contents, &bbn); | |
576 PopulateBookmarkBarNode(&bbn, bb_model_, bb_model_->GetBookmarkBarNode()); | |
577 | |
578 TestNode other; | |
579 PopulateNodeFromString(data[i].other_contents, &other); | |
580 PopulateBookmarkBarNode(&other, bb_model_, bb_model_->other_node()); | |
581 | |
582 profile_->CreateBookmarkBarModel(false); | |
583 BlockTillBookmarkModelLoaded(); | |
584 | |
585 VerifyModelMatchesNode(&bbn, bb_model_->GetBookmarkBarNode()); | |
586 VerifyModelMatchesNode(&other, bb_model_->other_node()); | |
587 } | |
588 } | |
589 | |
590 // Test class that creates a BookmarkBarModel with a real history backend. | |
591 class BookmarkBarModelTestWithProfile2 : | |
592 public BookmarkBarModelTestWithProfile { | |
593 public: | |
594 virtual void SetUp() { | |
595 profile_.reset(new TestingProfile()); | |
596 } | |
597 | |
598 protected: | |
599 // Verifies the state of the model matches that of the state in the saved | |
600 // history file. | |
601 void VerifyExpectedState() { | |
602 // Here's the structure we expect: | |
603 // bbn | |
604 // www.google.com - Google | |
605 // F1 | |
606 // http://www.google.com/intl/en/ads/ - Google Advertising | |
607 // F11 | |
608 // http://www.google.com/services/ - Google Business Solutions | |
609 // other | |
610 // OF1 | |
611 // http://www.google.com/intl/en/about.html - About Google | |
612 BookmarkBarNode* bbn = bb_model_->GetBookmarkBarNode(); | |
613 ASSERT_EQ(2, bbn->GetChildCount()); | |
614 | |
615 BookmarkBarNode* child = bbn->GetChild(0); | |
616 ASSERT_EQ(history::StarredEntry::URL, child->GetType()); | |
617 ASSERT_EQ(L"Google", child->GetTitle()); | |
618 ASSERT_TRUE(child->GetURL() == GURL("http://www.google.com")); | |
619 | |
620 child = bbn->GetChild(1); | |
621 ASSERT_TRUE(child->is_folder()); | |
622 ASSERT_EQ(L"F1", child->GetTitle()); | |
623 ASSERT_EQ(2, child->GetChildCount()); | |
624 | |
625 BookmarkBarNode* parent = child; | |
626 child = parent->GetChild(0); | |
627 ASSERT_EQ(history::StarredEntry::URL, child->GetType()); | |
628 ASSERT_EQ(L"Google Advertising", child->GetTitle()); | |
629 ASSERT_TRUE(child->GetURL() == GURL("http://www.google.com/intl/en/ads/")); | |
630 | |
631 child = parent->GetChild(1); | |
632 ASSERT_TRUE(child->is_folder()); | |
633 ASSERT_EQ(L"F11", child->GetTitle()); | |
634 ASSERT_EQ(1, child->GetChildCount()); | |
635 | |
636 parent = child; | |
637 child = parent->GetChild(0); | |
638 ASSERT_EQ(history::StarredEntry::URL, child->GetType()); | |
639 ASSERT_EQ(L"Google Business Solutions", child->GetTitle()); | |
640 ASSERT_TRUE(child->GetURL() == GURL("http://www.google.com/services/")); | |
641 | |
642 parent = bb_model_->other_node(); | |
643 ASSERT_EQ(2, parent->GetChildCount()); | |
644 | |
645 child = parent->GetChild(0); | |
646 ASSERT_TRUE(child->is_folder()); | |
647 ASSERT_EQ(L"OF1", child->GetTitle()); | |
648 ASSERT_EQ(0, child->GetChildCount()); | |
649 | |
650 child = parent->GetChild(1); | |
651 ASSERT_EQ(history::StarredEntry::URL, child->GetType()); | |
652 ASSERT_EQ(L"About Google", child->GetTitle()); | |
653 ASSERT_TRUE(child->GetURL() == | |
654 GURL("http://www.google.com/intl/en/about.html")); | |
655 | |
656 ASSERT_TRUE(bb_model_->GetNodeByURL(GURL("http://www.google.com")) != NULL); | |
657 } | |
658 }; | |
659 | |
660 // Tests migrating bookmarks from db into file. This copies an old history db | |
661 // file containing bookmarks and make sure they are loaded correctly and | |
662 // persisted correctly. | |
663 TEST_F(BookmarkBarModelTestWithProfile2, MigrateFromDBToFileTest) { | |
664 // Copy db file over that contains starred table. | |
665 std::wstring old_history_path; | |
666 PathService::Get(chrome::DIR_TEST_DATA, &old_history_path); | |
667 file_util::AppendToPath(&old_history_path, L"bookmarks"); | |
668 file_util::AppendToPath(&old_history_path, L"History_with_starred"); | |
669 std::wstring new_history_path = profile_->GetPath(); | |
670 file_util::Delete(new_history_path, true); | |
671 file_util::CreateDirectory(new_history_path); | |
672 file_util::AppendToPath(&new_history_path, chrome::kHistoryFilename); | |
673 file_util::CopyFile(old_history_path, new_history_path); | |
674 | |
675 // Create the history service making sure it doesn't blow away the file we | |
676 // just copied. | |
677 profile_->CreateHistoryService(false); | |
678 profile_->CreateBookmarkBarModel(true); | |
679 BlockTillBookmarkModelLoaded(); | |
680 | |
681 // Make sure we loaded OK. | |
682 VerifyExpectedState(); | |
683 if (HasFatalFailure()) | |
684 return; | |
685 | |
686 // Create again. This time we shouldn't load from history at all. | |
687 profile_->CreateBookmarkBarModel(false); | |
688 BlockTillBookmarkModelLoaded(); | |
689 | |
690 // Make sure we loaded OK. | |
691 VerifyExpectedState(); | |
692 if (HasFatalFailure()) | |
693 return; | |
694 | |
695 // Recreate the history service (with a clean db). Do this just to make sure | |
696 // we're loading correctly from the bookmarks file. | |
697 profile_->CreateHistoryService(true); | |
698 profile_->CreateBookmarkBarModel(false); | |
699 BlockTillBookmarkModelLoaded(); | |
700 VerifyExpectedState(); | |
701 } | |
702 | |
703 // Simple test that removes a bookmark. This test exercises the code paths in | |
704 // History that block till bookmark bar model is loaded. | |
705 TEST_F(BookmarkBarModelTestWithProfile2, RemoveNotification) { | |
706 profile_->CreateHistoryService(false); | |
707 profile_->CreateBookmarkBarModel(true); | |
708 BlockTillBookmarkModelLoaded(); | |
709 | |
710 // Add a URL. | |
711 GURL url("http://www.google.com"); | |
712 bb_model_->SetURLStarred(url, std::wstring(), true); | |
713 | |
714 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->AddPage( | |
715 url, NULL, 1, GURL(), PageTransition::TYPED, | |
716 HistoryService::RedirectList()); | |
717 | |
718 // This won't actually delete the URL, rather it'll empty out the visits. | |
719 // This triggers blocking on the BookmarkBarModel. | |
720 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->DeleteURL(url); | |
721 } | |
OLD | NEW |