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

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