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

Side by Side Diff: chrome/browser/download/download_history_unittest.cc

Issue 10915180: Make DownloadHistory observe manager, items (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: @r165669 Created 8 years, 1 month 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
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 #include <set>
6 #include <vector>
7
8 #include "base/rand_util.h"
9 #include "chrome/browser/download/download_history.h"
10 #include "chrome/browser/history/download_persistent_store_info.h"
11 #include "chrome/browser/history/history.h"
12 #include "chrome/test/base/in_process_browser_test.h"
13 #include "content/public/test/mock_download_item.h"
14 #include "content/public/test/mock_download_manager.h"
15 #include "content/public/test/test_utils.h"
16
17 using testing::DoAll;
18 using testing::Invoke;
19 using testing::Return;
20 using testing::ReturnRef;
21 using testing::SetArgPointee;
22 using testing::WithArg;
23 using testing::_;
24
25 namespace {
26
27 void CheckInfoEqual(const DownloadPersistentStoreInfo& left,
28 const DownloadPersistentStoreInfo& right) {
29 CHECK_EQ(left.path.value(), right.path.value());
30 CHECK_EQ(left.url.spec(), right.url.spec());
31 CHECK_EQ(left.referrer_url.spec(), right.referrer_url.spec());
32 CHECK_EQ(left.start_time.ToTimeT(), right.start_time.ToTimeT());
33 CHECK_EQ(left.end_time.ToTimeT(), right.end_time.ToTimeT());
34 CHECK_EQ(left.received_bytes, right.received_bytes);
35 CHECK_EQ(left.total_bytes, right.total_bytes);
36 CHECK_EQ(left.state, right.state);
37 CHECK_EQ(left.db_handle, right.db_handle);
38 CHECK_EQ(left.opened, right.opened);
39 }
40
41 typedef std::set<int64> HandleSet;
42 typedef std::vector<DownloadPersistentStoreInfo> InfoVector;
43
44 class FakeHistoryService : public HistoryService {
45 public:
46 FakeHistoryService()
47 : slow_create_download_(false),
48 handle_counter_(0) {
49 }
50
51 virtual ~FakeHistoryService() {}
52
53 virtual Handle QueryDownloads(
54 CancelableRequestConsumerBase* consumer,
55 const HistoryService::DownloadQueryCallback& callback) OVERRIDE {
56 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
57 base::Bind(&FakeHistoryService::QueryDownloadsDone,
58 base::Unretained(this), callback));
59 // DownloadHistory ignores the handle.
60 return -1;
61 }
62
63 void QueryDownloadsDone(
64 const HistoryService::DownloadQueryCallback& callback) {
65 CHECK(expect_query_downloads_.get());
66 callback.Run(expect_query_downloads_.get());
67 expect_query_downloads_.reset();
68 }
69
70 virtual Handle GetVisibleVisitCountToHost(
71 const GURL& referrer_url,
72 CancelableRequestConsumerBase* consumer,
73 const HistoryService::GetVisibleVisitCountToHostCallback&
74 callback) OVERRIDE {
75 NOTIMPLEMENTED();
76 return -1;
77 }
78
79 void set_slow_create_download(bool slow) { slow_create_download_ = slow; }
80
81 virtual Handle CreateDownload(
82 const DownloadPersistentStoreInfo& info,
83 CancelableRequestConsumerBase* consumer,
84 const HistoryService::DownloadCreateCallback& callback) OVERRIDE {
85 create_download_info_ = info;
86 create_download_callback_ = base::Bind(callback, handle_counter_++);
87 if (!slow_create_download_)
88 FinishCreateDownload();
89 return -1;
90 }
91
92 void FinishCreateDownload() {
93 create_download_callback_.Run();
94 create_download_callback_.Reset();
95 }
96
97 virtual void UpdateDownload(
98 const DownloadPersistentStoreInfo& info) OVERRIDE {
99 update_download_ = info;
100 }
101
102 virtual void RemoveDownloads(const HandleSet& handles) OVERRIDE {
103 for (HandleSet::const_iterator it = handles.begin();
104 it != handles.end(); ++it) {
105 remove_downloads_.insert(*it);
106 }
107 }
108
109 void ExpectWillQueryDownloads(scoped_ptr<InfoVector> infos) {
110 expect_query_downloads_ = infos.Pass();
111 }
112
113 void ExpectQueryDownloadsDone() {
114 CHECK(NULL == expect_query_downloads_.get());
115 }
116
117 void ExpectDownloadCreated(
118 const DownloadPersistentStoreInfo& info) {
119 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
120 CheckInfoEqual(info, create_download_info_);
121 create_download_info_ = DownloadPersistentStoreInfo();
122 }
123
124 void ExpectNoDownloadCreated() {
125 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
126 CheckInfoEqual(DownloadPersistentStoreInfo(), create_download_info_);
127 }
128
129 void ExpectDownloadUpdated(const DownloadPersistentStoreInfo& info) {
130 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
131 CheckInfoEqual(update_download_, info);
132 update_download_ = DownloadPersistentStoreInfo();
133 }
134
135 void ExpectNoDownloadUpdated() {
136 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
137 CheckInfoEqual(DownloadPersistentStoreInfo(), update_download_);
138 }
139
140 void ExpectNoDownloadsRemoved() {
141 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
142 CHECK_EQ(0, static_cast<int>(remove_downloads_.size()));
143 }
144
145 void ExpectDownloadsRemoved(const HandleSet& handles) {
146 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
147 HandleSet difference;
148 std::insert_iterator<HandleSet> insert_it(
149 difference, difference.begin());
150 std::set_difference(handles.begin(), handles.end(),
151 remove_downloads_.begin(),
152 remove_downloads_.end(),
153 insert_it);
154 for (HandleSet::const_iterator oops = difference.begin();
155 oops != difference.end(); ++oops) {
156 LOG(ERROR) << __FUNCTION__ << " " << *oops;
157 }
158 CHECK(difference.empty());
159 remove_downloads_.clear();
160 }
161
162 private:
163 bool slow_create_download_;
164 base::Closure create_download_callback_;
165 int handle_counter_;
166 DownloadPersistentStoreInfo update_download_;
167 scoped_ptr<InfoVector> expect_query_downloads_;
168 HandleSet remove_downloads_;
169 DownloadPersistentStoreInfo create_download_info_;
170
171 DISALLOW_COPY_AND_ASSIGN(FakeHistoryService);
172 };
173
174 class DownloadHistoryTest : public InProcessBrowserTest {
175 public:
176 DownloadHistoryTest()
177 : manager_(new content::MockDownloadManager()),
178 download_history_(NULL),
179 manager_observer_(NULL),
180 item_observer_(NULL) {
181 }
182 virtual ~DownloadHistoryTest() {}
183
184 protected:
185 virtual void CleanUpOnMainThread() OVERRIDE {
186 download_history_.reset();
187 }
188
189 content::MockDownloadManager& manager() { return *manager_.get(); }
190 content::MockDownloadItem& item() { return item_; }
191
192 void SetManagerObserver(
193 content::DownloadManager::Observer* manager_observer) {
194 manager_observer_ = manager_observer;
195 }
196 content::DownloadManager::Observer* manager_observer() {
197 return manager_observer_;
198 }
199 void SetItemObserver(
200 content::DownloadItem::Observer* item_observer) {
201 item_observer_ = item_observer;
202 }
203 content::DownloadItem::Observer* item_observer() {
204 return item_observer_;
205 }
206
207 void ExpectWillQueryDownloads(scoped_ptr<InfoVector> infos) {
208 CHECK(infos.get());
209 EXPECT_CALL(manager(), AddObserver(_)).WillOnce(WithArg<0>(Invoke(
210 this, &DownloadHistoryTest::SetManagerObserver)));
211 EXPECT_CALL(manager(), RemoveObserver(_));
212 if (infos->size() != 0) {
213 EXPECT_EQ(1, static_cast<int>(infos->size()));
214 EXPECT_CALL(manager(), CreateDownloadItem(
215 infos->at(0).path,
216 infos->at(0).url,
217 infos->at(0).referrer_url,
218 infos->at(0).start_time,
219 infos->at(0).end_time,
220 infos->at(0).received_bytes,
221 infos->at(0).total_bytes,
222 infos->at(0).state,
223 infos->at(0).opened))
224 .WillOnce(DoAll(
225 InvokeWithoutArgs(
226 this, &DownloadHistoryTest::CallOnDownloadCreated),
227 Return(&item())));
228 }
229 EXPECT_CALL(manager(), CheckForHistoryFilesRemoval());
230 history_.reset(new FakeHistoryService());
231 history_->ExpectWillQueryDownloads(infos.Pass());
232 EXPECT_CALL(*manager_.get(), GetAllDownloads(_)).WillRepeatedly(Return());
233 download_history_.reset(new DownloadHistory(&manager(), history_.get()));
234 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
235 history_->ExpectQueryDownloadsDone();
236 }
237
238 void CallOnDownloadCreated() {
239 manager_observer()->OnDownloadCreated(&manager(), &item());
240 }
241
242 void set_slow_create_download(bool slow) {
243 history_->set_slow_create_download(slow);
244 }
245
246 void FinishCreateDownload() {
247 history_->FinishCreateDownload();
248 }
249
250 void ExpectDownloadCreated(
251 const DownloadPersistentStoreInfo& info) {
252 history_->ExpectDownloadCreated(info);
253 }
254
255 void ExpectNoDownloadCreated() {
256 history_->ExpectNoDownloadCreated();
257 }
258
259 void ExpectDownloadUpdated(const DownloadPersistentStoreInfo& info) {
260 history_->ExpectDownloadUpdated(info);
261 }
262
263 void ExpectNoDownloadUpdated() {
264 history_->ExpectNoDownloadUpdated();
265 }
266
267 void ExpectNoDownloadsRemoved() {
268 history_->ExpectNoDownloadsRemoved();
269 }
270
271 void ExpectDownloadsRemoved(const HandleSet& handles) {
272 history_->ExpectDownloadsRemoved(handles);
273 }
274
275 void InitItem(
276 int32 id,
277 const FilePath& path,
278 const GURL& url,
279 const GURL& referrer,
280 const base::Time& start_time,
281 const base::Time& end_time,
282 int64 received_bytes,
283 int64 total_bytes,
284 content::DownloadItem::DownloadState state,
285 int64 db_handle,
286 bool opened,
287 DownloadPersistentStoreInfo* info) {
288 info->path = path;
289 info->url = url;
290 info->referrer_url = referrer;
291 info->start_time = start_time;
292 info->end_time = end_time;
293 info->received_bytes = received_bytes;
294 info->total_bytes = total_bytes;
295 info->state = state;
296 info->db_handle = db_handle;
297 info->opened = opened;
298 EXPECT_CALL(item(), GetId()).WillRepeatedly(Return(id));
299 EXPECT_CALL(item(), GetFullPath()).WillRepeatedly(ReturnRef(path));
300 EXPECT_CALL(item(), GetURL()).WillRepeatedly(ReturnRef(url));
301 EXPECT_CALL(item(), GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
302 EXPECT_CALL(item(), GetStartTime()).WillRepeatedly(Return(start_time));
303 EXPECT_CALL(item(), GetEndTime()).WillRepeatedly(Return(end_time));
304 EXPECT_CALL(item(), GetReceivedBytes())
305 .WillRepeatedly(Return(received_bytes));
306 EXPECT_CALL(item(), GetTotalBytes()).WillRepeatedly(Return(total_bytes));
307 EXPECT_CALL(item(), GetState()).WillRepeatedly(Return(state));
308 EXPECT_CALL(item(), GetOpened()).WillRepeatedly(Return(opened));
309 EXPECT_CALL(item(), GetTargetDisposition()).WillRepeatedly(Return(
310 content::DownloadItem::TARGET_DISPOSITION_OVERWRITE));
311 EXPECT_CALL(manager(), GetDownload(id))
312 .WillRepeatedly(Return(&item()));
313 EXPECT_CALL(item(), AddObserver(_)).WillOnce(WithArg<0>(Invoke(
314 this, &DownloadHistoryTest::SetItemObserver)));
315 EXPECT_CALL(item(), RemoveObserver(_));
316 std::vector<content::DownloadItem*> items;
317 items.push_back(&item());
318 EXPECT_CALL(*manager_.get(), GetAllDownloads(_))
319 .WillRepeatedly(SetArgPointee<0>(items));
320 }
321
322 private:
323 testing::NiceMock<content::MockDownloadItem> item_;
324 scoped_ptr<FakeHistoryService> history_;
325 scoped_refptr<content::MockDownloadManager> manager_;
326 scoped_ptr<DownloadHistory> download_history_;
327 content::DownloadManager::Observer* manager_observer_;
328 content::DownloadItem::Observer* item_observer_;
329
330 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryTest);
331 };
332
333 } // anonymous namespace
334
335 // Test loading an item from the database, changing it, saving it back, removing
336 // it.
337 IN_PROC_BROWSER_TEST_F(DownloadHistoryTest, DownloadHistoryTest_Load) {
338 // Load a download from history, create the item, OnDownloadCreated,
339 // OnDownloadUpdated, OnDownloadRemoved.
340 DownloadPersistentStoreInfo info;
341 InitItem(base::RandInt(0, 1 << 20),
342 FilePath(FILE_PATH_LITERAL("/foo/bar.pdf")),
343 GURL("http://example.com/bar.pdf"),
344 GURL("http://example.com/referrer.html"),
345 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
346 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
347 100,
348 100,
349 content::DownloadItem::COMPLETE,
350 base::RandInt(0, 1 << 20),
351 false,
352 &info);
353 {
354 scoped_ptr<InfoVector> infos(new InfoVector());
355 infos->push_back(info);
356 ExpectWillQueryDownloads(infos.Pass());
357 ExpectNoDownloadCreated();
358 }
359
360 // Pretend that something changed on the item.
361 EXPECT_CALL(item(), GetOpened()).WillRepeatedly(Return(true));
362 item_observer()->OnDownloadUpdated(&item());
363 info.opened = true;
364 ExpectDownloadUpdated(info);
365
366 // Pretend that the user removed the item.
367 HandleSet handles;
368 handles.insert(info.db_handle);
369 item_observer()->OnDownloadRemoved(&item());
370 ExpectDownloadsRemoved(handles);
371
372 // Pretend that the browser is closing.
373 manager_observer()->ManagerGoingDown(&manager());
374 item_observer()->OnDownloadDestroyed(&item());
375 }
376
377 // Test creating an item, saving it to the database, changing it, saving it
378 // back, removing it.
379 IN_PROC_BROWSER_TEST_F(DownloadHistoryTest, DownloadHistoryTest_Create) {
380 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
381 // OnDownloadRemoved.
382 ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
383
384 // Note that db_handle must be -1 at first because it isn't in the db yet.
385 DownloadPersistentStoreInfo info;
386 InitItem(base::RandInt(0, 1 << 20),
387 FilePath(FILE_PATH_LITERAL("/foo/bar.pdf")),
388 GURL("http://example.com/bar.pdf"),
389 GURL("http://example.com/referrer.html"),
390 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
391 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
392 100,
393 100,
394 content::DownloadItem::COMPLETE,
395 -1,
396 false,
397 &info);
398
399 // Pretend the manager just created |item|.
400 CallOnDownloadCreated();
401 // CreateDownload() always gets db_handle=-1.
402 ExpectDownloadCreated(info);
403 info.db_handle = 0;
404
405 // Pretend that something changed on the item.
406 EXPECT_CALL(item(), GetOpened()).WillRepeatedly(Return(true));
407 item_observer()->OnDownloadUpdated(&item());
408 info.opened = true;
409 ExpectDownloadUpdated(info);
410
411 // Pretend that the user removed the item.
412 HandleSet handles;
413 handles.insert(info.db_handle);
414 item_observer()->OnDownloadRemoved(&item());
415 ExpectDownloadsRemoved(handles);
416
417 // Pretend that the browser is closing.
418 manager_observer()->ManagerGoingDown(&manager());
419 item_observer()->OnDownloadDestroyed(&item());
420 }
421
422 // Test creating a new item, saving it, removing it by setting it Temporary,
423 // changing it without saving it back because it's Temporary, clearing
424 // IsTemporary, saving it back, changing it, saving it back because it isn't
425 // Temporary anymore.
426 IN_PROC_BROWSER_TEST_F(DownloadHistoryTest, DownloadHistoryTest_Temporary) {
427 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
428 // OnDownloadRemoved.
429 ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
430
431 // Note that db_handle must be -1 at first because it isn't in the db yet.
432 DownloadPersistentStoreInfo info;
433 InitItem(base::RandInt(0, 1 << 20),
434 FilePath(FILE_PATH_LITERAL("/foo/bar.pdf")),
435 GURL("http://example.com/bar.pdf"),
436 GURL("http://example.com/referrer.html"),
437 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
438 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
439 100,
440 100,
441 content::DownloadItem::COMPLETE,
442 -1,
443 false,
444 &info);
445
446 // Pretend the manager just created |item|.
447 CallOnDownloadCreated();
448 // CreateDownload() always gets db_handle=-1.
449 ExpectDownloadCreated(info);
450 info.db_handle = 0;
451
452 // Pretend the item was marked temporary. DownloadHistory should remove it
453 // from history and start ignoring it.
454 EXPECT_CALL(item(), IsTemporary()).WillRepeatedly(Return(true));
455 item_observer()->OnDownloadUpdated(&item());
456 HandleSet handles;
457 handles.insert(info.db_handle);
458 ExpectDownloadsRemoved(handles);
459
460 // Change something that would make DownloadHistory call UpdateDownload if the
461 // item weren't temporary.
462 EXPECT_CALL(item(), GetReceivedBytes()).WillRepeatedly(Return(4200));
463 item_observer()->OnDownloadUpdated(&item());
464 ExpectNoDownloadUpdated();
465
466 // Changing a temporary item back to a non-temporary item should make
467 // DownloadHistory call CreateDownload.
468 EXPECT_CALL(item(), IsTemporary()).WillRepeatedly(Return(false));
469 item_observer()->OnDownloadUpdated(&item());
470 info.received_bytes = 4200;
471 info.db_handle = -1;
472 // CreateDownload() always gets db_handle=-1.
473 ExpectDownloadCreated(info);
474 info.db_handle = 1;
475
476 EXPECT_CALL(item(), GetReceivedBytes()).WillRepeatedly(Return(100));
477 item_observer()->OnDownloadUpdated(&item());
478 info.received_bytes = 100;
479 ExpectDownloadUpdated(info);
480
481 // Pretend that the browser is closing.
482 manager_observer()->ManagerGoingDown(&manager());
483 item_observer()->OnDownloadDestroyed(&item());
484 }
485
486 // Test removing downloads while they're still being added.
487 IN_PROC_BROWSER_TEST_F(DownloadHistoryTest,
488 DownloadHistoryTest_RemoveWhileAdding) {
489 ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
490
491 // Note that db_handle must be -1 at first because it isn't in the db yet.
492 DownloadPersistentStoreInfo info;
493 InitItem(base::RandInt(0, 1 << 20),
494 FilePath(FILE_PATH_LITERAL("/foo/bar.pdf")),
495 GURL("http://example.com/bar.pdf"),
496 GURL("http://example.com/referrer.html"),
497 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
498 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
499 100,
500 100,
501 content::DownloadItem::COMPLETE,
502 -1,
503 false,
504 &info);
505
506 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
507 // but to wait for FinishCreateDownload().
508 set_slow_create_download(true);
509
510 // Pretend the manager just created |item|.
511 CallOnDownloadCreated();
512 // CreateDownload() always gets db_handle=-1.
513 ExpectDownloadCreated(info);
514 info.db_handle = 0;
515
516 // Call OnDownloadRemoved before calling back to DownloadHistory::ItemAdded().
517 // Instead of calling RemoveDownloads() immediately, it should
518 item_observer()->OnDownloadRemoved(&item());
519 EXPECT_CALL(manager(), GetDownload(item().GetId()))
520 .WillRepeatedly(Return(static_cast<content::DownloadItem*>(NULL)));
521 ExpectNoDownloadsRemoved();
522
523 // Now callback to DownloadHistory::ItemAdded(), and expect a call to
524 // RemoveDownloads() for the item that was removed while it was being added.
525 FinishCreateDownload();
526 HandleSet handles;
527 handles.insert(info.db_handle);
528 ExpectDownloadsRemoved(handles);
529
530 // Pretend that the browser is closing.
531 manager_observer()->ManagerGoingDown(&manager());
532 item_observer()->OnDownloadDestroyed(&item());
533 }
534
535 // TODO(benjhayden): test multiple downloads in flight at the same time, esp.
536 // batched removes.
Randy Smith (Not in Mondays) 2012/11/02 23:31:25 I'd like this in before landing.
benjhayden 2012/11/07 16:39:55 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698