| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/bookmarks/browser/bookmark_index.h" | |
| 6 | |
| 7 #include <stddef.h> | 5 #include <stddef.h> |
| 8 | 6 |
| 9 #include <string> | 7 #include <string> |
| 10 #include <vector> | 8 #include <vector> |
| 11 | 9 |
| 12 #include "base/macros.h" | 10 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 16 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 18 #include "components/bookmarks/browser/bookmark_match.h" | |
| 19 #include "components/bookmarks/browser/bookmark_model.h" | 16 #include "components/bookmarks/browser/bookmark_model.h" |
| 17 #include "components/bookmarks/browser/titled_url_match.h" |
| 20 #include "components/bookmarks/test/bookmark_test_helpers.h" | 18 #include "components/bookmarks/test/bookmark_test_helpers.h" |
| 21 #include "components/bookmarks/test/test_bookmark_client.h" | 19 #include "components/bookmarks/test/test_bookmark_client.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 21 |
| 24 using base::ASCIIToUTF16; | 22 using base::ASCIIToUTF16; |
| 25 using base::UTF8ToUTF16; | 23 using base::UTF8ToUTF16; |
| 26 | 24 |
| 27 namespace bookmarks { | 25 namespace bookmarks { |
| 28 namespace { | 26 namespace { |
| 29 | 27 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 std::vector<std::string> title_vector; | 84 std::vector<std::string> title_vector; |
| 87 for (size_t i = 0; i < expected_count; ++i) | 85 for (size_t i = 0; i < expected_count; ++i) |
| 88 title_vector.push_back(expected_titles[i]); | 86 title_vector.push_back(expected_titles[i]); |
| 89 ExpectMatches(query, query_parser::MatchingAlgorithm::DEFAULT, | 87 ExpectMatches(query, query_parser::MatchingAlgorithm::DEFAULT, |
| 90 title_vector); | 88 title_vector); |
| 91 } | 89 } |
| 92 | 90 |
| 93 void ExpectMatches(const std::string& query, | 91 void ExpectMatches(const std::string& query, |
| 94 query_parser::MatchingAlgorithm matching_algorithm, | 92 query_parser::MatchingAlgorithm matching_algorithm, |
| 95 const std::vector<std::string>& expected_titles) { | 93 const std::vector<std::string>& expected_titles) { |
| 96 std::vector<BookmarkMatch> matches; | 94 std::vector<TitledUrlMatch> matches; |
| 97 model_->GetBookmarksMatching(ASCIIToUTF16(query), 1000, matching_algorithm, | 95 model_->GetBookmarksMatching(ASCIIToUTF16(query), 1000, matching_algorithm, |
| 98 &matches); | 96 &matches); |
| 99 ASSERT_EQ(expected_titles.size(), matches.size()); | 97 ASSERT_EQ(expected_titles.size(), matches.size()); |
| 100 for (size_t i = 0; i < expected_titles.size(); ++i) { | 98 for (size_t i = 0; i < expected_titles.size(); ++i) { |
| 101 bool found = false; | 99 bool found = false; |
| 102 for (size_t j = 0; j < matches.size(); ++j) { | 100 for (size_t j = 0; j < matches.size(); ++j) { |
| 103 const base::string16& title = matches[j].node->GetTitledUrlNodeTitle(); | 101 const base::string16& title = matches[j].node->GetTitledUrlNodeTitle(); |
| 104 if (ASCIIToUTF16(expected_titles[i]) == title) { | 102 if (ASCIIToUTF16(expected_titles[i]) == title) { |
| 105 matches.erase(matches.begin() + j); | 103 matches.erase(matches.begin() + j); |
| 106 found = true; | 104 found = true; |
| 107 break; | 105 break; |
| 108 } | 106 } |
| 109 } | 107 } |
| 110 ASSERT_TRUE(found); | 108 ASSERT_TRUE(found); |
| 111 } | 109 } |
| 112 } | 110 } |
| 113 | 111 |
| 114 void ExtractMatchPositions(const std::string& string, | 112 void ExtractMatchPositions(const std::string& string, |
| 115 BookmarkMatch::MatchPositions* matches) { | 113 TitledUrlMatch::MatchPositions* matches) { |
| 116 for (const base::StringPiece& match : | 114 for (const base::StringPiece& match : |
| 117 base::SplitStringPiece(string, ":", | 115 base::SplitStringPiece(string, ":", |
| 118 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { | 116 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { |
| 119 std::vector<base::StringPiece> chunks = base::SplitStringPiece( | 117 std::vector<base::StringPiece> chunks = base::SplitStringPiece( |
| 120 match, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 118 match, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 121 ASSERT_EQ(2U, chunks.size()); | 119 ASSERT_EQ(2U, chunks.size()); |
| 122 matches->push_back(BookmarkMatch::MatchPosition()); | 120 matches->push_back(TitledUrlMatch::MatchPosition()); |
| 123 int chunks0, chunks1; | 121 int chunks0, chunks1; |
| 124 EXPECT_TRUE(base::StringToInt(chunks[0], &chunks0)); | 122 EXPECT_TRUE(base::StringToInt(chunks[0], &chunks0)); |
| 125 EXPECT_TRUE(base::StringToInt(chunks[1], &chunks1)); | 123 EXPECT_TRUE(base::StringToInt(chunks[1], &chunks1)); |
| 126 matches->back().first = chunks0; | 124 matches->back().first = chunks0; |
| 127 matches->back().second = chunks1; | 125 matches->back().second = chunks1; |
| 128 } | 126 } |
| 129 } | 127 } |
| 130 | 128 |
| 131 void ExpectMatchPositions( | 129 void ExpectMatchPositions( |
| 132 const BookmarkMatch::MatchPositions& actual_positions, | 130 const TitledUrlMatch::MatchPositions& actual_positions, |
| 133 const BookmarkMatch::MatchPositions& expected_positions) { | 131 const TitledUrlMatch::MatchPositions& expected_positions) { |
| 134 ASSERT_EQ(expected_positions.size(), actual_positions.size()); | 132 ASSERT_EQ(expected_positions.size(), actual_positions.size()); |
| 135 for (size_t i = 0; i < expected_positions.size(); ++i) { | 133 for (size_t i = 0; i < expected_positions.size(); ++i) { |
| 136 EXPECT_EQ(expected_positions[i].first, actual_positions[i].first); | 134 EXPECT_EQ(expected_positions[i].first, actual_positions[i].first); |
| 137 EXPECT_EQ(expected_positions[i].second, actual_positions[i].second); | 135 EXPECT_EQ(expected_positions[i].second, actual_positions[i].second); |
| 138 } | 136 } |
| 139 } | 137 } |
| 140 | 138 |
| 141 protected: | 139 protected: |
| 142 std::unique_ptr<BookmarkModel> model_; | 140 std::unique_ptr<BookmarkModel> model_; |
| 143 | 141 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 { "foo\xc3\xa4-test", "fooa\xcc\x88-test" }, | 350 { "foo\xc3\xa4-test", "fooa\xcc\x88-test" }, |
| 353 { "foo\xc3\xa4-test", "foo\xc3\xa4" }, | 351 { "foo\xc3\xa4-test", "foo\xc3\xa4" }, |
| 354 { "foo\xc3\xa4-test", "fooa\xcc\x88" }, | 352 { "foo\xc3\xa4-test", "fooa\xcc\x88" }, |
| 355 { "foo\xc3\xa4-test", "foo" }, | 353 { "foo\xc3\xa4-test", "foo" }, |
| 356 { "foo", "foo" } | 354 { "foo", "foo" } |
| 357 }; | 355 }; |
| 358 | 356 |
| 359 GURL url(kAboutBlankURL); | 357 GURL url(kAboutBlankURL); |
| 360 for (size_t i = 0; i < arraysize(data); ++i) { | 358 for (size_t i = 0; i < arraysize(data); ++i) { |
| 361 model_->AddURL(model_->other_node(), 0, UTF8ToUTF16(data[i].title), url); | 359 model_->AddURL(model_->other_node(), 0, UTF8ToUTF16(data[i].title), url); |
| 362 std::vector<BookmarkMatch> matches; | 360 std::vector<TitledUrlMatch> matches; |
| 363 model_->GetBookmarksMatching(UTF8ToUTF16(data[i].query), 10, &matches); | 361 model_->GetBookmarksMatching(UTF8ToUTF16(data[i].query), 10, &matches); |
| 364 EXPECT_EQ(1u, matches.size()); | 362 EXPECT_EQ(1u, matches.size()); |
| 365 model_ = TestBookmarkClient::CreateModel(); | 363 model_ = TestBookmarkClient::CreateModel(); |
| 366 } | 364 } |
| 367 } | 365 } |
| 368 | 366 |
| 369 // Makes sure match positions are updated appropriately for title matches. | 367 // Makes sure match positions are updated appropriately for title matches. |
| 370 TEST_F(BookmarkIndexTest, MatchPositionsTitles) { | 368 TEST_F(BookmarkIndexTest, MatchPositionsTitles) { |
| 371 struct TestData { | 369 struct TestData { |
| 372 const std::string title; | 370 const std::string title; |
| 373 const std::string query; | 371 const std::string query; |
| 374 const std::string expected_title_match_positions; | 372 const std::string expected_title_match_positions; |
| 375 } data[] = { | 373 } data[] = { |
| 376 // Trivial test case of only one term, exact match. | 374 // Trivial test case of only one term, exact match. |
| 377 { "a", "A", "0,1" }, | 375 { "a", "A", "0,1" }, |
| 378 { "foo bar", "bar", "4,7" }, | 376 { "foo bar", "bar", "4,7" }, |
| 379 { "fooey bark", "bar foo", "0,3:6,9" }, | 377 { "fooey bark", "bar foo", "0,3:6,9" }, |
| 380 // Non-trivial tests. | 378 // Non-trivial tests. |
| 381 { "foobar foo", "foobar foo", "0,6:7,10" }, | 379 { "foobar foo", "foobar foo", "0,6:7,10" }, |
| 382 { "foobar foo", "foo foobar", "0,6:7,10" }, | 380 { "foobar foo", "foo foobar", "0,6:7,10" }, |
| 383 { "foobar foobar", "foobar foo", "0,6:7,13" }, | 381 { "foobar foobar", "foobar foo", "0,6:7,13" }, |
| 384 { "foobar foobar", "foo foobar", "0,6:7,13" }, | 382 { "foobar foobar", "foo foobar", "0,6:7,13" }, |
| 385 }; | 383 }; |
| 386 for (size_t i = 0; i < arraysize(data); ++i) { | 384 for (size_t i = 0; i < arraysize(data); ++i) { |
| 387 std::vector<TitleAndURL> bookmarks; | 385 std::vector<TitleAndURL> bookmarks; |
| 388 TitleAndURL bookmark(data[i].title, kAboutBlankURL); | 386 TitleAndURL bookmark(data[i].title, kAboutBlankURL); |
| 389 bookmarks.push_back(bookmark); | 387 bookmarks.push_back(bookmark); |
| 390 AddBookmarks(bookmarks); | 388 AddBookmarks(bookmarks); |
| 391 | 389 |
| 392 std::vector<BookmarkMatch> matches; | 390 std::vector<TitledUrlMatch> matches; |
| 393 model_->GetBookmarksMatching(ASCIIToUTF16(data[i].query), 1000, &matches); | 391 model_->GetBookmarksMatching(ASCIIToUTF16(data[i].query), 1000, &matches); |
| 394 ASSERT_EQ(1U, matches.size()); | 392 ASSERT_EQ(1U, matches.size()); |
| 395 | 393 |
| 396 BookmarkMatch::MatchPositions expected_title_matches; | 394 TitledUrlMatch::MatchPositions expected_title_matches; |
| 397 ExtractMatchPositions(data[i].expected_title_match_positions, | 395 ExtractMatchPositions(data[i].expected_title_match_positions, |
| 398 &expected_title_matches); | 396 &expected_title_matches); |
| 399 ExpectMatchPositions(matches[0].title_match_positions, | 397 ExpectMatchPositions(matches[0].title_match_positions, |
| 400 expected_title_matches); | 398 expected_title_matches); |
| 401 | 399 |
| 402 model_ = TestBookmarkClient::CreateModel(); | 400 model_ = TestBookmarkClient::CreateModel(); |
| 403 } | 401 } |
| 404 } | 402 } |
| 405 | 403 |
| 406 // Makes sure match positions are updated appropriately for URL matches. | 404 // Makes sure match positions are updated appropriately for URL matches. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 434 "130,134:139,143" } | 432 "130,134:139,143" } |
| 435 }; | 433 }; |
| 436 | 434 |
| 437 for (size_t i = 0; i < arraysize(data); ++i) { | 435 for (size_t i = 0; i < arraysize(data); ++i) { |
| 438 model_ = TestBookmarkClient::CreateModel(); | 436 model_ = TestBookmarkClient::CreateModel(); |
| 439 std::vector<TitleAndURL> bookmarks; | 437 std::vector<TitleAndURL> bookmarks; |
| 440 TitleAndURL bookmark("123456", data[i].url); | 438 TitleAndURL bookmark("123456", data[i].url); |
| 441 bookmarks.push_back(bookmark); | 439 bookmarks.push_back(bookmark); |
| 442 AddBookmarks(bookmarks); | 440 AddBookmarks(bookmarks); |
| 443 | 441 |
| 444 std::vector<BookmarkMatch> matches; | 442 std::vector<TitledUrlMatch> matches; |
| 445 model_->GetBookmarksMatching(UTF8ToUTF16(data[i].query), 1000, &matches); | 443 model_->GetBookmarksMatching(UTF8ToUTF16(data[i].query), 1000, &matches); |
| 446 ASSERT_EQ(1U, matches.size()) << data[i].url << data[i].query; | 444 ASSERT_EQ(1U, matches.size()) << data[i].url << data[i].query; |
| 447 | 445 |
| 448 BookmarkMatch::MatchPositions expected_url_matches; | 446 TitledUrlMatch::MatchPositions expected_url_matches; |
| 449 ExtractMatchPositions(data[i].expected_url_match_positions, | 447 ExtractMatchPositions(data[i].expected_url_match_positions, |
| 450 &expected_url_matches); | 448 &expected_url_matches); |
| 451 ExpectMatchPositions(matches[0].url_match_positions, expected_url_matches); | 449 ExpectMatchPositions(matches[0].url_match_positions, expected_url_matches); |
| 452 } | 450 } |
| 453 } | 451 } |
| 454 | 452 |
| 455 // Makes sure index is updated when a node is removed. | 453 // Makes sure index is updated when a node is removed. |
| 456 TEST_F(BookmarkIndexTest, Remove) { | 454 TEST_F(BookmarkIndexTest, Remove) { |
| 457 const char* titles[] = { "a", "b" }; | 455 const char* titles[] = { "a", "b" }; |
| 458 const char* urls[] = {kAboutBlankURL, kAboutBlankURL}; | 456 const char* urls[] = {kAboutBlankURL, kAboutBlankURL}; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 486 model_->SetURL(model_->other_node()->GetChild(0), GURL("http://blah")); | 484 model_->SetURL(model_->other_node()->GetChild(0), GURL("http://blah")); |
| 487 ExpectMatches("blah", expected, arraysize(expected)); | 485 ExpectMatches("blah", expected, arraysize(expected)); |
| 488 } | 486 } |
| 489 | 487 |
| 490 // Makes sure no more than max queries is returned. | 488 // Makes sure no more than max queries is returned. |
| 491 TEST_F(BookmarkIndexTest, HonorMax) { | 489 TEST_F(BookmarkIndexTest, HonorMax) { |
| 492 const char* titles[] = { "abcd", "abcde" }; | 490 const char* titles[] = { "abcd", "abcde" }; |
| 493 const char* urls[] = {kAboutBlankURL, kAboutBlankURL}; | 491 const char* urls[] = {kAboutBlankURL, kAboutBlankURL}; |
| 494 AddBookmarks(titles, urls, arraysize(titles)); | 492 AddBookmarks(titles, urls, arraysize(titles)); |
| 495 | 493 |
| 496 std::vector<BookmarkMatch> matches; | 494 std::vector<TitledUrlMatch> matches; |
| 497 model_->GetBookmarksMatching(ASCIIToUTF16("ABc"), 1, &matches); | 495 model_->GetBookmarksMatching(ASCIIToUTF16("ABc"), 1, &matches); |
| 498 EXPECT_EQ(1U, matches.size()); | 496 EXPECT_EQ(1U, matches.size()); |
| 499 } | 497 } |
| 500 | 498 |
| 501 // Makes sure if the lower case string of a bookmark title is more characters | 499 // Makes sure if the lower case string of a bookmark title is more characters |
| 502 // than the upper case string no match positions are returned. | 500 // than the upper case string no match positions are returned. |
| 503 TEST_F(BookmarkIndexTest, EmptyMatchOnMultiwideLowercaseString) { | 501 TEST_F(BookmarkIndexTest, EmptyMatchOnMultiwideLowercaseString) { |
| 504 const BookmarkNode* n1 = model_->AddURL(model_->other_node(), 0, | 502 const BookmarkNode* n1 = model_->AddURL(model_->other_node(), 0, |
| 505 base::WideToUTF16(L"\u0130 i"), | 503 base::WideToUTF16(L"\u0130 i"), |
| 506 GURL("http://www.google.com")); | 504 GURL("http://www.google.com")); |
| 507 | 505 |
| 508 std::vector<BookmarkMatch> matches; | 506 std::vector<TitledUrlMatch> matches; |
| 509 model_->GetBookmarksMatching(ASCIIToUTF16("i"), 100, &matches); | 507 model_->GetBookmarksMatching(ASCIIToUTF16("i"), 100, &matches); |
| 510 ASSERT_EQ(1U, matches.size()); | 508 ASSERT_EQ(1U, matches.size()); |
| 511 EXPECT_EQ(n1, matches[0].node); | 509 EXPECT_EQ(n1, matches[0].node); |
| 512 EXPECT_TRUE(matches[0].title_match_positions.empty()); | 510 EXPECT_TRUE(matches[0].title_match_positions.empty()); |
| 513 } | 511 } |
| 514 | 512 |
| 515 TEST_F(BookmarkIndexTest, GetResultsSortedByTypedCount) { | 513 TEST_F(BookmarkIndexTest, GetResultsSortedByTypedCount) { |
| 516 struct TestData { | 514 struct TestData { |
| 517 const GURL url; | 515 const GURL url; |
| 518 const char* title; | 516 const char* title; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 531 std::unique_ptr<BookmarkModel> model = | 529 std::unique_ptr<BookmarkModel> model = |
| 532 TestBookmarkClient::CreateModelWithClient( | 530 TestBookmarkClient::CreateModelWithClient( |
| 533 base::MakeUnique<BookmarkClientMock>(typed_count_map)); | 531 base::MakeUnique<BookmarkClientMock>(typed_count_map)); |
| 534 | 532 |
| 535 for (size_t i = 0; i < arraysize(data); ++i) | 533 for (size_t i = 0; i < arraysize(data); ++i) |
| 536 // Populate the bookmark index. | 534 // Populate the bookmark index. |
| 537 model->AddURL( | 535 model->AddURL( |
| 538 model->other_node(), i, UTF8ToUTF16(data[i].title), data[i].url); | 536 model->other_node(), i, UTF8ToUTF16(data[i].title), data[i].url); |
| 539 | 537 |
| 540 // Populate match nodes. | 538 // Populate match nodes. |
| 541 std::vector<BookmarkMatch> matches; | 539 std::vector<TitledUrlMatch> matches; |
| 542 model->GetBookmarksMatching(ASCIIToUTF16("google"), 4, &matches); | 540 model->GetBookmarksMatching(ASCIIToUTF16("google"), 4, &matches); |
| 543 | 541 |
| 544 // The resulting order should be: | 542 // The resulting order should be: |
| 545 // 1. Google (google.com) 100 | 543 // 1. Google (google.com) 100 |
| 546 // 2. Google Reader (google.com/reader) 80 | 544 // 2. Google Reader (google.com/reader) 80 |
| 547 // 3. Google Docs (docs.google.com) 50 | 545 // 3. Google Docs (docs.google.com) 50 |
| 548 // 4. Google Maps (maps.google.com) 40 | 546 // 4. Google Maps (maps.google.com) 40 |
| 549 ASSERT_EQ(4U, matches.size()); | 547 ASSERT_EQ(4U, matches.size()); |
| 550 EXPECT_EQ(data[0].url, matches[0].node->GetTitledUrlNodeUrl()); | 548 EXPECT_EQ(data[0].url, matches[0].node->GetTitledUrlNodeUrl()); |
| 551 EXPECT_EQ(data[3].url, matches[1].node->GetTitledUrlNodeUrl()); | 549 EXPECT_EQ(data[3].url, matches[1].node->GetTitledUrlNodeUrl()); |
| 552 EXPECT_EQ(data[2].url, matches[2].node->GetTitledUrlNodeUrl()); | 550 EXPECT_EQ(data[2].url, matches[2].node->GetTitledUrlNodeUrl()); |
| 553 EXPECT_EQ(data[1].url, matches[3].node->GetTitledUrlNodeUrl()); | 551 EXPECT_EQ(data[1].url, matches[3].node->GetTitledUrlNodeUrl()); |
| 554 | 552 |
| 555 matches.clear(); | 553 matches.clear(); |
| 556 // Select top two matches. | 554 // Select top two matches. |
| 557 model->GetBookmarksMatching(ASCIIToUTF16("google"), 2, &matches); | 555 model->GetBookmarksMatching(ASCIIToUTF16("google"), 2, &matches); |
| 558 | 556 |
| 559 ASSERT_EQ(2U, matches.size()); | 557 ASSERT_EQ(2U, matches.size()); |
| 560 EXPECT_EQ(data[0].url, matches[0].node->GetTitledUrlNodeUrl()); | 558 EXPECT_EQ(data[0].url, matches[0].node->GetTitledUrlNodeUrl()); |
| 561 EXPECT_EQ(data[3].url, matches[1].node->GetTitledUrlNodeUrl()); | 559 EXPECT_EQ(data[3].url, matches[1].node->GetTitledUrlNodeUrl()); |
| 562 } | 560 } |
| 563 | 561 |
| 564 } // namespace | 562 } // namespace |
| 565 } // namespace bookmarks | 563 } // namespace bookmarks |
| OLD | NEW |