mixer_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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 3// found in the LICENSE file. 4 5#include <string> 6 7#include "base/memory/scoped_vector.h" 8#include "base/strings/string16.h" 9#include "base/strings/stringprintf.h" 10#include "base/strings/utf_string_conversions.h" 11#include "chrome/browser/ui/app_list/search/chrome_search_result.h" 12#include "chrome/browser/ui/app_list/search/history_types.h" 13#include "chrome/browser/ui/app_list/search/mixer.h" 14#include "chrome/browser/ui/app_list/search/search_provider.h" 15#include "testing/gtest/include/gtest/gtest.h" 16#include "ui/app_list/app_list_model.h" 17 18namespace app_list { 19namespace test { 20 21class TestSearchResult : public ChromeSearchResult { 22 public: 23 TestSearchResult(const std::string& id, double relevance) { 24 set_id(id); 25 set_title(UTF8ToUTF16(id)); 26 set_relevance(relevance); 27 } 28 virtual ~TestSearchResult() {} 29 30 private: 31 // ChromeSearchResult overides: 32 virtual void Open(int event_flags) OVERRIDE {} 33 virtual void InvokeAction(int action_index, int event_flags) OVERRIDE {} 34 virtual scoped_ptr<ChromeSearchResult> Duplicate() OVERRIDE { 35 return scoped_ptr<ChromeSearchResult>( 36 new TestSearchResult(id(), relevance())).Pass(); 37 } 38 virtual ChromeSearchResultType GetType() OVERRIDE { 39 return SEARCH_RESULT_TYPE_BOUNDARY; 40 } 41 42 DISALLOW_COPY_AND_ASSIGN(TestSearchResult); 43}; 44 45class TestSearchProvider : public SearchProvider { 46 public: 47 explicit TestSearchProvider(const std::string& prefix) 48 : prefix_(prefix), 49 count_(0) {} 50 virtual ~TestSearchProvider() {} 51 52 // SearchProvider overrides: 53 virtual void Start(const base::string16& query) OVERRIDE { 54 ClearResults(); 55 for (size_t i = 0; i < count_; ++i) { 56 const std::string id = 57 base::StringPrintf("%s%d", prefix_.c_str(), static_cast<int>(i)); 58 const double relevance = 1.0 - i / 10.0; 59 Add(scoped_ptr<ChromeSearchResult>( 60 new TestSearchResult(id, relevance)).Pass()); 61 } 62 } 63 virtual void Stop() OVERRIDE {} 64 65 void set_prefix(const std::string& prefix) { prefix_ = prefix; } 66 void set_count(size_t count) { count_ = count; } 67 68 private: 69 std::string prefix_; 70 size_t count_; 71 72 DISALLOW_COPY_AND_ASSIGN(TestSearchProvider); 73}; 74 75class MixerTest : public testing::Test { 76 public: 77 MixerTest() {} 78 virtual ~MixerTest() {} 79 80 // testing::Test overrides: 81 virtual void SetUp() OVERRIDE { 82 results_.reset(new AppListModel::SearchResults); 83 84 providers_.push_back(new TestSearchProvider("app")); 85 providers_.push_back(new TestSearchProvider("omnibox")); 86 providers_.push_back(new TestSearchProvider("webstore")); 87 providers_.push_back(new TestSearchProvider("people")); 88 89 mixer_.reset(new Mixer(results_.get())); 90 mixer_->Init(); 91 mixer_->AddProviderToGroup(Mixer::MAIN_GROUP, providers_[0]); 92 mixer_->AddProviderToGroup(Mixer::OMNIBOX_GROUP, providers_[1]); 93 mixer_->AddProviderToGroup(Mixer::WEBSTORE_GROUP, providers_[2]); 94 mixer_->AddProviderToGroup(Mixer::PEOPLE_GROUP, providers_[3]); 95 } 96 97 void RunQuery() { 98 const base::string16 query; 99 100 for (size_t i = 0; i < providers_.size(); ++i) { 101 providers_[i]->Start(query); 102 providers_[i]->Stop(); 103 } 104 105 mixer_->MixAndPublish(KnownResults()); 106 } 107 108 std::string GetResults() const { 109 std::string result; 110 for (size_t i = 0; i < results_->item_count(); ++i) { 111 if (!result.empty()) 112 result += ','; 113 114 result += UTF16ToUTF8(results_->GetItemAt(i)->title()); 115 } 116 117 return result; 118 } 119 120 Mixer* mixer() { return mixer_.get(); } 121 TestSearchProvider* app_provider() { return providers_[0]; } 122 TestSearchProvider* omnibox_provider() { return providers_[1]; } 123 TestSearchProvider* webstore_provider() { return providers_[2]; } 124 125 private: 126 scoped_ptr<Mixer> mixer_; 127 scoped_ptr<AppListModel::SearchResults> results_; 128 129 ScopedVector<TestSearchProvider> providers_; 130 131 DISALLOW_COPY_AND_ASSIGN(MixerTest); 132}; 133 134TEST_F(MixerTest, Basic) { 135 struct TestCase { 136 const size_t app_results; 137 const size_t omnibox_results; 138 const size_t webstore_results; 139 const char* expected; 140 } kTestCases[] = { 141 {0, 0, 0, ""}, 142 {4, 6, 2, "app0,app1,app2,app3,omnibox0,webstore0"}, 143 {10, 10, 10, "app0,app1,app2,app3,omnibox0,webstore0"}, 144 {0, 10, 0, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5"}, 145 {0, 10, 1, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,webstore0"}, 146 {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, 147 {1, 10, 0, "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4"}, 148 {2, 10, 0, "app0,app1,omnibox0,omnibox1,omnibox2,omnibox3"}, 149 {2, 10, 1, "app0,app1,omnibox0,omnibox1,omnibox2,webstore0"}, 150 {2, 10, 2, "app0,app1,omnibox0,omnibox1,webstore0,webstore1"}, 151 {2, 0, 2, "app0,app1,webstore0,webstore1"}, 152 {0, 0, 0, ""}, 153 }; 154 155 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { 156 app_provider()->set_count(kTestCases[i].app_results); 157 omnibox_provider()->set_count(kTestCases[i].omnibox_results); 158 webstore_provider()->set_count(kTestCases[i].webstore_results); 159 RunQuery(); 160 161 EXPECT_EQ(kTestCases[i].expected, GetResults()) << "Case " << i; 162 } 163} 164 165TEST_F(MixerTest, RemoveDuplicates) { 166 const std::string dup = "dup"; 167 168 // This gives "dup0,dup1,dup2". 169 app_provider()->set_prefix(dup); 170 app_provider()->set_count(3); 171 172 // This gives "dup0,dup1". 173 omnibox_provider()->set_prefix(dup); 174 omnibox_provider()->set_count(2); 175 176 // This gives "dup0". 177 webstore_provider()->set_prefix(dup); 178 webstore_provider()->set_count(1); 179 180 RunQuery(); 181 182 // Only three results with unique id are kept. 183 EXPECT_EQ("dup0,dup1,dup2", GetResults()); 184} 185 186} // namespace test 187} // namespace app_list 188