| 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 <set> |
| 5 #include <string> | 6 #include <string> |
| 6 | 7 |
| 7 #include "base/memory/scoped_vector.h" | 8 #include "base/memory/scoped_vector.h" |
| 8 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
| 9 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "ui/app_list/app_list_model.h" | 13 #include "ui/app_list/app_list_model.h" |
| 13 #include "ui/app_list/search/history_types.h" | 14 #include "ui/app_list/search/history_types.h" |
| 14 #include "ui/app_list/search/mixer.h" | 15 #include "ui/app_list/search/mixer.h" |
| 15 #include "ui/app_list/search_provider.h" | 16 #include "ui/app_list/search_provider.h" |
| 16 #include "ui/app_list/search_result.h" | 17 #include "ui/app_list/search_result.h" |
| 17 | 18 |
| 18 namespace app_list { | 19 namespace app_list { |
| 19 namespace test { | 20 namespace test { |
| 20 | 21 |
| 21 class TestSearchResult : public SearchResult { | 22 class TestSearchResult : public SearchResult { |
| 22 public: | 23 public: |
| 23 TestSearchResult(const std::string& id, double relevance) | 24 TestSearchResult(const std::string& id, double relevance) |
| 24 : instance_id_(instantiation_count++) { | 25 : instance_id_(instantiation_count++) { |
| 25 set_id(id); | 26 set_id(id); |
| 26 set_title(base::UTF8ToUTF16(id)); | 27 set_title(base::UTF8ToUTF16(id)); |
| 27 set_relevance(relevance); | 28 set_relevance(relevance); |
| 28 } | 29 } |
| 29 ~TestSearchResult() override {} | 30 ~TestSearchResult() override {} |
| 30 | 31 |
| 32 using SearchResult::set_voice_result; |
| 33 |
| 31 // SearchResult overrides: | 34 // SearchResult overrides: |
| 32 void Open(int event_flags) override {} | 35 void Open(int event_flags) override {} |
| 33 void InvokeAction(int action_index, int event_flags) override {} | 36 void InvokeAction(int action_index, int event_flags) override {} |
| 34 scoped_ptr<SearchResult> Duplicate() override { | 37 scoped_ptr<SearchResult> Duplicate() override { |
| 35 return scoped_ptr<SearchResult>(new TestSearchResult(id(), relevance())); | 38 return scoped_ptr<SearchResult>(new TestSearchResult(id(), relevance())); |
| 36 } | 39 } |
| 37 | 40 |
| 38 // For reference equality testing. (Addresses cannot be used to test reference | 41 // For reference equality testing. (Addresses cannot be used to test reference |
| 39 // equality because it is possible that an object will be allocated at the | 42 // equality because it is possible that an object will be allocated at the |
| 40 // same address as a previously deleted one.) | 43 // same address as a previously deleted one.) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 57 : prefix_(prefix), count_(0) {} | 60 : prefix_(prefix), count_(0) {} |
| 58 ~TestSearchProvider() override {} | 61 ~TestSearchProvider() override {} |
| 59 | 62 |
| 60 // SearchProvider overrides: | 63 // SearchProvider overrides: |
| 61 void Start(const base::string16& query) override { | 64 void Start(const base::string16& query) override { |
| 62 ClearResults(); | 65 ClearResults(); |
| 63 for (size_t i = 0; i < count_; ++i) { | 66 for (size_t i = 0; i < count_; ++i) { |
| 64 const std::string id = | 67 const std::string id = |
| 65 base::StringPrintf("%s%d", prefix_.c_str(), static_cast<int>(i)); | 68 base::StringPrintf("%s%d", prefix_.c_str(), static_cast<int>(i)); |
| 66 const double relevance = 1.0 - i / 10.0; | 69 const double relevance = 1.0 - i / 10.0; |
| 67 Add(scoped_ptr<SearchResult>(new TestSearchResult(id, relevance)).Pass()); | 70 TestSearchResult* result = new TestSearchResult(id, relevance); |
| 71 if (voice_result_indices.find(i) != voice_result_indices.end()) |
| 72 result->set_voice_result(true); |
| 73 Add(scoped_ptr<SearchResult>(result).Pass()); |
| 68 } | 74 } |
| 69 } | 75 } |
| 70 void Stop() override {} | 76 void Stop() override {} |
| 71 | 77 |
| 72 void set_prefix(const std::string& prefix) { prefix_ = prefix; } | 78 void set_prefix(const std::string& prefix) { prefix_ = prefix; } |
| 73 void set_count(size_t count) { count_ = count; } | 79 void set_count(size_t count) { count_ = count; } |
| 80 void set_as_voice_result(size_t index) { voice_result_indices.insert(index); } |
| 74 | 81 |
| 75 private: | 82 private: |
| 76 std::string prefix_; | 83 std::string prefix_; |
| 77 size_t count_; | 84 size_t count_; |
| 85 // Indices of results that will have the |voice_result| flag set. |
| 86 std::set<size_t> voice_result_indices; |
| 78 | 87 |
| 79 DISALLOW_COPY_AND_ASSIGN(TestSearchProvider); | 88 DISALLOW_COPY_AND_ASSIGN(TestSearchProvider); |
| 80 }; | 89 }; |
| 81 | 90 |
| 82 class MixerTest : public testing::Test { | 91 class MixerTest : public testing::Test { |
| 83 public: | 92 public: |
| 84 MixerTest() {} | 93 MixerTest() : is_voice_query_(false) {} |
| 85 ~MixerTest() override {} | 94 ~MixerTest() override {} |
| 86 | 95 |
| 87 // testing::Test overrides: | 96 // testing::Test overrides: |
| 88 void SetUp() override { | 97 void SetUp() override { |
| 89 results_.reset(new AppListModel::SearchResults); | 98 results_.reset(new AppListModel::SearchResults); |
| 90 | 99 |
| 91 providers_.push_back(new TestSearchProvider("app")); | 100 providers_.push_back(new TestSearchProvider("app")); |
| 92 providers_.push_back(new TestSearchProvider("omnibox")); | 101 providers_.push_back(new TestSearchProvider("omnibox")); |
| 93 providers_.push_back(new TestSearchProvider("webstore")); | 102 providers_.push_back(new TestSearchProvider("webstore")); |
| 94 providers_.push_back(new TestSearchProvider("people")); | 103 providers_.push_back(new TestSearchProvider("people")); |
| 95 | 104 |
| 105 is_voice_query_ = false; |
| 106 |
| 96 mixer_.reset(new Mixer(results_.get())); | 107 mixer_.reset(new Mixer(results_.get())); |
| 97 mixer_->Init(); | 108 mixer_->Init(); |
| 98 mixer_->AddProviderToGroup(Mixer::MAIN_GROUP, providers_[0]); | 109 mixer_->AddProviderToGroup(Mixer::MAIN_GROUP, providers_[0]); |
| 99 mixer_->AddProviderToGroup(Mixer::OMNIBOX_GROUP, providers_[1]); | 110 mixer_->AddProviderToGroup(Mixer::OMNIBOX_GROUP, providers_[1]); |
| 100 mixer_->AddProviderToGroup(Mixer::WEBSTORE_GROUP, providers_[2]); | 111 mixer_->AddProviderToGroup(Mixer::WEBSTORE_GROUP, providers_[2]); |
| 101 mixer_->AddProviderToGroup(Mixer::PEOPLE_GROUP, providers_[3]); | 112 mixer_->AddProviderToGroup(Mixer::PEOPLE_GROUP, providers_[3]); |
| 102 } | 113 } |
| 103 | 114 |
| 104 void RunQuery() { | 115 void RunQuery() { |
| 105 const base::string16 query; | 116 const base::string16 query; |
| 106 | 117 |
| 107 for (size_t i = 0; i < providers_.size(); ++i) { | 118 for (size_t i = 0; i < providers_.size(); ++i) { |
| 108 providers_[i]->Start(query); | 119 providers_[i]->Start(query); |
| 109 providers_[i]->Stop(); | 120 providers_[i]->Stop(); |
| 110 } | 121 } |
| 111 | 122 |
| 112 mixer_->MixAndPublish(KnownResults()); | 123 mixer_->MixAndPublish(is_voice_query_, KnownResults()); |
| 113 } | 124 } |
| 114 | 125 |
| 115 std::string GetResults() const { | 126 std::string GetResults() const { |
| 116 std::string result; | 127 std::string result; |
| 117 for (size_t i = 0; i < results_->item_count(); ++i) { | 128 for (size_t i = 0; i < results_->item_count(); ++i) { |
| 118 if (!result.empty()) | 129 if (!result.empty()) |
| 119 result += ','; | 130 result += ','; |
| 120 | 131 |
| 121 result += base::UTF16ToUTF8(results_->GetItemAt(i)->title()); | 132 result += base::UTF16ToUTF8(results_->GetItemAt(i)->title()); |
| 122 } | 133 } |
| 123 | 134 |
| 124 return result; | 135 return result; |
| 125 } | 136 } |
| 126 | 137 |
| 127 Mixer* mixer() { return mixer_.get(); } | 138 Mixer* mixer() { return mixer_.get(); } |
| 128 TestSearchProvider* app_provider() { return providers_[0]; } | 139 TestSearchProvider* app_provider() { return providers_[0]; } |
| 129 TestSearchProvider* omnibox_provider() { return providers_[1]; } | 140 TestSearchProvider* omnibox_provider() { return providers_[1]; } |
| 130 TestSearchProvider* webstore_provider() { return providers_[2]; } | 141 TestSearchProvider* webstore_provider() { return providers_[2]; } |
| 131 TestSearchProvider* people_provider() { return providers_[3]; } | 142 TestSearchProvider* people_provider() { return providers_[3]; } |
| 132 | 143 |
| 144 // Sets whether test runs should be treated as a voice query. |
| 145 void set_is_voice_query(bool is_voice_query) { |
| 146 is_voice_query_ = is_voice_query; |
| 147 } |
| 148 |
| 133 private: | 149 private: |
| 134 scoped_ptr<Mixer> mixer_; | 150 scoped_ptr<Mixer> mixer_; |
| 135 scoped_ptr<AppListModel::SearchResults> results_; | 151 scoped_ptr<AppListModel::SearchResults> results_; |
| 136 | 152 |
| 153 bool is_voice_query_; |
| 154 |
| 137 ScopedVector<TestSearchProvider> providers_; | 155 ScopedVector<TestSearchProvider> providers_; |
| 138 | 156 |
| 139 DISALLOW_COPY_AND_ASSIGN(MixerTest); | 157 DISALLOW_COPY_AND_ASSIGN(MixerTest); |
| 140 }; | 158 }; |
| 141 | 159 |
| 142 TEST_F(MixerTest, Basic) { | 160 TEST_F(MixerTest, Basic) { |
| 143 struct TestCase { | 161 struct TestCase { |
| 144 const size_t app_results; | 162 const size_t app_results; |
| 145 const size_t omnibox_results; | 163 const size_t omnibox_results; |
| 146 const size_t webstore_results; | 164 const size_t webstore_results; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 // This gives "dup0". | 211 // This gives "dup0". |
| 194 webstore_provider()->set_prefix(dup); | 212 webstore_provider()->set_prefix(dup); |
| 195 webstore_provider()->set_count(1); | 213 webstore_provider()->set_count(1); |
| 196 | 214 |
| 197 RunQuery(); | 215 RunQuery(); |
| 198 | 216 |
| 199 // Only three results with unique id are kept. | 217 // Only three results with unique id are kept. |
| 200 EXPECT_EQ("dup0,dup1,dup2", GetResults()); | 218 EXPECT_EQ("dup0,dup1,dup2", GetResults()); |
| 201 } | 219 } |
| 202 | 220 |
| 221 TEST_F(MixerTest, VoiceQuery) { |
| 222 omnibox_provider()->set_count(3); |
| 223 RunQuery(); |
| 224 EXPECT_EQ("omnibox0,omnibox1,omnibox2", GetResults()); |
| 225 |
| 226 // Set "omnibox1" as a voice result. Do not expect any changes (as this is not |
| 227 // a voice query). |
| 228 omnibox_provider()->set_as_voice_result(1); |
| 229 RunQuery(); |
| 230 EXPECT_EQ("omnibox0,omnibox1,omnibox2", GetResults()); |
| 231 |
| 232 // Perform a voice query. Expect voice result first. |
| 233 set_is_voice_query(true); |
| 234 RunQuery(); |
| 235 EXPECT_EQ("omnibox1,omnibox0,omnibox2", GetResults()); |
| 236 |
| 237 // All voice results should appear before non-voice results. |
| 238 omnibox_provider()->set_as_voice_result(2); |
| 239 RunQuery(); |
| 240 EXPECT_EQ("omnibox1,omnibox2,omnibox0", GetResults()); |
| 241 } |
| 242 |
| 203 TEST_F(MixerTest, Publish) { | 243 TEST_F(MixerTest, Publish) { |
| 204 scoped_ptr<SearchResult> result1(new TestSearchResult("app1", 0)); | 244 scoped_ptr<SearchResult> result1(new TestSearchResult("app1", 0)); |
| 205 scoped_ptr<SearchResult> result2(new TestSearchResult("app2", 0)); | 245 scoped_ptr<SearchResult> result2(new TestSearchResult("app2", 0)); |
| 206 scoped_ptr<SearchResult> result3(new TestSearchResult("app3", 0)); | 246 scoped_ptr<SearchResult> result3(new TestSearchResult("app3", 0)); |
| 207 scoped_ptr<SearchResult> result3_copy = result3->Duplicate(); | 247 scoped_ptr<SearchResult> result3_copy = result3->Duplicate(); |
| 208 scoped_ptr<SearchResult> result4(new TestSearchResult("app4", 0)); | 248 scoped_ptr<SearchResult> result4(new TestSearchResult("app4", 0)); |
| 209 scoped_ptr<SearchResult> result5(new TestSearchResult("app5", 0)); | 249 scoped_ptr<SearchResult> result5(new TestSearchResult("app5", 0)); |
| 210 | 250 |
| 211 AppListModel::SearchResults ui_results; | 251 AppListModel::SearchResults ui_results; |
| 212 | 252 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 EXPECT_EQ(old_ui_result_ids[0], | 323 EXPECT_EQ(old_ui_result_ids[0], |
| 284 TestSearchResult::GetInstanceId(ui_results.GetItemAt(3))); | 324 TestSearchResult::GetInstanceId(ui_results.GetItemAt(3))); |
| 285 EXPECT_EQ(old_ui_result_ids[1], | 325 EXPECT_EQ(old_ui_result_ids[1], |
| 286 TestSearchResult::GetInstanceId(ui_results.GetItemAt(0))); | 326 TestSearchResult::GetInstanceId(ui_results.GetItemAt(0))); |
| 287 EXPECT_EQ(old_ui_result_ids[2], | 327 EXPECT_EQ(old_ui_result_ids[2], |
| 288 TestSearchResult::GetInstanceId(ui_results.GetItemAt(2))); | 328 TestSearchResult::GetInstanceId(ui_results.GetItemAt(2))); |
| 289 } | 329 } |
| 290 | 330 |
| 291 } // namespace test | 331 } // namespace test |
| 292 } // namespace app_list | 332 } // namespace app_list |
| OLD | NEW |