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 |