| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "ui/app_list/search/mixer.h" | 5 #include "ui/app_list/search/mixer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "ui/app_list/search_result.h" | 24 #include "ui/app_list/search_result.h" |
| 25 | 25 |
| 26 namespace app_list { | 26 namespace app_list { |
| 27 namespace test { | 27 namespace test { |
| 28 | 28 |
| 29 // Maximum number of results to show in each mixer group. | 29 // Maximum number of results to show in each mixer group. |
| 30 const size_t kMaxAppsGroupResults = 4; | 30 const size_t kMaxAppsGroupResults = 4; |
| 31 // Ignored unless AppListMixer field trial is "Blended". | 31 // Ignored unless AppListMixer field trial is "Blended". |
| 32 const size_t kMaxOmniboxResults = 4; | 32 const size_t kMaxOmniboxResults = 4; |
| 33 const size_t kMaxWebstoreResults = 2; | 33 const size_t kMaxWebstoreResults = 2; |
| 34 const size_t kMaxPeopleResults = 2; | |
| 35 | 34 |
| 36 class TestSearchResult : public SearchResult { | 35 class TestSearchResult : public SearchResult { |
| 37 public: | 36 public: |
| 38 TestSearchResult(const std::string& id, double relevance) | 37 TestSearchResult(const std::string& id, double relevance) |
| 39 : instance_id_(instantiation_count++) { | 38 : instance_id_(instantiation_count++) { |
| 40 set_id(id); | 39 set_id(id); |
| 41 set_title(base::UTF8ToUTF16(id)); | 40 set_title(base::UTF8ToUTF16(id)); |
| 42 set_relevance(relevance); | 41 set_relevance(relevance); |
| 43 } | 42 } |
| 44 ~TestSearchResult() override {} | 43 ~TestSearchResult() override {} |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 void SetUp() override { | 128 void SetUp() override { |
| 130 // If the parameter is true, enable the field trial. | 129 // If the parameter is true, enable the field trial. |
| 131 const char* field_trial_name = GetParam() ? "Blended" : "Control"; | 130 const char* field_trial_name = GetParam() ? "Blended" : "Control"; |
| 132 base::FieldTrialList::CreateFieldTrial("AppListMixer", field_trial_name); | 131 base::FieldTrialList::CreateFieldTrial("AppListMixer", field_trial_name); |
| 133 | 132 |
| 134 results_.reset(new AppListModel::SearchResults); | 133 results_.reset(new AppListModel::SearchResults); |
| 135 | 134 |
| 136 providers_.push_back(new TestSearchProvider("app")); | 135 providers_.push_back(new TestSearchProvider("app")); |
| 137 providers_.push_back(new TestSearchProvider("omnibox")); | 136 providers_.push_back(new TestSearchProvider("omnibox")); |
| 138 providers_.push_back(new TestSearchProvider("webstore")); | 137 providers_.push_back(new TestSearchProvider("webstore")); |
| 139 providers_.push_back(new TestSearchProvider("people")); | |
| 140 | 138 |
| 141 is_voice_query_ = false; | 139 is_voice_query_ = false; |
| 142 | 140 |
| 143 mixer_.reset(new Mixer(results_.get())); | 141 mixer_.reset(new Mixer(results_.get())); |
| 144 | 142 |
| 145 size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 3.0, 1.0); | 143 size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 3.0, 1.0); |
| 146 size_t omnibox_group_id = | 144 size_t omnibox_group_id = |
| 147 mixer_->AddOmniboxGroup(kMaxOmniboxResults, 2.0, 1.0); | 145 mixer_->AddOmniboxGroup(kMaxOmniboxResults, 2.0, 1.0); |
| 148 size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 1.0, 0.5); | 146 size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 1.0, 0.5); |
| 149 size_t people_group_id = mixer_->AddGroup(kMaxPeopleResults, 0.0, 1.0); | |
| 150 | 147 |
| 151 mixer_->AddProviderToGroup(apps_group_id, providers_[0]); | 148 mixer_->AddProviderToGroup(apps_group_id, providers_[0]); |
| 152 mixer_->AddProviderToGroup(omnibox_group_id, providers_[1]); | 149 mixer_->AddProviderToGroup(omnibox_group_id, providers_[1]); |
| 153 mixer_->AddProviderToGroup(webstore_group_id, providers_[2]); | 150 mixer_->AddProviderToGroup(webstore_group_id, providers_[2]); |
| 154 mixer_->AddProviderToGroup(people_group_id, providers_[3]); | |
| 155 } | 151 } |
| 156 | 152 |
| 157 void RunQuery() { | 153 void RunQuery() { |
| 158 const base::string16 query; | 154 const base::string16 query; |
| 159 | 155 |
| 160 for (size_t i = 0; i < providers_.size(); ++i) { | 156 for (size_t i = 0; i < providers_.size(); ++i) { |
| 161 providers_[i]->Start(is_voice_query_, query); | 157 providers_[i]->Start(is_voice_query_, query); |
| 162 providers_[i]->Stop(); | 158 providers_[i]->Stop(); |
| 163 } | 159 } |
| 164 | 160 |
| 165 mixer_->MixAndPublish(is_voice_query_, known_results_); | 161 mixer_->MixAndPublish(is_voice_query_, known_results_); |
| 166 } | 162 } |
| 167 | 163 |
| 168 std::string GetResults() const { | 164 std::string GetResults() const { |
| 169 std::string result; | 165 std::string result; |
| 170 for (size_t i = 0; i < results_->item_count(); ++i) { | 166 for (size_t i = 0; i < results_->item_count(); ++i) { |
| 171 if (!result.empty()) | 167 if (!result.empty()) |
| 172 result += ','; | 168 result += ','; |
| 173 | 169 |
| 174 result += base::UTF16ToUTF8(results_->GetItemAt(i)->title()); | 170 result += base::UTF16ToUTF8(results_->GetItemAt(i)->title()); |
| 175 } | 171 } |
| 176 | 172 |
| 177 return result; | 173 return result; |
| 178 } | 174 } |
| 179 | 175 |
| 180 Mixer* mixer() { return mixer_.get(); } | 176 Mixer* mixer() { return mixer_.get(); } |
| 181 TestSearchProvider* app_provider() { return providers_[0]; } | 177 TestSearchProvider* app_provider() { return providers_[0]; } |
| 182 TestSearchProvider* omnibox_provider() { return providers_[1]; } | 178 TestSearchProvider* omnibox_provider() { return providers_[1]; } |
| 183 TestSearchProvider* webstore_provider() { return providers_[2]; } | 179 TestSearchProvider* webstore_provider() { return providers_[2]; } |
| 184 TestSearchProvider* people_provider() { return providers_[3]; } | |
| 185 | 180 |
| 186 // Sets whether test runs should be treated as a voice query. | 181 // Sets whether test runs should be treated as a voice query. |
| 187 void set_is_voice_query(bool is_voice_query) { | 182 void set_is_voice_query(bool is_voice_query) { |
| 188 is_voice_query_ = is_voice_query; | 183 is_voice_query_ = is_voice_query; |
| 189 } | 184 } |
| 190 | 185 |
| 191 void AddKnownResult(const std::string& id, KnownResultType type) { | 186 void AddKnownResult(const std::string& id, KnownResultType type) { |
| 192 known_results_[id] = type; | 187 known_results_[id] = type; |
| 193 } | 188 } |
| 194 | 189 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 208 | 203 |
| 209 TEST_P(MixerTest, Basic) { | 204 TEST_P(MixerTest, Basic) { |
| 210 // Note: Some cases in |expected_blended| have vastly more results than | 205 // Note: Some cases in |expected_blended| have vastly more results than |
| 211 // others, due to the "at least 6" mechanism. If it gets at least 6 results | 206 // others, due to the "at least 6" mechanism. If it gets at least 6 results |
| 212 // from all providers, it stops at 6. If not, it fetches potentially many more | 207 // from all providers, it stops at 6. If not, it fetches potentially many more |
| 213 // results from all providers. Not ideal, but currently by design. | 208 // results from all providers. Not ideal, but currently by design. |
| 214 struct TestCase { | 209 struct TestCase { |
| 215 const size_t app_results; | 210 const size_t app_results; |
| 216 const size_t omnibox_results; | 211 const size_t omnibox_results; |
| 217 const size_t webstore_results; | 212 const size_t webstore_results; |
| 218 const size_t people_results; | |
| 219 const char* expected_default; // Expected results with trial off. | 213 const char* expected_default; // Expected results with trial off. |
| 220 const char* expected_blended; // Expected results with trial on. | 214 const char* expected_blended; // Expected results with trial on. |
| 221 } kTestCases[] = { | 215 } kTestCases[] = { |
| 222 {0, 0, 0, 0, "", ""}, | 216 {0, 0, 0, "", ""}, |
| 223 {10, | 217 {10, 0, 0, "app0,app1,app2,app3", |
| 224 0, | |
| 225 0, | |
| 226 0, | |
| 227 "app0,app1,app2,app3", | |
| 228 "app0,app1,app2,app3,app4,app5,app6,app7,app8,app9"}, | 218 "app0,app1,app2,app3,app4,app5,app6,app7,app8,app9"}, |
| 229 {0, | 219 {0, 0, 10, "webstore0,webstore1", |
| 230 0, | |
| 231 10, | |
| 232 0, | |
| 233 "webstore0,webstore1", | |
| 234 "webstore0,webstore1,webstore2,webstore3,webstore4,webstore5,webstore6," | 220 "webstore0,webstore1,webstore2,webstore3,webstore4,webstore5,webstore6," |
| 235 "webstore7,webstore8,webstore9"}, | 221 "webstore7,webstore8,webstore9"}, |
| 236 {0, | 222 {4, 6, 0, "app0,app1,app2,app3,omnibox0,omnibox1", |
| 237 0, | |
| 238 0, | |
| 239 10, | |
| 240 "people0,people1", | |
| 241 "people0,people1,people2,people3,people4,people5,people6,people7," | |
| 242 "people8,people9"}, | |
| 243 {4, | |
| 244 6, | |
| 245 0, | |
| 246 0, | |
| 247 "app0,app1,app2,app3,omnibox0,omnibox1", | |
| 248 "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3"}, | 223 "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3"}, |
| 249 {4, | 224 {4, 6, 2, "app0,app1,app2,app3,omnibox0,webstore0", |
| 250 6, | |
| 251 2, | |
| 252 0, | |
| 253 "app0,app1,app2,app3,omnibox0,webstore0", | |
| 254 "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0," | 225 "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0," |
| 255 "webstore1"}, | 226 "webstore1"}, |
| 256 {4, | 227 {10, 10, 10, "app0,app1,app2,app3,omnibox0,webstore0", |
| 257 6, | |
| 258 0, | |
| 259 2, | |
| 260 "app0,app1,app2,app3,omnibox0,people0", | |
| 261 "app0,omnibox0,people0,app1,omnibox1,people1,app2,omnibox2,app3," | |
| 262 "omnibox3"}, | |
| 263 {10, | |
| 264 10, | |
| 265 10, | |
| 266 0, | |
| 267 "app0,app1,app2,app3,omnibox0,webstore0", | |
| 268 "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0," | 228 "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0," |
| 269 "webstore1"}, | 229 "webstore1"}, |
| 270 {0, | 230 {0, 10, 0, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5", |
| 271 10, | |
| 272 0, | |
| 273 0, | |
| 274 "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5", | |
| 275 "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6," | 231 "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6," |
| 276 "omnibox7,omnibox8,omnibox9"}, | 232 "omnibox7,omnibox8,omnibox9"}, |
| 277 {0, | 233 {0, 10, 1, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,webstore0", |
| 278 10, | |
| 279 1, | |
| 280 0, | |
| 281 "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,webstore0", | |
| 282 "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,omnibox4,omnibox5," | 234 "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,omnibox4,omnibox5," |
| 283 "omnibox6,omnibox7,omnibox8,omnibox9"}, | 235 "omnibox6,omnibox7,omnibox8,omnibox9"}, |
| 284 {0, | 236 {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1", |
| 285 10, | |
| 286 2, | |
| 287 0, | |
| 288 "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1", | |
| 289 "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, | 237 "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, |
| 290 {1, | 238 {1, 10, 0, "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4", |
| 291 10, | |
| 292 0, | |
| 293 0, | |
| 294 "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4", | |
| 295 "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6," | 239 "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6," |
| 296 "omnibox7,omnibox8,omnibox9"}, | 240 "omnibox7,omnibox8,omnibox9"}, |
| 297 {2, | 241 {2, 10, 0, "app0,app1,omnibox0,omnibox1,omnibox2,omnibox3", |
| 298 10, | |
| 299 0, | |
| 300 0, | |
| 301 "app0,app1,omnibox0,omnibox1,omnibox2,omnibox3", | |
| 302 "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3"}, | 242 "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3"}, |
| 303 {2, | 243 {2, 10, 1, "app0,app1,omnibox0,omnibox1,omnibox2,webstore0", |
| 304 10, | |
| 305 1, | |
| 306 0, | |
| 307 "app0,app1,omnibox0,omnibox1,omnibox2,webstore0", | |
| 308 "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0"}, | 244 "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0"}, |
| 309 {2, | 245 {2, 10, 2, "app0,app1,omnibox0,omnibox1,webstore0,webstore1", |
| 310 10, | |
| 311 2, | |
| 312 0, | |
| 313 "app0,app1,omnibox0,omnibox1,webstore0,webstore1", | |
| 314 "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, | 246 "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, |
| 315 {2, | 247 {2, 0, 2, "app0,app1,webstore0,webstore1", |
| 316 0, | |
| 317 2, | |
| 318 0, | |
| 319 "app0,app1,webstore0,webstore1", | |
| 320 "app0,app1,webstore0,webstore1"}, | 248 "app0,app1,webstore0,webstore1"}, |
| 321 {10, | 249 {0, 0, 0, "", ""}, |
| 322 0, | |
| 323 10, | |
| 324 10, | |
| 325 "app0,app1,app2,app3,webstore0,webstore1", | |
| 326 "app0,people0,app1,people1,app2,app3,webstore0,webstore1"}, | |
| 327 {10, | |
| 328 10, | |
| 329 10, | |
| 330 10, | |
| 331 "app0,app1,app2,app3,omnibox0,webstore0", | |
| 332 "app0,omnibox0,people0,app1,omnibox1,people1,app2,omnibox2,app3," | |
| 333 "omnibox3,webstore0,webstore1"}, | |
| 334 {0, 0, 0, 0, "", ""}, | |
| 335 }; | 250 }; |
| 336 | 251 |
| 337 for (size_t i = 0; i < arraysize(kTestCases); ++i) { | 252 for (size_t i = 0; i < arraysize(kTestCases); ++i) { |
| 338 app_provider()->set_count(kTestCases[i].app_results); | 253 app_provider()->set_count(kTestCases[i].app_results); |
| 339 omnibox_provider()->set_count(kTestCases[i].omnibox_results); | 254 omnibox_provider()->set_count(kTestCases[i].omnibox_results); |
| 340 webstore_provider()->set_count(kTestCases[i].webstore_results); | 255 webstore_provider()->set_count(kTestCases[i].webstore_results); |
| 341 people_provider()->set_count(kTestCases[i].people_results); | |
| 342 RunQuery(); | 256 RunQuery(); |
| 343 | 257 |
| 344 const char* expected = GetParam() ? kTestCases[i].expected_blended | 258 const char* expected = GetParam() ? kTestCases[i].expected_blended |
| 345 : kTestCases[i].expected_default; | 259 : kTestCases[i].expected_default; |
| 346 EXPECT_EQ(expected, GetResults()) << "Case " << i; | 260 EXPECT_EQ(expected, GetResults()) << "Case " << i; |
| 347 } | 261 } |
| 348 } | 262 } |
| 349 | 263 |
| 350 TEST_P(MixerTest, RemoveDuplicates) { | 264 TEST_P(MixerTest, RemoveDuplicates) { |
| 351 const std::string dup = "dup"; | 265 const std::string dup = "dup"; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 set_is_voice_query(true); | 335 set_is_voice_query(true); |
| 422 RunQuery(); | 336 RunQuery(); |
| 423 EXPECT_EQ("omnibox1,omnibox0,omnibox2", GetResults()); | 337 EXPECT_EQ("omnibox1,omnibox0,omnibox2", GetResults()); |
| 424 | 338 |
| 425 // All voice results should appear before non-voice results. | 339 // All voice results should appear before non-voice results. |
| 426 omnibox_provider()->set_as_voice_result(2); | 340 omnibox_provider()->set_as_voice_result(2); |
| 427 RunQuery(); | 341 RunQuery(); |
| 428 EXPECT_EQ("omnibox1,omnibox2,omnibox0", GetResults()); | 342 EXPECT_EQ("omnibox1,omnibox2,omnibox0", GetResults()); |
| 429 } | 343 } |
| 430 | 344 |
| 431 TEST_P(MixerTest, BadRelevanceRange) { | |
| 432 // This gives relevance scores: (10.0, 0.0). Even though providers are | |
| 433 // supposed to give scores within the range [0.0, 1.0], we cannot rely on | |
| 434 // providers to do this, since they retrieve results from disparate and | |
| 435 // unreliable sources (like the Google+ API). | |
| 436 people_provider()->set_bad_relevance_range(); | |
| 437 people_provider()->set_count(2); | |
| 438 | |
| 439 // Give a massive boost to the second result. | |
| 440 AddKnownResult("people1", PERFECT_PRIMARY); | |
| 441 | |
| 442 RunQuery(); | |
| 443 | |
| 444 // If the results are correctly clamped to the range [0.0, 1.0], the boost to | |
| 445 // "people1" will push it over the first result. If not, the massive base | |
| 446 // score of "people0" will erroneously keep it on top. | |
| 447 EXPECT_EQ("people1,people0", GetResults()); | |
| 448 } | |
| 449 | |
| 450 TEST_P(MixerTest, Publish) { | 345 TEST_P(MixerTest, Publish) { |
| 451 std::unique_ptr<SearchResult> result1(new TestSearchResult("app1", 0)); | 346 std::unique_ptr<SearchResult> result1(new TestSearchResult("app1", 0)); |
| 452 std::unique_ptr<SearchResult> result2(new TestSearchResult("app2", 0)); | 347 std::unique_ptr<SearchResult> result2(new TestSearchResult("app2", 0)); |
| 453 std::unique_ptr<SearchResult> result3(new TestSearchResult("app3", 0)); | 348 std::unique_ptr<SearchResult> result3(new TestSearchResult("app3", 0)); |
| 454 std::unique_ptr<SearchResult> result3_copy = result3->Duplicate(); | 349 std::unique_ptr<SearchResult> result3_copy = result3->Duplicate(); |
| 455 std::unique_ptr<SearchResult> result4(new TestSearchResult("app4", 0)); | 350 std::unique_ptr<SearchResult> result4(new TestSearchResult("app4", 0)); |
| 456 std::unique_ptr<SearchResult> result5(new TestSearchResult("app5", 0)); | 351 std::unique_ptr<SearchResult> result5(new TestSearchResult("app5", 0)); |
| 457 | 352 |
| 458 AppListModel::SearchResults ui_results; | 353 AppListModel::SearchResults ui_results; |
| 459 | 354 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 EXPECT_EQ(old_ui_result_ids[1], | 427 EXPECT_EQ(old_ui_result_ids[1], |
| 533 TestSearchResult::GetInstanceId(ui_results.GetItemAt(0))); | 428 TestSearchResult::GetInstanceId(ui_results.GetItemAt(0))); |
| 534 EXPECT_EQ(old_ui_result_ids[2], | 429 EXPECT_EQ(old_ui_result_ids[2], |
| 535 TestSearchResult::GetInstanceId(ui_results.GetItemAt(2))); | 430 TestSearchResult::GetInstanceId(ui_results.GetItemAt(2))); |
| 536 } | 431 } |
| 537 | 432 |
| 538 INSTANTIATE_TEST_CASE_P(MixerTestInstance, MixerTest, testing::Bool()); | 433 INSTANTIATE_TEST_CASE_P(MixerTestInstance, MixerTest, testing::Bool()); |
| 539 | 434 |
| 540 } // namespace test | 435 } // namespace test |
| 541 } // namespace app_list | 436 } // namespace app_list |
| OLD | NEW |