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

Side by Side Diff: content/browser/download/download_query_unittest.cc

Issue 8601012: DownloadQuery filters and sorts DownloadItems. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: comments Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/download/download_query.cc ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/bind.h"
8 #include "base/file_path.h"
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "base/time.h"
12 #include "base/values.h"
13 #include "content/browser/download/download_query.h"
14 #include "content/browser/download/mock_download_item.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using ::testing::Return;
19 using ::testing::ReturnRef;
20 using ::testing::_;
21 using base::Time;
22 using base::Value;
23 typedef DownloadQuery::DownloadVector DownloadVector;
24
25 namespace {
26
27 bool IdNotEqual(int not_id, const DownloadItem& item) {
28 return item.GetId() != not_id;
29 }
30
31 bool AlwaysReturn(bool result, const DownloadItem& item) {
32 return result;
33 }
34
35 } // anonymous namespace
36
37 class DownloadQueryTest : public testing::Test {
38 public:
39 DownloadQueryTest() {}
40
41 virtual ~DownloadQueryTest() {}
42
43 virtual void TearDown() {
44 STLDeleteElements(&mocks_);
45 }
46
47 void CreateMocks(int count) {
48 for (int i = 0; i < count; ++i) {
49 mocks_.push_back(new MockDownloadItem());
50 }
51 }
52
53 MockDownloadItem& mock(int index) { return *mocks_[index]; }
54
55 DownloadQuery* query() { return &query_; }
56
57 template<typename ValueType> void AddFilter(
58 DownloadQuery::FilterType name, ValueType value);
59
60 void Search() {
61 query_.Search(mocks_.begin(), mocks_.end(), &results_);
62 }
63
64 DownloadVector* results() { return &results_; }
65
66 private:
67 std::vector<MockDownloadItem*> mocks_;
68 DownloadQuery query_;
69 DownloadVector results_;
70
71 DISALLOW_COPY_AND_ASSIGN(DownloadQueryTest);
72 };
73
74 template<> void DownloadQueryTest::AddFilter(
75 DownloadQuery::FilterType name, bool cpp_value) {
76 scoped_ptr<base::Value> value(Value::CreateBooleanValue(cpp_value));
77 CHECK(query_.AddFilter(name, *value.get()));
78 }
79
80 template<> void DownloadQueryTest::AddFilter(
81 DownloadQuery::FilterType name, int cpp_value) {
82 scoped_ptr<base::Value> value(Value::CreateIntegerValue(cpp_value));
83 CHECK(query_.AddFilter(name, *value.get()));
84 }
85
86 template<> void DownloadQueryTest::AddFilter(
87 DownloadQuery::FilterType name, const char* cpp_value) {
88 scoped_ptr<base::Value> value(Value::CreateStringValue(cpp_value));
89 CHECK(query_.AddFilter(name, *value.get()));
90 }
91
92 TEST_F(DownloadQueryTest, DownloadQueryEmptyNoItems) {
93 Search();
94 EXPECT_EQ(0U, results()->size());
95 }
96
97 TEST_F(DownloadQueryTest, DownloadQueryEmptySomeItems) {
98 CreateMocks(3);
99 Search();
100 EXPECT_EQ(3U, results()->size());
101 }
102
103 TEST_F(DownloadQueryTest, DownloadQueryInvalidFilters) {
104 scoped_ptr<base::Value> value(Value::CreateIntegerValue(0));
105 EXPECT_FALSE(query()->AddFilter(
106 static_cast<DownloadQuery::FilterType>(kint32max),
107 *value.get()));
108 }
109
110 TEST_F(DownloadQueryTest, DownloadQueryLimit) {
111 CreateMocks(2);
112 query()->Limit(1);
113 Search();
114 EXPECT_EQ(1U, results()->size());
115 }
116
117 // Syntactic sugar for an expression version of the switch-case statement.
118 // Cf. Lisp's |case| form.
119 #define SWITCH2(_index, _col1, _ret1, _default) \
120 ((_index == (_col1)) ? _ret1 : _default)
121 #define SWITCH3(_index, _col1, _ret1, _col2, _ret2, _default) \
122 SWITCH2(_index, _col1, _ret1, SWITCH2(_index, _col2, _ret2, _default))
123 #define SWITCH4(_index, _col1, _ret1, _col2, _ret2, _col3, _ret3, _default) \
124 SWITCH3(_index, _col1, _ret1, _col2, _ret2, \
125 SWITCH2(_index, _col3, _ret3, _default))
126
127 TEST_F(DownloadQueryTest, DownloadQueryAllFilters) {
128 // Set up mocks such that only mock(0) matches all filters, and every other
129 // mock fails a different filter (or two for GREATER/LESS filters).
130 static const size_t kNumItems = 19;
131 CreateMocks(kNumItems);
132 FilePath refail_filename("z");
133 FilePath fail_filename("fail");
134 FilePath match_filename("match");
135 GURL refail_url("http://z.com/");
136 GURL fail_url("http://example.com/fail");
137 GURL match_url("http://example.com/match");
138 // Picture a 2D matrix. The rows are MockDownloadItems and the columns are
139 // filter types. Every cell contains a value that matches all filters, except
140 // for the diagonal. Every item matches all the filters except one filter,
141 // which it fails, except one item, which matches all the filters without
142 // exception. Each mocked method is used to test (corresponds to) one or more
143 // filter types (columns). For example, GetTotalBytes() is used to test
144 // FILTER_TOTAL_BYTES_GREATER, FILTER_TOTAL_BYTES_LESS, and
145 // FILTER_TOTAL_BYTES, so it uses 3 columns: it returns 1 for row (item) 11,
146 // it returns 4 for row 12, 3 for 13, and it returns 2 for all other rows
147 // (items).
148 for (size_t i = 0; i < kNumItems; ++i) {
149 EXPECT_CALL(mock(i), GetId()).WillRepeatedly(Return(i));
150 EXPECT_CALL(mock(i), GetReceivedBytes()).WillRepeatedly(Return(SWITCH2(i,
151 1, 2,
152 1)));
153 EXPECT_CALL(mock(i), GetSafetyState()).WillRepeatedly(Return(SWITCH2(i,
154 2, DownloadItem::DANGEROUS,
155 DownloadItem::DANGEROUS_BUT_VALIDATED)));
156 EXPECT_CALL(mock(i), GetFullPath()).WillRepeatedly(ReturnRef(SWITCH3(i,
157 3, refail_filename,
158 4, fail_filename,
159 match_filename)));
160 EXPECT_CALL(mock(i), GetMimeType()).WillRepeatedly(Return(SWITCH2(i,
161 5, "image",
162 "text")));
163 EXPECT_CALL(mock(i), IsPaused()).WillRepeatedly(Return(SWITCH2(i,
164 6, false,
165 true)));
166 EXPECT_CALL(mock(i), MatchesQuery(_)).WillRepeatedly(Return(SWITCH2(i,
167 7, false,
168 true)));
169 EXPECT_CALL(mock(i), GetStartTime()).WillRepeatedly(Return(SWITCH4(i,
170 8, base::Time::FromTimeT(1),
171 9, base::Time::FromTimeT(4),
172 10, base::Time::FromTimeT(3),
173 base::Time::FromTimeT(2))));
174 EXPECT_CALL(mock(i), GetTotalBytes()).WillRepeatedly(Return(SWITCH4(i,
175 11, 1,
176 12, 4,
177 13, 3,
178 2)));
179 EXPECT_CALL(mock(i), GetOriginalUrl()).WillRepeatedly(ReturnRef(SWITCH3(i,
180 14, refail_url,
181 15, fail_url,
182 match_url)));
183 EXPECT_CALL(mock(i), GetState()).WillRepeatedly(Return(SWITCH2(i,
184 17, DownloadItem::CANCELLED,
185 DownloadItem::IN_PROGRESS)));
186 EXPECT_CALL(mock(i), GetDangerType()).WillRepeatedly(Return(SWITCH2(i,
187 18, DownloadStateInfo::DANGEROUS_FILE,
188 DownloadStateInfo::NOT_DANGEROUS)));
189 }
190 for (size_t i = 0; i < kNumItems; ++i) {
191 switch (i) {
192 case 0: break;
193 case 1: AddFilter(DownloadQuery::FILTER_BYTES_RECEIVED, 1); break;
194 case 2: AddFilter(DownloadQuery::FILTER_DANGER_ACCEPTED, true);
195 break;
196 case 3: AddFilter(DownloadQuery::FILTER_FILENAME_REGEX, "a"); break;
197 case 4: AddFilter(DownloadQuery::FILTER_FILENAME,
198 match_filename.value().c_str()); break;
199 case 5: AddFilter(DownloadQuery::FILTER_MIME, "text"); break;
200 case 6: AddFilter(DownloadQuery::FILTER_PAUSED, true); break;
201 case 7: AddFilter(DownloadQuery::FILTER_QUERY, ""); break;
202 case 8: AddFilter(DownloadQuery::FILTER_STARTED_AFTER, 1000); break;
203 case 9: AddFilter(DownloadQuery::FILTER_STARTED_BEFORE, 4000);
204 break;
205 case 10: AddFilter(DownloadQuery::FILTER_START_TIME, 2000); break;
206 case 11: AddFilter(DownloadQuery::FILTER_TOTAL_BYTES_GREATER, 1);
207 break;
208 case 12: AddFilter(DownloadQuery::FILTER_TOTAL_BYTES_LESS, 4);
209 break;
210 case 13: AddFilter(DownloadQuery::FILTER_TOTAL_BYTES, 2); break;
211 case 14: AddFilter(DownloadQuery::FILTER_URL_REGEX, "example");
212 break;
213 case 15: AddFilter(DownloadQuery::FILTER_URL,
214 match_url.spec().c_str()); break;
215 case 16: CHECK(query()->AddFilter(base::Bind(&IdNotEqual, 16))); break;
216 case 17: query()->AddFilter(DownloadItem::IN_PROGRESS); break;
217 case 18: query()->AddFilter(DownloadStateInfo::NOT_DANGEROUS); break;
218 default: NOTREACHED(); break;
219 }
220 Search();
221 ASSERT_EQ(kNumItems - i, results()->size())
222 << "Failing filter: " << i;
223 if (i > 0) {
224 ASSERT_EQ(0, results()->at(0)->GetId())
225 << "Failing filter: " << i;
226 for (size_t j = 1; j < kNumItems - i; ++j) {
227 ASSERT_EQ(static_cast<int32>(j + i), results()->at(j)->GetId())
228 << "Failing filter: " << i;
229 }
230 }
231 }
232 }
233
234 TEST_F(DownloadQueryTest, DownloadQuerySortBytesReceived) {
235 CreateMocks(2);
236 EXPECT_CALL(mock(0), GetReceivedBytes()).WillRepeatedly(Return(0));
237 EXPECT_CALL(mock(1), GetReceivedBytes()).WillRepeatedly(Return(1));
238 query()->AddSorter(
239 DownloadQuery::SORT_BYTES_RECEIVED, DownloadQuery::DESCENDING);
240 Search();
241 EXPECT_EQ(1, results()->at(0)->GetReceivedBytes());
242 EXPECT_EQ(0, results()->at(1)->GetReceivedBytes());
243 }
244
245 TEST_F(DownloadQueryTest, DownloadQuerySortDanger) {
246 CreateMocks(2);
247 EXPECT_CALL(mock(0), GetDangerType()).WillRepeatedly(Return(
248 DownloadStateInfo::DANGEROUS_FILE));
249 EXPECT_CALL(mock(1), GetDangerType()).WillRepeatedly(Return(
250 DownloadStateInfo::NOT_DANGEROUS));
251 query()->AddSorter(
252 DownloadQuery::SORT_DANGER, DownloadQuery::ASCENDING);
253 Search();
254 EXPECT_EQ(DownloadStateInfo::NOT_DANGEROUS,
255 results()->at(0)->GetDangerType());
256 EXPECT_EQ(DownloadStateInfo::DANGEROUS_FILE,
257 results()->at(1)->GetDangerType());
258 }
259
260 TEST_F(DownloadQueryTest, DownloadQuerySortDangerAccepted) {
261 CreateMocks(2);
262 EXPECT_CALL(mock(0), GetSafetyState()).WillRepeatedly(Return(
263 DownloadItem::DANGEROUS));
264 EXPECT_CALL(mock(1), GetSafetyState()).WillRepeatedly(Return(
265 DownloadItem::DANGEROUS_BUT_VALIDATED));
266 query()->AddSorter(
267 DownloadQuery::SORT_DANGER_ACCEPTED, DownloadQuery::DESCENDING);
268 Search();
269 EXPECT_EQ(DownloadItem::DANGEROUS_BUT_VALIDATED,
270 results()->at(0)->GetSafetyState());
271 EXPECT_EQ(DownloadItem::DANGEROUS, results()->at(1)->GetSafetyState());
272 }
273
274 TEST_F(DownloadQueryTest, DownloadQuerySortFilename) {
275 CreateMocks(2);
276 FilePath a_filename("a");
277 FilePath b_filename("b");
278 EXPECT_CALL(mock(0), GetFullPath()).WillRepeatedly(ReturnRef(b_filename));
279 EXPECT_CALL(mock(1), GetFullPath()).WillRepeatedly(ReturnRef(a_filename));
280 query()->AddSorter(
281 DownloadQuery::SORT_FILENAME, DownloadQuery::ASCENDING);
282 Search();
283 EXPECT_EQ(a_filename, results()->at(0)->GetFullPath());
284 EXPECT_EQ(b_filename, results()->at(1)->GetFullPath());
285 }
286
287 TEST_F(DownloadQueryTest, DownloadQuerySortMime) {
288 CreateMocks(2);
289 EXPECT_CALL(mock(0), GetMimeType()).WillRepeatedly(Return("a"));
290 EXPECT_CALL(mock(1), GetMimeType()).WillRepeatedly(Return("b"));
291 query()->AddSorter(
292 DownloadQuery::SORT_MIME, DownloadQuery::DESCENDING);
293 Search();
294 EXPECT_EQ("b", results()->at(0)->GetMimeType());
295 EXPECT_EQ("a", results()->at(1)->GetMimeType());
296 }
297
298 TEST_F(DownloadQueryTest, DownloadQuerySortPaused) {
299 CreateMocks(2);
300 EXPECT_CALL(mock(0), IsPaused()).WillRepeatedly(Return(true));
301 EXPECT_CALL(mock(1), IsPaused()).WillRepeatedly(Return(false));
302 query()->AddSorter(
303 DownloadQuery::SORT_PAUSED, DownloadQuery::ASCENDING);
304 Search();
305 EXPECT_EQ(false, results()->at(0)->IsPaused());
306 EXPECT_EQ(true, results()->at(1)->IsPaused());
307 }
308
309 TEST_F(DownloadQueryTest, DownloadQuerySortStartTime) {
310 CreateMocks(2);
311 EXPECT_CALL(mock(0), GetStartTime()).WillRepeatedly(Return(
312 base::Time::FromTimeT(0)));
313 EXPECT_CALL(mock(1), GetStartTime()).WillRepeatedly(Return(
314 base::Time::FromTimeT(1)));
315 query()->AddSorter(
316 DownloadQuery::SORT_START_TIME, DownloadQuery::DESCENDING);
317 Search();
318 EXPECT_EQ(base::Time::FromTimeT(1), results()->at(0)->GetStartTime());
319 EXPECT_EQ(base::Time::FromTimeT(0), results()->at(1)->GetStartTime());
320 }
321
322 TEST_F(DownloadQueryTest, DownloadQuerySortState) {
323 CreateMocks(2);
324 EXPECT_CALL(mock(0), GetState()).WillRepeatedly(Return(
325 DownloadItem::IN_PROGRESS));
326 EXPECT_CALL(mock(1), GetState()).WillRepeatedly(Return(
327 DownloadItem::COMPLETE));
328 query()->AddSorter(
329 DownloadQuery::SORT_STATE, DownloadQuery::ASCENDING);
330 Search();
331 EXPECT_EQ(DownloadItem::IN_PROGRESS, results()->at(0)->GetState());
332 EXPECT_EQ(DownloadItem::COMPLETE, results()->at(1)->GetState());
333 }
334
335 TEST_F(DownloadQueryTest, DownloadQuerySortTotalBytes) {
336 CreateMocks(2);
337 EXPECT_CALL(mock(0), GetTotalBytes()).WillRepeatedly(Return(0));
338 EXPECT_CALL(mock(1), GetTotalBytes()).WillRepeatedly(Return(1));
339 query()->AddSorter(
340 DownloadQuery::SORT_TOTAL_BYTES, DownloadQuery::DESCENDING);
341 Search();
342 EXPECT_EQ(1, results()->at(0)->GetTotalBytes());
343 EXPECT_EQ(0, results()->at(1)->GetTotalBytes());
344 }
345
346 TEST_F(DownloadQueryTest, DownloadQuerySortUrl) {
347 CreateMocks(2);
348 GURL a_url("http://example.com/a");
349 GURL b_url("http://example.com/b");
350 EXPECT_CALL(mock(0), GetOriginalUrl()).WillRepeatedly(ReturnRef(b_url));
351 EXPECT_CALL(mock(1), GetOriginalUrl()).WillRepeatedly(ReturnRef(a_url));
352 query()->AddSorter(
353 DownloadQuery::SORT_URL, DownloadQuery::ASCENDING);
354 Search();
355 EXPECT_EQ(a_url, results()->at(0)->GetOriginalUrl());
356 EXPECT_EQ(b_url, results()->at(1)->GetOriginalUrl());
357 }
358
359 TEST_F(DownloadQueryTest, DownloadQuerySortId) {
360 CreateMocks(2);
361 EXPECT_CALL(mock(0), GetReceivedBytes()).WillRepeatedly(Return(0));
362 EXPECT_CALL(mock(1), GetReceivedBytes()).WillRepeatedly(Return(0));
363 EXPECT_CALL(mock(0), GetId()).WillRepeatedly(Return(1));
364 EXPECT_CALL(mock(1), GetId()).WillRepeatedly(Return(0));
365 query()->AddSorter(
366 DownloadQuery::SORT_BYTES_RECEIVED, DownloadQuery::DESCENDING);
367 Search();
368 EXPECT_EQ(0, results()->at(0)->GetId());
369 EXPECT_EQ(1, results()->at(1)->GetId());
370 }
371
372 TEST_F(DownloadQueryTest, DownloadQuerySortDbHandle) {
373 CreateMocks(2);
374 EXPECT_CALL(mock(0), GetReceivedBytes()).WillRepeatedly(Return(0));
375 EXPECT_CALL(mock(1), GetReceivedBytes()).WillRepeatedly(Return(0));
376 EXPECT_CALL(mock(0), GetId()).WillRepeatedly(Return(0));
377 EXPECT_CALL(mock(1), GetId()).WillRepeatedly(Return(0));
Randy Smith (Not in Mondays) 2011/12/12 21:01:38 From our offline conversation: Given that we shoul
benjhayden 2011/12/12 21:28:06 Done.
378 EXPECT_CALL(mock(0), GetDbHandle()).WillRepeatedly(Return(1));
379 EXPECT_CALL(mock(1), GetDbHandle()).WillRepeatedly(Return(0));
380 query()->AddSorter(
381 DownloadQuery::SORT_BYTES_RECEIVED, DownloadQuery::DESCENDING);
382 Search();
383 EXPECT_EQ(0, results()->at(0)->GetDbHandle());
384 EXPECT_EQ(1, results()->at(1)->GetDbHandle());
385 }
386
387 TEST_F(DownloadQueryTest, DownloadQueryFilterPerformance) {
388 static const int kNumItems = 10000;
389 static const int kNumFilters = 1000;
390 CreateMocks(kNumItems);
391 for (size_t i = 0; i < (kNumFilters - 1); ++i) {
392 query()->AddFilter(base::Bind(&AlwaysReturn, true));
393 }
394 query()->AddFilter(base::Bind(&AlwaysReturn, false));
395 base::Time start = base::Time::Now();
396 Search();
397 base::Time end = base::Time::Now();
398 double nanos = (end - start).InMillisecondsF() * 1000.0 * 1000.0;
399 double nanos_per_item = nanos / static_cast<double>(kNumItems);
400 double nanos_per_item_per_filter = nanos_per_item
401 / static_cast<double>(kNumFilters);
402 std::cout << "Search took " << nanos_per_item_per_filter
403 << " nanoseconds per item per filter.\n";
404 }
OLDNEW
« no previous file with comments | « content/browser/download/download_query.cc ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698