mixer_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 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)
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string>
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string16.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/stringprintf.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_list/search/history_types.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/app_list/search/mixer.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/app_list/search/search_provider.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/app_list/app_list_model.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace app_list {
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSearchResult : public ChromeSearchResult {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSearchResult(const std::string& id, double relevance) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_id(id);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_title(UTF8ToUTF16(id));
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set_relevance(relevance);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSearchResult() {}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeSearchResult overides:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Open(int event_flags) OVERRIDE {}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void InvokeAction(int action_index, int event_flags) OVERRIDE {}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual scoped_ptr<ChromeSearchResult> Duplicate() OVERRIDE {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_ptr<ChromeSearchResult>(
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new TestSearchResult(id(), relevance())).Pass();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ChromeSearchResultType GetType() OVERRIDE {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SEARCH_RESULT_TYPE_BOUNDARY;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestSearchResult);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSearchProvider : public SearchProvider {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestSearchProvider(const std::string& prefix)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : prefix_(prefix),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        count_(0) {}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSearchProvider() {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SearchProvider overrides:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start(const string16& query) OVERRIDE {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearResults();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < count_; ++i) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string id =
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::StringPrintf("%s%d", prefix_.c_str(), static_cast<int>(i));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const double relevance = 1.0 - i / 10.0;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Add(scoped_ptr<ChromeSearchResult>(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new TestSearchResult(id, relevance)).Pass());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Stop() OVERRIDE {}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_prefix(const std::string& prefix) { prefix_ = prefix; }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_count(size_t count) { count_ = count; }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string prefix_;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t count_;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(TestSearchProvider);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MixerTest : public testing::Test {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MixerTest() {}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MixerTest() {}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test overrides:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_.reset(new AppListModel::SearchResults);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    providers_.push_back(new TestSearchProvider("app"));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    providers_.push_back(new TestSearchProvider("omnibox"));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    providers_.push_back(new TestSearchProvider("webstore"));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_.reset(new Mixer(results_.get()));
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    mixer_->Init();
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    mixer_->AddProviderToGroup(Mixer::MAIN_GROUP, providers_[0]);
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    mixer_->AddProviderToGroup(Mixer::OMNIBOX_GROUP, providers_[1]);
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    mixer_->AddProviderToGroup(Mixer::WEBSTORE_GROUP, providers_[2]);
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void RunQuery() {
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const string16 query;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < providers_.size(); ++i) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      providers_[i]->Start(query);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      providers_[i]->Stop();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_->MixAndPublish(KnownResults());
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetResults() const {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < results_->item_count(); ++i) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!result.empty())
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result += ',';
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result += UTF16ToUTF8(results_->GetItemAt(i)->title());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mixer* mixer() { return mixer_.get(); }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSearchProvider* app_provider() { return providers_[0]; }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSearchProvider* omnibox_provider() { return providers_[1]; }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSearchProvider* webstore_provider() { return providers_[2]; }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Mixer> mixer_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AppListModel::SearchResults> results_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<TestSearchProvider> providers_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MixerTest);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MixerTest, Basic) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestCase {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t app_results;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t omnibox_results;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t webstore_results;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } kTestCases[] = {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0, 0, 0, ""},
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {4, 6, 2, "app0,app1,app2,app3,omnibox0,webstore0"},
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {10, 10, 10, "app0,app1,app2,app3,omnibox0,webstore0"},
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0, 10, 0, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5"},
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0, 10, 1, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,webstore0"},
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"},
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {1, 10, 0, "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4"},
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {2, 10, 0, "app0,app1,omnibox0,omnibox1,omnibox2,omnibox3"},
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {2, 10, 1, "app0,app1,omnibox0,omnibox1,omnibox2,webstore0"},
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {2, 10, 2, "app0,app1,omnibox0,omnibox1,webstore0,webstore1"},
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {2, 0, 2, "app0,app1,webstore0,webstore1"},
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0, 0, 0, ""},
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    app_provider()->set_count(kTestCases[i].app_results);
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    omnibox_provider()->set_count(kTestCases[i].omnibox_results);
156    webstore_provider()->set_count(kTestCases[i].webstore_results);
157    RunQuery();
158
159    EXPECT_EQ(kTestCases[i].expected, GetResults()) << "Case " << i;
160  }
161}
162
163TEST_F(MixerTest, RemoveDuplicates) {
164  const std::string dup = "dup";
165
166  // This gives "dup0,dup1,dup2".
167  app_provider()->set_prefix(dup);
168  app_provider()->set_count(3);
169
170  // This gives "dup0,dup1".
171  omnibox_provider()->set_prefix(dup);
172  omnibox_provider()->set_count(2);
173
174  // This gives "dup0".
175  webstore_provider()->set_prefix(dup);
176  webstore_provider()->set_count(1);
177
178  RunQuery();
179
180  // Only three results with unique id are kept.
181  EXPECT_EQ("dup0,dup1,dup2", GetResults());
182}
183
184}  // namespace test
185}  // namespace app_list
186