15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(beaudoin): What is really needed here?
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/suggestions_combiner.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/suggestions_page_handler.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/suggestions_source.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SourceInfo {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int weight;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source_name;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number_of_suggestions;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestDescription {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SourceInfo sources[3];
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* results[8];
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} test_suite[] = {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One source, more than 8 items.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 10}},
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "A 6", "A 7"}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One source, exactly 8 items.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 8}},
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "A 6", "A 7"}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One source, not enough items.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 3}},
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2"}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One source, no items.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 0}},
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, more than 8 items.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 10}, {1, "B", 10}},
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "B 2", "B 3"}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, exactly 8 items.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 4}, {1, "B", 4}},
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "B 2", "B 3"}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, exactly 8 items but source A has more.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 5}, {1, "B", 3}},
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "A 4", "B 0", "B 1", "B 2"}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, exactly 8 items but source B has more.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 2}, {1, "B", 6}},
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "B 0", "B 1", "B 2", "B 3", "B 4", "B 5"}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, exactly 8 items but source A has none.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 0}, {1, "B", 8}},
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"B 0", "B 1", "B 2", "B 3", "B 4", "B 5", "B 6", "B 7"}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, exactly 8 items but source B has none.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 8}, {1, "B", 0}},
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "A 6", "A 7"}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, less than 8 items.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 3}, {1, "B", 3}},
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "B 0", "B 1", "B 2"}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, less than 8 items but source A has more.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 4}, {1, "B", 3}},
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "B 2"}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, equal weight, less than 8 items but source B has more.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 1}, {1, "B", 3}},
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "B 0", "B 1", "B 2"}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, weights 3/4 A  1/4 B, more than 8 items.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{3, "A", 10}, {1, "B", 10}},
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "B 0", "B 1"}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, weights 1/8 A  7/8 B, more than 8 items.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 10}, {7, "B", 10}},
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "B 0", "B 1", "B 2", "B 3", "B 4", "B 5", "B 6"}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Two sources, weights 1/3 A  2/3 B, more than 8 items.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 10}, {2, "B", 10}},
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "B 0", "B 1", "B 2", "B 3", "B 4", "B 5"}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Three sources, weights 1/2 A  1/4 B  1/4 C, more than 8 items.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{2, "A", 10}, {1, "B", 10}, {1, "C", 10}},
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "C 0", "C 1"}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Three sources, weights 1/3 A  1/3 B  1/3 C, more than 8 items.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 10}, {1, "B", 10}, {1, "C", 10}},
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "B 0", "B 1", "B 2", "C 0", "C 1", "C 2"}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extra items should be grouped together.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {{1, "A", 3}, {1, "B", 4}, {10, "C", 1}},
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"A 0", "A 1", "A 2", "B 0", "B 1", "B 2", "B 3", "C 0"}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stub for a SuggestionsSource that can provide a number of fake suggestions.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fake suggestions are DictionaryValue with a single "title" string field
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// containing the |source_name| followed by the index of the suggestion.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Not in the empty namespace since it's a friend of SuggestionsCombiner.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SuggestionsSourceStub : public SuggestionsSource {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SuggestionsSourceStub(int weight,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& source_name, int number_of_suggestions)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : combiner_(NULL),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        weight_(weight),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source_name_(source_name),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        number_of_suggestions_(number_of_suggestions),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        debug_(false) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SuggestionsSourceStub() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&items_);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call this method to simulate that the SuggestionsSource has received all
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // its suggestions.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Done() {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    combiner_->OnItemsReady();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SuggestionsSource Override and implementation.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetDebug(bool enable) OVERRIDE {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    debug_ = enable;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetWeight() OVERRIDE {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return weight_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetItemCount() OVERRIDE {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return items_.size();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual base::DictionaryValue* PopItem() OVERRIDE {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (items_.empty())
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* item = items_.front();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items_.pop_front();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return item;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void FetchItems(Profile* profile) OVERRIDE {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char num_str[21];  // Enough to hold all numbers up to 64-bits.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < number_of_suggestions_; ++i) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::snprintf(num_str, sizeof(num_str), "%d", i);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddSuggestion(source_name_ + ' ' + num_str);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds a fake suggestion. This suggestion is a DictionaryValue with a single
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "title" field containing |title|.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddSuggestion(const std::string& title) {
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* item = new base::DictionaryValue();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->SetString("title", title);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items_.push_back(item);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetCombiner(SuggestionsCombiner* combiner) OVERRIDE {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!combiner_);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    combiner_ = combiner;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our combiner.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuggestionsCombiner* combiner_;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int weight_;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string source_name_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number_of_suggestions_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool debug_;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep the results of the db query here.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::deque<base::DictionaryValue*> items_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SuggestionsSourceStub);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SuggestionsCombinerTest : public testing::Test {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuggestionsCombinerTest() {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile_;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuggestionsHandler* suggestions_handler_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuggestionsCombiner* combiner_;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset() {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete combiner_;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    combiner_ = new SuggestionsCombiner(suggestions_handler_, profile_);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_ = new TestingProfile();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suggestions_handler_ = new SuggestionsHandler();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    combiner_ = new SuggestionsCombiner(suggestions_handler_, profile_);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete combiner_;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete suggestions_handler_;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete profile_;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SuggestionsCombinerTest);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SuggestionsCombinerTest, NoSource) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  combiner_->FetchItems(NULL);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0UL, combiner_->GetPageValues()->GetSize());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SuggestionsCombinerTest, SourcesAreNotDoneFetching) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  combiner_->AddSource(new SuggestionsSourceStub(1, "sourceA", 10));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  combiner_->AddSource(new SuggestionsSourceStub(1, "sourceB", 10));
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  combiner_->FetchItems(NULL);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0UL, combiner_->GetPageValues()->GetSize());
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SuggestionsCombinerTest, TestSuite) {
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t test_count = arraysize(test_suite);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < test_count; ++i) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TestDescription& description = test_suite[i];
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    size_t source_count = arraysize(description.sources);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<SuggestionsSourceStub*[]> sources(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new SuggestionsSourceStub*[source_count]);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setup sources.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < source_count; ++j) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const SourceInfo& source_info = description.sources[j];
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A NULL |source_name| means we shouldn't add this source.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (source_info.source_name) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sources[j] = new SuggestionsSourceStub(source_info.weight,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            source_info.source_name, source_info.number_of_suggestions);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        combiner_->AddSource(sources[j]);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sources[j] = NULL;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start fetching.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    combiner_->FetchItems(NULL);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sources complete.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < source_count; ++j) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sources[j])
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sources[j]->Done();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify expectations.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ListValue* results = combiner_->GetPageValues();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t result_count = results->GetSize();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LE(result_count, 8UL);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < 8; ++j) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j < result_count) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string value;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::DictionaryValue* dictionary;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        results->GetDictionary(j, &dictionary);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dictionary->GetString("title", &value);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_STREQ(description.results[j], value.c_str()) <<
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            " test index:" << i;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(description.results[j], static_cast<const char*>(NULL)) <<
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            " test index:" << i;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reset();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305