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 <string> | 5 #include <string> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
12 #include "chrome/browser/bookmarks/bookmark_index.h" | 12 #include "chrome/browser/bookmarks/bookmark_index.h" |
13 #include "chrome/browser/bookmarks/bookmark_model.h" | 13 #include "chrome/browser/bookmarks/bookmark_model.h" |
14 #include "chrome/browser/bookmarks/bookmark_utils.h" | 14 #include "chrome/browser/bookmarks/bookmark_utils.h" |
15 #include "chrome/browser/chrome_thread.h" | 15 #include "chrome/browser/chrome_thread.h" |
16 #include "chrome/browser/history/history_database.h" | 16 #include "chrome/browser/history/history_database.h" |
17 #include "chrome/browser/history/in_memory_database.h" | 17 #include "chrome/browser/history/in_memory_database.h" |
18 #include "chrome/browser/history/query_parser.h" | 18 #include "chrome/browser/history/query_parser.h" |
19 #include "chrome/test/testing_profile.h" | 19 #include "chrome/test/testing_profile.h" |
20 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
21 | 21 |
22 class BookmarkIndexTest : public testing::Test { | 22 class BookmarkIndexTest : public testing::Test { |
23 public: | 23 public: |
24 BookmarkIndexTest() : model_(new BookmarkModel(NULL)) {} | 24 BookmarkIndexTest() : model_(new BookmarkModel(NULL)) {} |
25 | 25 |
26 void AddBookmarksWithTitles(const wchar_t** titles, size_t count) { | 26 void AddBookmarksWithTitles(const char** titles, size_t count) { |
27 std::vector<std::wstring> title_vector; | 27 std::vector<std::string> title_vector; |
28 for (size_t i = 0; i < count; ++i) | 28 for (size_t i = 0; i < count; ++i) |
29 title_vector.push_back(titles[i]); | 29 title_vector.push_back(titles[i]); |
30 AddBookmarksWithTitles(title_vector); | 30 AddBookmarksWithTitles(title_vector); |
31 } | 31 } |
32 | 32 |
33 void AddBookmarksWithTitles(const std::vector<std::wstring>& titles) { | 33 void AddBookmarksWithTitles(const std::vector<std::string>& titles) { |
34 GURL url("about:blank"); | 34 GURL url("about:blank"); |
35 for (size_t i = 0; i < titles.size(); ++i) | 35 for (size_t i = 0; i < titles.size(); ++i) |
36 model_->AddURL(model_->other_node(), static_cast<int>(i), | 36 model_->AddURL(model_->other_node(), static_cast<int>(i), |
37 WideToUTF16Hack(titles[i]), url); | 37 ASCIIToUTF16(titles[i]), url); |
38 } | 38 } |
39 | 39 |
40 void ExpectMatches(const std::wstring& query, | 40 void ExpectMatches(const std::string& query, |
41 const wchar_t** expected_titles, | 41 const char** expected_titles, |
42 size_t expected_count) { | 42 size_t expected_count) { |
43 std::vector<std::wstring> title_vector; | 43 std::vector<std::string> title_vector; |
44 for (size_t i = 0; i < expected_count; ++i) | 44 for (size_t i = 0; i < expected_count; ++i) |
45 title_vector.push_back(expected_titles[i]); | 45 title_vector.push_back(expected_titles[i]); |
46 ExpectMatches(query, title_vector); | 46 ExpectMatches(query, title_vector); |
47 } | 47 } |
48 | 48 |
49 void ExpectMatches(const std::wstring& query, | 49 void ExpectMatches(const std::string& query, |
50 const std::vector<std::wstring> expected_titles) { | 50 const std::vector<std::string> expected_titles) { |
51 std::vector<bookmark_utils::TitleMatch> matches; | 51 std::vector<bookmark_utils::TitleMatch> matches; |
52 model_->GetBookmarksWithTitlesMatching(WideToUTF16Hack(query), 1000, | 52 model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16(query), 1000, &matches); |
53 &matches); | |
54 ASSERT_EQ(expected_titles.size(), matches.size()); | 53 ASSERT_EQ(expected_titles.size(), matches.size()); |
55 for (size_t i = 0; i < expected_titles.size(); ++i) { | 54 for (size_t i = 0; i < expected_titles.size(); ++i) { |
56 bool found = false; | 55 bool found = false; |
57 for (size_t j = 0; j < matches.size(); ++j) { | 56 for (size_t j = 0; j < matches.size(); ++j) { |
58 if (std::wstring(expected_titles[i]) == matches[j].node->GetTitle()) { | 57 if (ASCIIToUTF16(expected_titles[i]) == |
| 58 matches[j].node->GetTitleAsString16()) { |
59 matches.erase(matches.begin() + j); | 59 matches.erase(matches.begin() + j); |
60 found = true; | 60 found = true; |
61 break; | 61 break; |
62 } | 62 } |
63 } | 63 } |
64 ASSERT_TRUE(found); | 64 ASSERT_TRUE(found); |
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 void ExtractMatchPositions(const std::string& string, | 68 void ExtractMatchPositions(const std::string& string, |
69 Snippet::MatchPositions* matches) { | 69 Snippet::MatchPositions* matches) { |
70 std::vector<std::string> match_strings; | 70 std::vector<std::string> match_strings; |
71 SplitString(string, L':', &match_strings); | 71 SplitString(string, ':', &match_strings); |
72 for (size_t i = 0; i < match_strings.size(); ++i) { | 72 for (size_t i = 0; i < match_strings.size(); ++i) { |
73 std::vector<std::string> chunks; | 73 std::vector<std::string> chunks; |
74 SplitString(match_strings[i], ',', &chunks); | 74 SplitString(match_strings[i], ',', &chunks); |
75 ASSERT_EQ(2U, chunks.size()); | 75 ASSERT_EQ(2U, chunks.size()); |
76 matches->push_back(Snippet::MatchPosition()); | 76 matches->push_back(Snippet::MatchPosition()); |
77 int chunks0, chunks1; | 77 int chunks0, chunks1; |
78 base::StringToInt(chunks[0], &chunks0); | 78 base::StringToInt(chunks[0], &chunks0); |
79 base::StringToInt(chunks[1], &chunks1); | 79 base::StringToInt(chunks[1], &chunks1); |
80 matches->back().first = chunks0; | 80 matches->back().first = chunks0; |
81 matches->back().second = chunks1; | 81 matches->back().second = chunks1; |
82 } | 82 } |
83 } | 83 } |
84 | 84 |
85 void ExpectMatchPositions(const std::wstring& query, | 85 void ExpectMatchPositions(const std::string& query, |
86 const Snippet::MatchPositions& expected_positions) { | 86 const Snippet::MatchPositions& expected_positions) { |
87 std::vector<bookmark_utils::TitleMatch> matches; | 87 std::vector<bookmark_utils::TitleMatch> matches; |
88 model_->GetBookmarksWithTitlesMatching(WideToUTF16Hack(query), 1000, | 88 model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16(query), 1000, &matches); |
89 &matches); | |
90 ASSERT_EQ(1U, matches.size()); | 89 ASSERT_EQ(1U, matches.size()); |
91 const bookmark_utils::TitleMatch& match = matches[0]; | 90 const bookmark_utils::TitleMatch& match = matches[0]; |
92 ASSERT_EQ(expected_positions.size(), match.match_positions.size()); | 91 ASSERT_EQ(expected_positions.size(), match.match_positions.size()); |
93 for (size_t i = 0; i < expected_positions.size(); ++i) { | 92 for (size_t i = 0; i < expected_positions.size(); ++i) { |
94 EXPECT_EQ(expected_positions[i].first, match.match_positions[i].first); | 93 EXPECT_EQ(expected_positions[i].first, match.match_positions[i].first); |
95 EXPECT_EQ(expected_positions[i].second, match.match_positions[i].second); | 94 EXPECT_EQ(expected_positions[i].second, match.match_positions[i].second); |
96 } | 95 } |
97 } | 96 } |
98 | 97 |
99 protected: | 98 protected: |
100 scoped_ptr<BookmarkModel> model_; | 99 scoped_ptr<BookmarkModel> model_; |
101 | 100 |
102 private: | 101 private: |
103 DISALLOW_COPY_AND_ASSIGN(BookmarkIndexTest); | 102 DISALLOW_COPY_AND_ASSIGN(BookmarkIndexTest); |
104 }; | 103 }; |
105 | 104 |
106 // Various permutations with differing input, queries and output that exercises | 105 // Various permutations with differing input, queries and output that exercises |
107 // all query paths. | 106 // all query paths. |
108 TEST_F(BookmarkIndexTest, Tests) { | 107 TEST_F(BookmarkIndexTest, Tests) { |
109 struct TestData { | 108 struct TestData { |
110 const std::wstring input; | 109 const std::string input; |
111 const std::wstring query; | 110 const std::string query; |
112 const std::wstring expected; | 111 const std::string expected; |
113 } data[] = { | 112 } data[] = { |
114 // Trivial test case of only one term, exact match. | 113 // Trivial test case of only one term, exact match. |
115 { L"a;b", L"A", L"a" }, | 114 { "a;b", "A", "a" }, |
116 | 115 |
117 // Prefix match, one term. | 116 // Prefix match, one term. |
118 { L"abcd;abc;b", L"abc", L"abcd;abc" }, | 117 { "abcd;abc;b", "abc", "abcd;abc" }, |
119 | 118 |
120 // Prefix match, multiple terms. | 119 // Prefix match, multiple terms. |
121 { L"abcd cdef;abcd;abcd cdefg", L"abc cde", L"abcd cdef;abcd cdefg"}, | 120 { "abcd cdef;abcd;abcd cdefg", "abc cde", "abcd cdef;abcd cdefg"}, |
122 | 121 |
123 // Exact and prefix match. | 122 // Exact and prefix match. |
124 { L"ab cdef;abcd;abcd cdefg", L"ab cdef", L"ab cdef"}, | 123 { "ab cdef;abcd;abcd cdefg", "ab cdef", "ab cdef"}, |
125 | 124 |
126 // Exact and prefix match. | 125 // Exact and prefix match. |
127 { L"ab cdef ghij;ab;cde;cdef;ghi;cdef ab;ghij ab", | 126 { "ab cdef ghij;ab;cde;cdef;ghi;cdef ab;ghij ab", |
128 L"ab cde ghi", | 127 "ab cde ghi", |
129 L"ab cdef ghij"}, | 128 "ab cdef ghij"}, |
130 | 129 |
131 // Title with term multiple times. | 130 // Title with term multiple times. |
132 { L"ab ab", L"ab", L"ab ab"}, | 131 { "ab ab", "ab", "ab ab"}, |
133 | 132 |
134 // Make sure quotes don't do a prefix match. | 133 // Make sure quotes don't do a prefix match. |
135 { L"think", L"\"thi\"", L""}, | 134 { "think", "\"thi\"", ""}, |
136 }; | 135 }; |
137 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { | 136 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { |
138 std::vector<std::wstring> titles; | 137 std::vector<std::string> titles; |
139 SplitString(data[i].input, L';', &titles); | 138 SplitString(data[i].input, ';', &titles); |
140 AddBookmarksWithTitles(titles); | 139 AddBookmarksWithTitles(titles); |
141 | 140 |
142 std::vector<std::wstring> expected; | 141 std::vector<std::string> expected; |
143 if (!data[i].expected.empty()) | 142 if (!data[i].expected.empty()) |
144 SplitString(data[i].expected, L';', &expected); | 143 SplitString(data[i].expected, ';', &expected); |
145 | 144 |
146 ExpectMatches(data[i].query, expected); | 145 ExpectMatches(data[i].query, expected); |
147 | 146 |
148 model_.reset(new BookmarkModel(NULL)); | 147 model_.reset(new BookmarkModel(NULL)); |
149 } | 148 } |
150 } | 149 } |
151 | 150 |
152 // Makes sure match positions are updated appropriately. | 151 // Makes sure match positions are updated appropriately. |
153 TEST_F(BookmarkIndexTest, MatchPositions) { | 152 TEST_F(BookmarkIndexTest, MatchPositions) { |
154 struct TestData { | 153 struct TestData { |
155 const std::wstring title; | 154 const std::string title; |
156 const std::wstring query; | 155 const std::string query; |
157 const std::string expected; | 156 const std::string expected; |
158 } data[] = { | 157 } data[] = { |
159 // Trivial test case of only one term, exact match. | 158 // Trivial test case of only one term, exact match. |
160 { L"a", L"A", "0,1" }, | 159 { "a", "A", "0,1" }, |
161 { L"foo bar", L"bar", "4,7" }, | 160 { "foo bar", "bar", "4,7" }, |
162 { L"fooey bark", L"bar foo", "0,3:6,9"}, | 161 { "fooey bark", "bar foo", "0,3:6,9"}, |
163 }; | 162 }; |
164 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { | 163 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { |
165 std::vector<std::wstring> titles; | 164 std::vector<std::string> titles; |
166 titles.push_back(data[i].title); | 165 titles.push_back(data[i].title); |
167 AddBookmarksWithTitles(titles); | 166 AddBookmarksWithTitles(titles); |
168 | 167 |
169 Snippet::MatchPositions expected_matches; | 168 Snippet::MatchPositions expected_matches; |
170 ExtractMatchPositions(data[i].expected, &expected_matches); | 169 ExtractMatchPositions(data[i].expected, &expected_matches); |
171 ExpectMatchPositions(data[i].query, expected_matches); | 170 ExpectMatchPositions(data[i].query, expected_matches); |
172 | 171 |
173 model_.reset(new BookmarkModel(NULL)); | 172 model_.reset(new BookmarkModel(NULL)); |
174 } | 173 } |
175 } | 174 } |
176 | 175 |
177 // Makes sure index is updated when a node is removed. | 176 // Makes sure index is updated when a node is removed. |
178 TEST_F(BookmarkIndexTest, Remove) { | 177 TEST_F(BookmarkIndexTest, Remove) { |
179 const wchar_t* input[] = { L"a", L"b" }; | 178 const char* input[] = { "a", "b" }; |
180 AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input)); | 179 AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input)); |
181 | 180 |
182 // Remove the node and make sure we don't get back any results. | 181 // Remove the node and make sure we don't get back any results. |
183 model_->Remove(model_->other_node(), 0); | 182 model_->Remove(model_->other_node(), 0); |
184 ExpectMatches(L"A", NULL, 0U); | 183 ExpectMatches("A", NULL, 0U); |
185 } | 184 } |
186 | 185 |
187 // Makes sure index is updated when a node's title is changed. | 186 // Makes sure index is updated when a node's title is changed. |
188 TEST_F(BookmarkIndexTest, ChangeTitle) { | 187 TEST_F(BookmarkIndexTest, ChangeTitle) { |
189 const wchar_t* input[] = { L"a", L"b" }; | 188 const char* input[] = { "a", "b" }; |
190 AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input)); | 189 AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input)); |
191 | 190 |
192 // Remove the node and make sure we don't get back any results. | 191 // Remove the node and make sure we don't get back any results. |
193 const wchar_t* expected[] = { L"blah" }; | 192 const char* expected[] = { "blah" }; |
194 model_->SetTitle(model_->other_node()->GetChild(0), ASCIIToUTF16("blah")); | 193 model_->SetTitle(model_->other_node()->GetChild(0), ASCIIToUTF16("blah")); |
195 ExpectMatches(L"BlAh", expected, ARRAYSIZE_UNSAFE(expected)); | 194 ExpectMatches("BlAh", expected, ARRAYSIZE_UNSAFE(expected)); |
196 } | 195 } |
197 | 196 |
198 // Makes sure no more than max queries is returned. | 197 // Makes sure no more than max queries is returned. |
199 TEST_F(BookmarkIndexTest, HonorMax) { | 198 TEST_F(BookmarkIndexTest, HonorMax) { |
200 const wchar_t* input[] = { L"abcd", L"abcde" }; | 199 const char* input[] = { "abcd", "abcde" }; |
201 AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input)); | 200 AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input)); |
202 | 201 |
203 std::vector<bookmark_utils::TitleMatch> matches; | 202 std::vector<bookmark_utils::TitleMatch> matches; |
204 model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16("ABc"), 1, &matches); | 203 model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16("ABc"), 1, &matches); |
205 EXPECT_EQ(1U, matches.size()); | 204 EXPECT_EQ(1U, matches.size()); |
206 } | 205 } |
207 | 206 |
208 // Makes sure if the lower case string of a bookmark title is more characters | 207 // Makes sure if the lower case string of a bookmark title is more characters |
209 // than the upper case string no match positions are returned. | 208 // than the upper case string no match positions are returned. |
210 TEST_F(BookmarkIndexTest, EmptyMatchOnMultiwideLowercaseString) { | 209 TEST_F(BookmarkIndexTest, EmptyMatchOnMultiwideLowercaseString) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 | 294 |
296 matches.clear(); | 295 matches.clear(); |
297 // Select top two matches. | 296 // Select top two matches. |
298 model->GetBookmarksWithTitlesMatching(ASCIIToUTF16("google"), 2, &matches); | 297 model->GetBookmarksWithTitlesMatching(ASCIIToUTF16("google"), 2, &matches); |
299 | 298 |
300 EXPECT_EQ(2, static_cast<int>(matches.size())); | 299 EXPECT_EQ(2, static_cast<int>(matches.size())); |
301 EXPECT_EQ(data[0].url, matches[0].node->GetURL()); | 300 EXPECT_EQ(data[0].url, matches[0].node->GetURL()); |
302 EXPECT_EQ(data[3].url, matches[1].node->GetURL()); | 301 EXPECT_EQ(data[3].url, matches[1].node->GetURL()); |
303 } | 302 } |
304 | 303 |
OLD | NEW |