Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc

Issue 1141843004: NTP Zombie Code Slayer II: Suggestions Page (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: and remove urls Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 // TODO(beaudoin): What is really needed here?
6
7 #include <deque>
8 #include <string>
9
10 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h"
13 #include "base/values.h"
14 #include "chrome/browser/ui/webui/ntp/suggestions_combiner.h"
15 #include "chrome/browser/ui/webui/ntp/suggestions_page_handler.h"
16 #include "chrome/browser/ui/webui/ntp/suggestions_source.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace {
22
23 struct SourceInfo {
24 int weight;
25 const char* source_name;
26 int number_of_suggestions;
27 };
28
29 struct TestDescription {
30 SourceInfo sources[3];
31 const char* results[8];
32 } test_suite[] = {
33 // One source, more than 8 items.
34 {
35 {{1, "A", 10}},
36 {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "A 6", "A 7"}
37 },
38 // One source, exactly 8 items.
39 {
40 {{1, "A", 8}},
41 {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "A 6", "A 7"}
42 },
43 // One source, not enough items.
44 {
45 {{1, "A", 3}},
46 {"A 0", "A 1", "A 2"}
47 },
48 // One source, no items.
49 {
50 {{1, "A", 0}},
51 {}
52 },
53 // Two sources, equal weight, more than 8 items.
54 {
55 {{1, "A", 10}, {1, "B", 10}},
56 {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "B 2", "B 3"}
57 },
58 // Two sources, equal weight, exactly 8 items.
59 {
60 {{1, "A", 4}, {1, "B", 4}},
61 {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "B 2", "B 3"}
62 },
63 // Two sources, equal weight, exactly 8 items but source A has more.
64 {
65 {{1, "A", 5}, {1, "B", 3}},
66 {"A 0", "A 1", "A 2", "A 3", "A 4", "B 0", "B 1", "B 2"}
67 },
68 // Two sources, equal weight, exactly 8 items but source B has more.
69 {
70 {{1, "A", 2}, {1, "B", 6}},
71 {"A 0", "A 1", "B 0", "B 1", "B 2", "B 3", "B 4", "B 5"}
72 },
73 // Two sources, equal weight, exactly 8 items but source A has none.
74 {
75 {{1, "A", 0}, {1, "B", 8}},
76 {"B 0", "B 1", "B 2", "B 3", "B 4", "B 5", "B 6", "B 7"}
77 },
78 // Two sources, equal weight, exactly 8 items but source B has none.
79 {
80 {{1, "A", 8}, {1, "B", 0}},
81 {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "A 6", "A 7"}
82 },
83 // Two sources, equal weight, less than 8 items.
84 {
85 {{1, "A", 3}, {1, "B", 3}},
86 {"A 0", "A 1", "A 2", "B 0", "B 1", "B 2"}
87 },
88 // Two sources, equal weight, less than 8 items but source A has more.
89 {
90 {{1, "A", 4}, {1, "B", 3}},
91 {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "B 2"}
92 },
93 // Two sources, equal weight, less than 8 items but source B has more.
94 {
95 {{1, "A", 1}, {1, "B", 3}},
96 {"A 0", "B 0", "B 1", "B 2"}
97 },
98 // Two sources, weights 3/4 A 1/4 B, more than 8 items.
99 {
100 {{3, "A", 10}, {1, "B", 10}},
101 {"A 0", "A 1", "A 2", "A 3", "A 4", "A 5", "B 0", "B 1"}
102 },
103 // Two sources, weights 1/8 A 7/8 B, more than 8 items.
104 {
105 {{1, "A", 10}, {7, "B", 10}},
106 {"A 0", "B 0", "B 1", "B 2", "B 3", "B 4", "B 5", "B 6"}
107 },
108 // Two sources, weights 1/3 A 2/3 B, more than 8 items.
109 {
110 {{1, "A", 10}, {2, "B", 10}},
111 {"A 0", "A 1", "B 0", "B 1", "B 2", "B 3", "B 4", "B 5"}
112 },
113 // Three sources, weights 1/2 A 1/4 B 1/4 C, more than 8 items.
114 {
115 {{2, "A", 10}, {1, "B", 10}, {1, "C", 10}},
116 {"A 0", "A 1", "A 2", "A 3", "B 0", "B 1", "C 0", "C 1"}
117 },
118 // Three sources, weights 1/3 A 1/3 B 1/3 C, more than 8 items.
119 {
120 {{1, "A", 10}, {1, "B", 10}, {1, "C", 10}},
121 {"A 0", "A 1", "B 0", "B 1", "B 2", "C 0", "C 1", "C 2"}
122 },
123 // Extra items should be grouped together.
124 {
125 {{1, "A", 3}, {1, "B", 4}, {10, "C", 1}},
126 {"A 0", "A 1", "A 2", "B 0", "B 1", "B 2", "B 3", "C 0"}
127 }
128 };
129
130 } // namespace
131
132 // Stub for a SuggestionsSource that can provide a number of fake suggestions.
133 // Fake suggestions are DictionaryValue with a single "title" string field
134 // containing the |source_name| followed by the index of the suggestion.
135 // Not in the empty namespace since it's a friend of SuggestionsCombiner.
136 class SuggestionsSourceStub : public SuggestionsSource {
137 public:
138 explicit SuggestionsSourceStub(int weight,
139 const std::string& source_name, int number_of_suggestions)
140 : combiner_(NULL),
141 weight_(weight),
142 source_name_(source_name),
143 number_of_suggestions_(number_of_suggestions),
144 debug_(false) {
145 }
146 ~SuggestionsSourceStub() override { STLDeleteElements(&items_); }
147
148 // Call this method to simulate that the SuggestionsSource has received all
149 // its suggestions.
150 void Done() {
151 combiner_->OnItemsReady();
152 }
153
154 private:
155 // SuggestionsSource Override and implementation.
156 void SetDebug(bool enable) override { debug_ = enable; }
157 int GetWeight() override { return weight_; }
158 int GetItemCount() override { return items_.size(); }
159 base::DictionaryValue* PopItem() override {
160 if (items_.empty())
161 return NULL;
162 base::DictionaryValue* item = items_.front();
163 items_.pop_front();
164 return item;
165 }
166
167 void FetchItems(Profile* profile) override {
168 char num_str[21]; // Enough to hold all numbers up to 64-bits.
169 for (int i = 0; i < number_of_suggestions_; ++i) {
170 base::snprintf(num_str, sizeof(num_str), "%d", i);
171 AddSuggestion(source_name_ + ' ' + num_str);
172 }
173 }
174
175 // Adds a fake suggestion. This suggestion is a DictionaryValue with a single
176 // "title" field containing |title|.
177 void AddSuggestion(const std::string& title) {
178 base::DictionaryValue* item = new base::DictionaryValue();
179 item->SetString("title", title);
180 items_.push_back(item);
181 }
182
183 void SetCombiner(SuggestionsCombiner* combiner) override {
184 DCHECK(!combiner_);
185 combiner_ = combiner;
186 }
187
188 // Our combiner.
189 SuggestionsCombiner* combiner_;
190
191 int weight_;
192 std::string source_name_;
193 int number_of_suggestions_;
194 bool debug_;
195
196 // Keep the results of the db query here.
197 std::deque<base::DictionaryValue*> items_;
198
199 DISALLOW_COPY_AND_ASSIGN(SuggestionsSourceStub);
200 };
201
202 class SuggestionsCombinerTest : public testing::Test {
203 public:
204 SuggestionsCombinerTest() {
205 }
206
207 protected:
208 content::TestBrowserThreadBundle thread_bundle_;
209 Profile* profile_;
210 SuggestionsHandler* suggestions_handler_;
211 SuggestionsCombiner* combiner_;
212
213 void Reset() {
214 delete combiner_;
215 combiner_ = new SuggestionsCombiner(suggestions_handler_, profile_);
216 }
217
218 private:
219 void SetUp() override {
220 profile_ = new TestingProfile();
221 suggestions_handler_ = new SuggestionsHandler();
222 combiner_ = new SuggestionsCombiner(suggestions_handler_, profile_);
223 }
224
225 void TearDown() override {
226 delete combiner_;
227 delete suggestions_handler_;
228 delete profile_;
229 }
230
231 DISALLOW_COPY_AND_ASSIGN(SuggestionsCombinerTest);
232 };
233
234 TEST_F(SuggestionsCombinerTest, NoSource) {
235 combiner_->FetchItems(NULL);
236 EXPECT_EQ(0UL, combiner_->GetPageValues()->GetSize());
237 }
238
239 TEST_F(SuggestionsCombinerTest, SourcesAreNotDoneFetching) {
240 combiner_->AddSource(new SuggestionsSourceStub(1, "sourceA", 10));
241 combiner_->AddSource(new SuggestionsSourceStub(1, "sourceB", 10));
242 combiner_->FetchItems(NULL);
243 EXPECT_EQ(0UL, combiner_->GetPageValues()->GetSize());
244 }
245
246 TEST_F(SuggestionsCombinerTest, TestSuite) {
247 size_t test_count = arraysize(test_suite);
248 for (size_t i = 0; i < test_count; ++i) {
249 const TestDescription& description = test_suite[i];
250 size_t source_count = arraysize(description.sources);
251
252 scoped_ptr<SuggestionsSourceStub*[]> sources(
253 new SuggestionsSourceStub*[source_count]);
254
255 // Setup sources.
256 for (size_t j = 0; j < source_count; ++j) {
257 const SourceInfo& source_info = description.sources[j];
258 // A NULL |source_name| means we shouldn't add this source.
259 if (source_info.source_name) {
260 sources[j] = new SuggestionsSourceStub(source_info.weight,
261 source_info.source_name, source_info.number_of_suggestions);
262 combiner_->AddSource(sources[j]);
263 } else {
264 sources[j] = NULL;
265 }
266 }
267
268 // Start fetching.
269 combiner_->FetchItems(NULL);
270
271 // Sources complete.
272 for (size_t j = 0; j < source_count; ++j) {
273 if (sources[j])
274 sources[j]->Done();
275 }
276
277 // Verify expectations.
278 base::ListValue* results = combiner_->GetPageValues();
279 size_t result_count = results->GetSize();
280 EXPECT_LE(result_count, 8UL);
281 for (size_t j = 0; j < 8; ++j) {
282 if (j < result_count) {
283 std::string value;
284 base::DictionaryValue* dictionary;
285 results->GetDictionary(j, &dictionary);
286 dictionary->GetString("title", &value);
287 EXPECT_STREQ(description.results[j], value.c_str()) <<
288 " test index:" << i;
289 } else {
290 EXPECT_EQ(description.results[j], static_cast<const char*>(NULL)) <<
291 " test index:" << i;
292 }
293 }
294
295 Reset();
296 }
297 }
298
OLDNEW
« no previous file with comments | « chrome/browser/ui/webui/ntp/suggestions_combiner.cc ('k') | chrome/browser/ui/webui/ntp/suggestions_page_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698