bookmark_provider_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/bookmark_provider.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/memory/ref_counted.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string16.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_provider.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The bookmark corpus against which we will simulate searches.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BookmarksTestInfo {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string title;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} bookmark_provider_test_data[] = {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { "abc def", "http://www.catsanddogs.com/a" },
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { "abcde", "http://www.catsanddogs.com/b" },
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "abcdef", "http://www.catsanddogs.com/c" },
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { "a definition", "http://www.catsanddogs.com/d" },
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "carry carbon carefully", "http://www.catsanddogs.com/e" },
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { "ghi jkl", "http://www.catsanddogs.com/f" },
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "jkl ghi", "http://www.catsanddogs.com/g" },
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "frankly frankly frank", "http://www.catsanddogs.com/h" },
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { "foobar foobar", "http://www.foobar.com/" },
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For testing ranking with different URLs.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {"achlorhydric featherheads resuscitates mockingbirds",
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   "http://www.featherheads.com/a" },
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {"achlorhydric mockingbirds resuscitates featherhead",
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   "http://www.featherheads.com/b" },
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {"featherhead resuscitates achlorhydric mockingbirds",
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   "http://www.featherheads.com/c" },
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {"mockingbirds resuscitates featherheads achlorhydric",
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   "http://www.featherheads.com/d" },
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For testing URL boosting.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {"burning worms #1", "http://www.burned.com/" },
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {"burning worms #2", "http://www.worms.com/" },
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  {"worming burns #10", "http://www.burned.com/" },
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  {"worming burns #20", "http://www.worms.com/" },
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  {"jive music", "http://www.worms.com/" },
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkProviderTest : public testing::Test,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             public AutocompleteProviderListener {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkProviderTest() : model_(new BookmarkModel(NULL)) {}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AutocompleteProviderListener: Not called.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnProviderUpdate(bool updated_matches) OVERRIDE {}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkModel> model_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<BookmarkProvider> provider_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BookmarkProviderTest);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkProviderTest::SetUp() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_.reset(new TestingProfile());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_.get());
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  provider_ = new BookmarkProvider(this, profile_.get());
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(provider_.get());
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  provider_->set_bookmark_model_for_testing(model_.get());
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const BookmarkNode* other_node = model_->other_node();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(bookmark_provider_test_data); ++i) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarksTestInfo& cur(bookmark_provider_test_data[i]);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL url(cur.url);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    model_->AddURL(other_node, other_node->child_count(),
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   ASCIIToUTF16(cur.title), url);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Structures and functions supporting the BookmarkProviderTest.Positions
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// unit test.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestBookmarkPosition {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestBookmarkPosition(size_t begin, size_t end)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : begin(begin), end(end) {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t begin;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t end;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::vector<TestBookmarkPosition> TestBookmarkPositions;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return |positions| as a formatted string for unit test diagnostic output.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestBookmarkPositionsAsString(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TestBookmarkPositions& positions) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string position_string("{");
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (TestBookmarkPositions::const_iterator i = positions.begin();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != positions.end(); ++i) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != positions.begin())
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      position_string += ", ";
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_string += "{" + base::IntToString(i->begin) + ", " +
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::IntToString(i->end) + "}";
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position_string += "}\n";
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return position_string;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return the positions in |matches| as a formatted string for unit test
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// diagnostic output.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::string16 MatchesAsString16(const ACMatches& matches) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::string16 matches_string;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ACMatches::const_iterator i = matches.begin(); i != matches.end(); ++i) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matches_string.append(ASCIIToUTF16("    '"));
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matches_string.append(i->description);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matches_string.append(ASCIIToUTF16("'\n"));
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return matches_string;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Comparison function for sorting search terms by descending length.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestBookmarkPositionsEqual(const TestBookmarkPosition& pos_a,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const TestBookmarkPosition& pos_b) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pos_a.begin == pos_b.begin && pos_a.end == pos_b.end;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convience function to make comparing ACMatchClassifications against the
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// test expectations structure easier.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestBookmarkPositions PositionsFromAutocompleteMatch(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AutocompleteMatch& match) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestBookmarkPositions positions;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool started = false;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t start = 0;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AutocompleteMatch::ACMatchClassifications::const_iterator
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i = match.description_class.begin();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != match.description_class.end(); ++i) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->style & AutocompleteMatch::ACMatchClassification::MATCH) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have found the start of a match.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(started);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      started = true;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start = i->offset;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (started) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have found the end of a match.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      started = false;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      positions.push_back(TestBookmarkPosition(start, i->offset));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start = 0;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Record the final position if the last match goes to the end of the
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // candidate string.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (started)
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    positions.push_back(TestBookmarkPosition(start, match.description.size()));
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return positions;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convience function to make comparing test expectations structure against the
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// actual ACMatchClassifications easier.
165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)TestBookmarkPositions PositionsFromExpectations(
166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const size_t expectations[9][2]) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestBookmarkPositions positions;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i = 0;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The array is zero-terminated in the [1]th element.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (expectations[i][1]) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    positions.push_back(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TestBookmarkPosition(expectations[i][0], expectations[i][1]));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++i;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return positions;
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BookmarkProviderTest, Positions) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simulate searches.
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Description of |positions|:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   The first index represents the collection of positions for each expected
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   match. The count of the actual subarrays in each instance of |query_data|
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   must equal |match_count|. The second index represents each expected
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   match position. The third index represents the |start| and |end| of the
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   expected match's position within the |test_data|. This array must be
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   terminated by an entry with a value of '0' for |end|.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Example:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Consider the line for 'def' below:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     {"def", 2, {{{4, 7}, {XXX, 0}}, {{2, 5}, {11, 14}, {XXX, 0}}}},
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   There are two expected matches:
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     0. {{4, 7}, {XXX, 0}}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     1. {{2, 5}, {11 ,14}, {XXX, 0}}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   For the first match, [0], there is one match within the bookmark's title
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   expected, {4, 7}, which maps to the 'def' within "abc def". The 'XXX'
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   value is ignored. The second match, [1], indicates that two matches are
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  //   expected within the bookmark title "a definite definition". In each case,
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  //   the {XXX, 0} indicates the end of the subarray. Or:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 Match #1            Match #2
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //                 ------------------  ----------------------------
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //                  Pos1    Term        Pos1    Pos2      Term
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //                  ------  --------    ------  --------  --------
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     {"def", 2, {{{4, 7}, {999, 0}}, {{2, 5}, {11, 14}, {999, 0}}}},
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct QueryData {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string query;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t match_count;  // This count must match the number of major
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               // elements in the following |positions| array.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t positions[99][9][2];
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } query_data[] = {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This first set is primarily for position detection validation.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"abc",                   3, {{{0, 3}, {0, 0}},
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  {{0, 3}, {0, 0}},
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  {{0, 3}, {0, 0}}}},
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"abcde",                 2, {{{0, 5}, {0, 0}},
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  {{0, 5}, {0, 0}}}},
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"foo bar",               0, {{{0, 0}}}},
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"fooey bark",            0, {{{0, 0}}}},
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"def",                   2, {{{2, 5}, {0, 0}},
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  {{4, 7}, {0, 0}}}},
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"ghi jkl",               2, {{{0, 3}, {4, 7}, {0, 0}},
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  {{0, 3}, {4, 7}, {0, 0}}}},
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NB: GetBookmarksWithTitlesMatching(...) uses exact match for "a".
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"a",                     1, {{{0, 1}, {0, 0}}}},
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"a d",                   0, {{{0, 0}}}},
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"carry carbon",          1, {{{0, 5}, {6, 12}, {0, 0}}}},
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // NB: GetBookmarksWithTitlesMatching(...) sorts the match positions.
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"carbon carry",          1, {{{0, 5}, {6, 12}, {0, 0}}}},
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"arbon",                 0, {{{0, 0}}}},
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"ar",                    0, {{{0, 0}}}},
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"arry",                  0, {{{0, 0}}}},
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Quoted terms are single terms.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"\"carry carbon\"",      1, {{{0, 12}, {0, 0}}}},
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"\"carry carbon\" care", 1, {{{0, 12}, {13, 17}, {0, 0}}}},
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Quoted terms require complete word matches.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"\"carry carbo\"",       0, {{{0, 0}}}},
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This set uses duplicated and/or overlaps search terms in the title.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"frank",                 1, {{{0, 5}, {8, 13}, {16, 21}, {0, 0}}}},
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"frankly",               1, {{{0, 7}, {8, 15}, {0, 0}}}},
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"frankly frankly",       1, {{{0, 7}, {8, 15}, {0, 0}}}},
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"foobar foo",            1, {{{0, 6}, {7, 13}, {0, 0}}}},
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"foo foobar",            1, {{{0, 6}, {7, 13}, {0, 0}}}},
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(query_data); ++i) {
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    AutocompleteInput input(ASCIIToUTF16(query_data[i].query),
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::string16::npos, base::string16(), GURL(),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            AutocompleteInput::INVALID_SPEC, false, false,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            false, AutocompleteInput::ALL_MATCHES);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider_->Start(input, false);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ACMatches& matches(provider_->matches());
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Validate number of results is as expected.
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_LE(matches.size(), query_data[i].match_count)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "One or more of the following matches were unexpected:\n"
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << MatchesAsString16(matches)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "For query '" << query_data[i].query << "'.";
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GE(matches.size(), query_data[i].match_count)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "One or more expected matches are missing. Matches found:\n"
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << MatchesAsString16(matches)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "for query '" << query_data[i].query << "'.";
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Validate positions within each match is as expected.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < matches.size(); ++j) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Collect the expected positions as a vector, collect the match's
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // classifications for match positions as a vector, then compare.
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestBookmarkPositions expected_positions(
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          PositionsFromExpectations(query_data[i].positions[j]));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestBookmarkPositions actual_positions(
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PositionsFromAutocompleteMatch(matches[j]));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(std::equal(expected_positions.begin(),
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             expected_positions.end(),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             actual_positions.begin(),
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             TestBookmarkPositionsEqual))
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "EXPECTED: " << TestBookmarkPositionsAsString(expected_positions)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "ACTUAL:   " << TestBookmarkPositionsAsString(actual_positions)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "    for query: '" << query_data[i].query << "'.";
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BookmarkProviderTest, Rankings) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simulate searches.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct QueryData {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string query;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |match_count| must match the number of elements in the following
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |matches| array.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t match_count;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |matches| specifies the titles for all bookmarks expected to be matched
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by the |query|
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string matches[99];
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } query_data[] = {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Basic ranking test.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"abc",       3, {"abcde",      // Most complete match.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "abcdef",
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "abc def"}},  // Least complete match.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"ghi",       2, {"ghi jkl",    // Matched earlier.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "jkl ghi"}},  // Matched later.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Rankings of exact-word matches with different URLs.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"achlorhydric",
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  3, {"achlorhydric mockingbirds resuscitates featherhead",
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "achlorhydric featherheads resuscitates mockingbirds",
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "featherhead resuscitates achlorhydric mockingbirds"}},
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"achlorhydric featherheads",
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  2, {"achlorhydric featherheads resuscitates mockingbirds",
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "mockingbirds resuscitates featherheads achlorhydric"}},
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"mockingbirds resuscitates",
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  3, {"mockingbirds resuscitates featherheads achlorhydric",
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      "achlorhydric mockingbirds resuscitates featherhead",
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      "featherhead resuscitates achlorhydric mockingbirds"}},
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ranking of exact-word matches with URL boost.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"worms",     2, {"burning worms #2",    // boosted
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      "burning worms #1"}},  // not boosted
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ranking of prefix matches with URL boost. Note that a query of
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // "worm burn" will have the same results.
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"burn worm", 3, {"burning worms #2",    // boosted
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "worming burns #20",   // boosted
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "burning worms #1"}},  // not boosted but shorter
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(query_data); ++i) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutocompleteInput input(ASCIIToUTF16(query_data[i].query),
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::string16::npos, base::string16(), GURL(),
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            AutocompleteInput::INVALID_SPEC, false, false,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            false, AutocompleteInput::ALL_MATCHES);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider_->Start(input, false);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ACMatches& matches(provider_->matches());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Validate number and content of results is as expected.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < std::max(query_data[i].match_count, matches.size());
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++j) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_LT(j, query_data[i].match_count) << "    Unexpected match '"
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << UTF16ToUTF8(matches[j].description) << "' for query: '"
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          <<  query_data[i].query << "'.";
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j >= query_data[i].match_count)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_LT(j, matches.size()) << "    Missing match '"
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << query_data[i].matches[j] << "' for query: '"
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << query_data[i].query << "'.";
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j >= matches.size())
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(query_data[i].matches[j], UTF16ToUTF8(matches[j].description))
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << "    Mismatch at [" << base::IntToString(j) << "] for query '"
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << query_data[i].query << "'.";
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_FALSE(matches[j].allowed_to_be_default_match);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)