| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <set> | 5 #include <set> |
| 6 | 6 |
| 7 #include "app/tree_node_iterator.h" | 7 #include "app/tree_node_iterator.h" |
| 8 #include "app/tree_node_model.h" | 8 #include "app/tree_node_model.h" |
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 ClearCounts(); | 308 ClearCounts(); |
| 309 model.Remove(root, 0); | 309 model.Remove(root, 0); |
| 310 AssertObserverCount(0, 0, 1, 0, 0); | 310 AssertObserverCount(0, 0, 1, 0, 0); |
| 311 observer_details.AssertEquals(root, NULL, 0, -1); | 311 observer_details.AssertEquals(root, NULL, 0, -1); |
| 312 EXPECT_TRUE(model.GetMostRecentlyAddedNodeForURL(url) == NULL); | 312 EXPECT_TRUE(model.GetMostRecentlyAddedNodeForURL(url) == NULL); |
| 313 EXPECT_EQ(0, root->GetChildCount()); | 313 EXPECT_EQ(0, root->GetChildCount()); |
| 314 } | 314 } |
| 315 | 315 |
| 316 TEST_F(BookmarkModelTest, Copy) { | 316 TEST_F(BookmarkModelTest, Copy) { |
| 317 const BookmarkNode* root = model.GetBookmarkBarNode(); | 317 const BookmarkNode* root = model.GetBookmarkBarNode(); |
| 318 static const std::wstring model_string(L"a 1:[ b c ] d 2:[ e f g ] h "); | 318 static const std::string model_string("a 1:[ b c ] d 2:[ e f g ] h "); |
| 319 model_test_utils::AddNodesFromModelString(model, root, model_string); | 319 model_test_utils::AddNodesFromModelString(model, root, model_string); |
| 320 | 320 |
| 321 // Validate initial model. | 321 // Validate initial model. |
| 322 std::wstring actualModelString = model_test_utils::ModelStringFromNode(root); | 322 std::string actualModelString = model_test_utils::ModelStringFromNode(root); |
| 323 EXPECT_EQ(model_string, actualModelString); | 323 EXPECT_EQ(model_string, actualModelString); |
| 324 | 324 |
| 325 // Copy 'd' to be after '1:b': URL item from bar to folder. | 325 // Copy 'd' to be after '1:b': URL item from bar to folder. |
| 326 const BookmarkNode* nodeToCopy = root->GetChild(2); | 326 const BookmarkNode* nodeToCopy = root->GetChild(2); |
| 327 const BookmarkNode* destination = root->GetChild(1); | 327 const BookmarkNode* destination = root->GetChild(1); |
| 328 model.Copy(nodeToCopy, destination, 1); | 328 model.Copy(nodeToCopy, destination, 1); |
| 329 actualModelString = model_test_utils::ModelStringFromNode(root); | 329 actualModelString = model_test_utils::ModelStringFromNode(root); |
| 330 EXPECT_EQ(L"a 1:[ b d c ] d 2:[ e f g ] h ", actualModelString); | 330 EXPECT_EQ("a 1:[ b d c ] d 2:[ e f g ] h ", actualModelString); |
| 331 | 331 |
| 332 // Copy '1:d' to be after 'a': URL item from folder to bar. | 332 // Copy '1:d' to be after 'a': URL item from folder to bar. |
| 333 const BookmarkNode* group = root->GetChild(1); | 333 const BookmarkNode* group = root->GetChild(1); |
| 334 nodeToCopy = group->GetChild(1); | 334 nodeToCopy = group->GetChild(1); |
| 335 model.Copy(nodeToCopy, root, 1); | 335 model.Copy(nodeToCopy, root, 1); |
| 336 actualModelString = model_test_utils::ModelStringFromNode(root); | 336 actualModelString = model_test_utils::ModelStringFromNode(root); |
| 337 EXPECT_EQ(L"a d 1:[ b d c ] d 2:[ e f g ] h ", actualModelString); | 337 EXPECT_EQ("a d 1:[ b d c ] d 2:[ e f g ] h ", actualModelString); |
| 338 | 338 |
| 339 // Copy '1' to be after '2:e': Folder from bar to folder. | 339 // Copy '1' to be after '2:e': Folder from bar to folder. |
| 340 nodeToCopy = root->GetChild(2); | 340 nodeToCopy = root->GetChild(2); |
| 341 destination = root->GetChild(4); | 341 destination = root->GetChild(4); |
| 342 model.Copy(nodeToCopy, destination, 1); | 342 model.Copy(nodeToCopy, destination, 1); |
| 343 actualModelString = model_test_utils::ModelStringFromNode(root); | 343 actualModelString = model_test_utils::ModelStringFromNode(root); |
| 344 EXPECT_EQ(L"a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f g ] h ", actualModelString); | 344 EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f g ] h ", actualModelString); |
| 345 | 345 |
| 346 // Copy '2:1' to be after '2:f': Folder within same folder. | 346 // Copy '2:1' to be after '2:f': Folder within same folder. |
| 347 group = root->GetChild(4); | 347 group = root->GetChild(4); |
| 348 nodeToCopy = group->GetChild(1); | 348 nodeToCopy = group->GetChild(1); |
| 349 model.Copy(nodeToCopy, group, 3); | 349 model.Copy(nodeToCopy, group, 3); |
| 350 actualModelString = model_test_utils::ModelStringFromNode(root); | 350 actualModelString = model_test_utils::ModelStringFromNode(root); |
| 351 EXPECT_EQ(L"a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h ", | 351 EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h ", |
| 352 actualModelString); | 352 actualModelString); |
| 353 | 353 |
| 354 // Copy first 'd' to be after 'h': URL item within the bar. | 354 // Copy first 'd' to be after 'h': URL item within the bar. |
| 355 nodeToCopy = root->GetChild(1); | 355 nodeToCopy = root->GetChild(1); |
| 356 model.Copy(nodeToCopy, root, 6); | 356 model.Copy(nodeToCopy, root, 6); |
| 357 actualModelString = model_test_utils::ModelStringFromNode(root); | 357 actualModelString = model_test_utils::ModelStringFromNode(root); |
| 358 EXPECT_EQ(L"a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ", | 358 EXPECT_EQ("a d 1:[ b d c ] d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ", |
| 359 actualModelString); | 359 actualModelString); |
| 360 | 360 |
| 361 // Copy '2' to be after 'a': Folder within the bar. | 361 // Copy '2' to be after 'a': Folder within the bar. |
| 362 nodeToCopy = root->GetChild(4); | 362 nodeToCopy = root->GetChild(4); |
| 363 model.Copy(nodeToCopy, root, 1); | 363 model.Copy(nodeToCopy, root, 1); |
| 364 actualModelString = model_test_utils::ModelStringFromNode(root); | 364 actualModelString = model_test_utils::ModelStringFromNode(root); |
| 365 EXPECT_EQ(L"a 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] d 1:[ b d c ] " | 365 EXPECT_EQ("a 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] d 1:[ b d c ] " |
| 366 L"d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ", | 366 "d 2:[ e 1:[ b d c ] f 1:[ b d c ] g ] h d ", |
| 367 actualModelString); | 367 actualModelString); |
| 368 } | 368 } |
| 369 | 369 |
| 370 // Tests that adding a URL to a folder updates the last modified time. | 370 // Tests that adding a URL to a folder updates the last modified time. |
| 371 TEST_F(BookmarkModelTest, ParentForNewNodes) { | 371 TEST_F(BookmarkModelTest, ParentForNewNodes) { |
| 372 ASSERT_EQ(model.GetBookmarkBarNode(), model.GetParentForNewNodes()); | 372 ASSERT_EQ(model.GetBookmarkBarNode(), model.GetParentForNewNodes()); |
| 373 | 373 |
| 374 const string16 title(ASCIIToUTF16("foo")); | 374 const string16 title(ASCIIToUTF16("foo")); |
| 375 const GURL url("http://foo.com"); | 375 const GURL url("http://foo.com"); |
| 376 | 376 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 EXPECT_TRUE(url == *(listener.details_.changed_urls.begin())); | 553 EXPECT_TRUE(url == *(listener.details_.changed_urls.begin())); |
| 554 } | 554 } |
| 555 | 555 |
| 556 namespace { | 556 namespace { |
| 557 | 557 |
| 558 // See comment in PopulateNodeFromString. | 558 // See comment in PopulateNodeFromString. |
| 559 typedef TreeNodeWithValue<BookmarkNode::Type> TestNode; | 559 typedef TreeNodeWithValue<BookmarkNode::Type> TestNode; |
| 560 | 560 |
| 561 // Does the work of PopulateNodeFromString. index gives the index of the current | 561 // Does the work of PopulateNodeFromString. index gives the index of the current |
| 562 // element in description to process. | 562 // element in description to process. |
| 563 static void PopulateNodeImpl(const std::vector<std::wstring>& description, | 563 static void PopulateNodeImpl(const std::vector<std::string>& description, |
| 564 size_t* index, | 564 size_t* index, |
| 565 TestNode* parent) { | 565 TestNode* parent) { |
| 566 while (*index < description.size()) { | 566 while (*index < description.size()) { |
| 567 const std::wstring& element = description[*index]; | 567 const std::string& element = description[*index]; |
| 568 (*index)++; | 568 (*index)++; |
| 569 if (element == L"[") { | 569 if (element == "[") { |
| 570 // Create a new group and recurse to add all the children. | 570 // Create a new group and recurse to add all the children. |
| 571 // Groups are given a unique named by way of an ever increasing integer | 571 // Groups are given a unique named by way of an ever increasing integer |
| 572 // value. The groups need not have a name, but one is assigned to help | 572 // value. The groups need not have a name, but one is assigned to help |
| 573 // in debugging. | 573 // in debugging. |
| 574 static int next_group_id = 1; | 574 static int next_group_id = 1; |
| 575 TestNode* new_node = | 575 TestNode* new_node = |
| 576 new TestNode(UTF8ToWide(base::IntToString(next_group_id++)), | 576 new TestNode(UTF16ToWideHack(base::IntToString16(next_group_id++)), |
| 577 BookmarkNode::FOLDER); | 577 BookmarkNode::FOLDER); |
| 578 parent->Add(parent->GetChildCount(), new_node); | 578 parent->Add(parent->GetChildCount(), new_node); |
| 579 PopulateNodeImpl(description, index, new_node); | 579 PopulateNodeImpl(description, index, new_node); |
| 580 } else if (element == L"]") { | 580 } else if (element == "]") { |
| 581 // End the current group. | 581 // End the current group. |
| 582 return; | 582 return; |
| 583 } else { | 583 } else { |
| 584 // Add a new URL. | 584 // Add a new URL. |
| 585 | 585 |
| 586 // All tokens must be space separated. If there is a [ or ] in the name it | 586 // All tokens must be space separated. If there is a [ or ] in the name it |
| 587 // likely means a space was forgotten. | 587 // likely means a space was forgotten. |
| 588 DCHECK(element.find('[') == std::string::npos); | 588 DCHECK(element.find('[') == std::string::npos); |
| 589 DCHECK(element.find(']') == std::string::npos); | 589 DCHECK(element.find(']') == std::string::npos); |
| 590 parent->Add(parent->GetChildCount(), | 590 parent->Add(parent->GetChildCount(), |
| 591 new TestNode(element, BookmarkNode::URL)); | 591 new TestNode(UTF8ToWide(element), BookmarkNode::URL)); |
| 592 } | 592 } |
| 593 } | 593 } |
| 594 } | 594 } |
| 595 | 595 |
| 596 // Creates and adds nodes to parent based on description. description consists | 596 // Creates and adds nodes to parent based on description. description consists |
| 597 // of the following tokens (all space separated): | 597 // of the following tokens (all space separated): |
| 598 // [ : creates a new USER_GROUP node. All elements following the [ until the | 598 // [ : creates a new USER_GROUP node. All elements following the [ until the |
| 599 // next balanced ] is encountered are added as children to the node. | 599 // next balanced ] is encountered are added as children to the node. |
| 600 // ] : closes the last group created by [ so that any further nodes are added | 600 // ] : closes the last group created by [ so that any further nodes are added |
| 601 // to the current groups parent. | 601 // to the current groups parent. |
| 602 // text: creates a new URL node. | 602 // text: creates a new URL node. |
| 603 // For example, "a [b] c" creates the following nodes: | 603 // For example, "a [b] c" creates the following nodes: |
| 604 // a 1 c | 604 // a 1 c |
| 605 // | | 605 // | |
| 606 // b | 606 // b |
| 607 // In words: a node of type URL with the title a, followed by a group node with | 607 // In words: a node of type URL with the title a, followed by a group node with |
| 608 // the title 1 having the single child of type url with name b, followed by | 608 // the title 1 having the single child of type url with name b, followed by |
| 609 // the url node with the title c. | 609 // the url node with the title c. |
| 610 // | 610 // |
| 611 // NOTE: each name must be unique, and groups are assigned a unique title by way | 611 // NOTE: each name must be unique, and groups are assigned a unique title by way |
| 612 // of an increasing integer. | 612 // of an increasing integer. |
| 613 static void PopulateNodeFromString(const std::wstring& description, | 613 static void PopulateNodeFromString(const std::string& description, |
| 614 TestNode* parent) { | 614 TestNode* parent) { |
| 615 std::vector<std::wstring> elements; | 615 std::vector<std::string> elements; |
| 616 size_t index = 0; | 616 size_t index = 0; |
| 617 SplitStringAlongWhitespace(description, &elements); | 617 SplitStringAlongWhitespace(description, &elements); |
| 618 PopulateNodeImpl(elements, &index, parent); | 618 PopulateNodeImpl(elements, &index, parent); |
| 619 } | 619 } |
| 620 | 620 |
| 621 // Populates the BookmarkNode with the children of parent. | 621 // Populates the BookmarkNode with the children of parent. |
| 622 static void PopulateBookmarkNode(TestNode* parent, | 622 static void PopulateBookmarkNode(TestNode* parent, |
| 623 BookmarkModel* model, | 623 BookmarkModel* model, |
| 624 const BookmarkNode* bb_node) { | 624 const BookmarkNode* bb_node) { |
| 625 for (int i = 0; i < parent->GetChildCount(); ++i) { | 625 for (int i = 0; i < parent->GetChildCount(); ++i) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 ChromeThread ui_thread_; | 739 ChromeThread ui_thread_; |
| 740 ChromeThread file_thread_; | 740 ChromeThread file_thread_; |
| 741 }; | 741 }; |
| 742 | 742 |
| 743 // Creates a set of nodes in the bookmark bar model, then recreates the | 743 // Creates a set of nodes in the bookmark bar model, then recreates the |
| 744 // bookmark bar model which triggers loading from the db and checks the loaded | 744 // bookmark bar model which triggers loading from the db and checks the loaded |
| 745 // structure to make sure it is what we first created. | 745 // structure to make sure it is what we first created. |
| 746 TEST_F(BookmarkModelTestWithProfile, CreateAndRestore) { | 746 TEST_F(BookmarkModelTestWithProfile, CreateAndRestore) { |
| 747 struct TestData { | 747 struct TestData { |
| 748 // Structure of the children of the bookmark bar model node. | 748 // Structure of the children of the bookmark bar model node. |
| 749 const std::wstring bbn_contents; | 749 const std::string bbn_contents; |
| 750 // Structure of the children of the other node. | 750 // Structure of the children of the other node. |
| 751 const std::wstring other_contents; | 751 const std::string other_contents; |
| 752 } data[] = { | 752 } data[] = { |
| 753 // See PopulateNodeFromString for a description of these strings. | 753 // See PopulateNodeFromString for a description of these strings. |
| 754 { L"", L"" }, | 754 { "", "" }, |
| 755 { L"a", L"b" }, | 755 { "a", "b" }, |
| 756 { L"a [ b ]", L"" }, | 756 { "a [ b ]", "" }, |
| 757 { L"", L"[ b ] a [ c [ d e [ f ] ] ]" }, | 757 { "", "[ b ] a [ c [ d e [ f ] ] ]" }, |
| 758 { L"a [ b ]", L"" }, | 758 { "a [ b ]", "" }, |
| 759 { L"a b c [ d e [ f ] ]", L"g h i [ j k [ l ] ]"}, | 759 { "a b c [ d e [ f ] ]", "g h i [ j k [ l ] ]"}, |
| 760 }; | 760 }; |
| 761 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { | 761 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { |
| 762 // Recreate the profile. We need to reset with NULL first so that the last | 762 // Recreate the profile. We need to reset with NULL first so that the last |
| 763 // HistoryService releases the locks on the files it creates and we can | 763 // HistoryService releases the locks on the files it creates and we can |
| 764 // delete them. | 764 // delete them. |
| 765 profile_.reset(NULL); | 765 profile_.reset(NULL); |
| 766 profile_.reset(new TestingProfile()); | 766 profile_.reset(new TestingProfile()); |
| 767 profile_->CreateBookmarkModel(true); | 767 profile_->CreateBookmarkModel(true); |
| 768 profile_->CreateHistoryService(true, false); | 768 profile_->CreateHistoryService(true, false); |
| 769 BlockTillBookmarkModelLoaded(); | 769 BlockTillBookmarkModelLoaded(); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 | 952 |
| 953 // This won't actually delete the URL, rather it'll empty out the visits. | 953 // This won't actually delete the URL, rather it'll empty out the visits. |
| 954 // This triggers blocking on the BookmarkModel. | 954 // This triggers blocking on the BookmarkModel. |
| 955 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->DeleteURL(url); | 955 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->DeleteURL(url); |
| 956 } | 956 } |
| 957 | 957 |
| 958 TEST_F(BookmarkModelTest, Sort) { | 958 TEST_F(BookmarkModelTest, Sort) { |
| 959 // Populate the bookmark bar node with nodes for 'B', 'a', 'd' and 'C'. | 959 // Populate the bookmark bar node with nodes for 'B', 'a', 'd' and 'C'. |
| 960 // 'C' and 'a' are folders. | 960 // 'C' and 'a' are folders. |
| 961 TestNode bbn; | 961 TestNode bbn; |
| 962 PopulateNodeFromString(L"B [ a ] d [ a ]", &bbn); | 962 PopulateNodeFromString("B [ a ] d [ a ]", &bbn); |
| 963 const BookmarkNode* parent = model.GetBookmarkBarNode(); | 963 const BookmarkNode* parent = model.GetBookmarkBarNode(); |
| 964 PopulateBookmarkNode(&bbn, &model, parent); | 964 PopulateBookmarkNode(&bbn, &model, parent); |
| 965 | 965 |
| 966 BookmarkNode* child1 = AsMutable(parent->GetChild(1)); | 966 BookmarkNode* child1 = AsMutable(parent->GetChild(1)); |
| 967 child1->SetTitle(ASCIIToUTF16("a")); | 967 child1->SetTitle(ASCIIToUTF16("a")); |
| 968 delete child1->Remove(0); | 968 delete child1->Remove(0); |
| 969 BookmarkNode* child3 = AsMutable(parent->GetChild(3)); | 969 BookmarkNode* child3 = AsMutable(parent->GetChild(3)); |
| 970 child3->SetTitle(ASCIIToUTF16("C")); | 970 child3->SetTitle(ASCIIToUTF16("C")); |
| 971 delete child3->Remove(0); | 971 delete child3->Remove(0); |
| 972 | 972 |
| 973 ClearCounts(); | 973 ClearCounts(); |
| 974 | 974 |
| 975 // Sort the children of the bookmark bar node. | 975 // Sort the children of the bookmark bar node. |
| 976 model.SortChildren(parent); | 976 model.SortChildren(parent); |
| 977 | 977 |
| 978 // Make sure we were notified. | 978 // Make sure we were notified. |
| 979 AssertObserverCount(0, 0, 0, 0, 1); | 979 AssertObserverCount(0, 0, 0, 0, 1); |
| 980 | 980 |
| 981 // Make sure the order matches (remember, 'a' and 'C' are folders and | 981 // Make sure the order matches (remember, 'a' and 'C' are folders and |
| 982 // come first). | 982 // come first). |
| 983 EXPECT_EQ(parent->GetChild(0)->GetTitleAsString16(), ASCIIToUTF16("a")); | 983 EXPECT_EQ(parent->GetChild(0)->GetTitleAsString16(), ASCIIToUTF16("a")); |
| 984 EXPECT_EQ(parent->GetChild(1)->GetTitleAsString16(), ASCIIToUTF16("C")); | 984 EXPECT_EQ(parent->GetChild(1)->GetTitleAsString16(), ASCIIToUTF16("C")); |
| 985 EXPECT_EQ(parent->GetChild(2)->GetTitleAsString16(), ASCIIToUTF16("B")); | 985 EXPECT_EQ(parent->GetChild(2)->GetTitleAsString16(), ASCIIToUTF16("B")); |
| 986 EXPECT_EQ(parent->GetChild(3)->GetTitleAsString16(), ASCIIToUTF16("d")); | 986 EXPECT_EQ(parent->GetChild(3)->GetTitleAsString16(), ASCIIToUTF16("d")); |
| 987 } | 987 } |
| OLD | NEW |