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

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

Issue 10912173: Replace the DownloadFileManager with direct ownership of DownloadFileImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync'd to LKGR (r162700) Created 8 years, 2 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 | 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 "content/browser/download/download_file_manager.h"
6
7 #include "base/file_path.h"
8 #include "base/file_util.h"
9 #include "base/message_loop.h"
10 #include "base/scoped_temp_dir.h"
11 #include "base/string_number_conversions.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/download/byte_stream.h"
14 #include "content/browser/download/download_create_info.h"
15 #include "content/browser/download/download_interrupt_reasons_impl.h"
16 #include "content/browser/download/download_file_factory.h"
17 #include "content/browser/download/download_request_handle.h"
18 #include "content/browser/download/mock_download_file.h"
19 #include "content/public/browser/download_id.h"
20 #include "content/public/test/mock_download_manager.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using content::BrowserThread;
27 using content::BrowserThreadImpl;
28 using content::DownloadId;
29 using content::MockDownloadManager;
30
31 using ::testing::_;
32 using ::testing::AtLeast;
33 using ::testing::Mock;
34 using ::testing::Return;
35 using ::testing::SaveArg;
36 using ::testing::StrictMock;
37 using ::testing::StrEq;
38
39 namespace {
40
41 // MockDownloadManager with the addition of a mock callback used for testing.
42 class TestDownloadManager : public MockDownloadManager {
43 public:
44 MOCK_METHOD3(OnDownloadRenamed,
45 void(int download_id,
46 content::DownloadInterruptReason reason,
47 const FilePath& full_path));
48 private:
49 ~TestDownloadManager() {}
50 };
51
52 class MockDownloadFileFactory : public content::DownloadFileFactory {
53
54 public:
55 MockDownloadFileFactory() {}
56 virtual ~MockDownloadFileFactory() {}
57
58 virtual content::DownloadFile* CreateFile(
59 scoped_ptr<DownloadCreateInfo> info,
60 scoped_ptr<content::ByteStreamReader> stream,
61 content::DownloadManager* download_manager,
62 bool calculate_hash,
63 const net::BoundNetLog& bound_net_log) OVERRIDE;
64
65 MockDownloadFile* GetExistingFile(const DownloadId& id);
66
67 private:
68 std::map<DownloadId, MockDownloadFile*> files_;
69 };
70
71 content::DownloadFile* MockDownloadFileFactory::CreateFile(
72 scoped_ptr<DownloadCreateInfo> info,
73 scoped_ptr<content::ByteStreamReader> stream,
74 content::DownloadManager* download_manager,
75 bool calculate_hash,
76 const net::BoundNetLog& bound_net_log) {
77 DCHECK(files_.end() == files_.find(info->download_id));
78 MockDownloadFile* created_file = new StrictMock<MockDownloadFile>();
79 files_[info->download_id] = created_file;
80
81 ON_CALL(*created_file, GetDownloadManager())
82 .WillByDefault(Return(download_manager));
83 EXPECT_CALL(*created_file, Initialize());
84
85 return created_file;
86 }
87
88 MockDownloadFile* MockDownloadFileFactory::GetExistingFile(
89 const DownloadId& id) {
90 DCHECK(files_.find(id) != files_.end());
91 return files_[id];
92 }
93
94 class MockDownloadRequestHandle : public DownloadRequestHandle {
95 public:
96 MockDownloadRequestHandle(content::DownloadManager* manager)
97 : manager_(manager) {}
98
99 virtual content::DownloadManager* GetDownloadManager() const OVERRIDE;
100
101 private:
102
103 content::DownloadManager* manager_;
104 };
105
106 content::DownloadManager* MockDownloadRequestHandle::GetDownloadManager()
107 const {
108 return manager_;
109 }
110
111 void NullCallback() { }
112
113 } // namespace
114
115 class DownloadFileManagerTest : public testing::Test {
116 public:
117 // State of renamed file. Used with RenameFile().
118 enum RenameFileState {
119 IN_PROGRESS,
120 COMPLETE
121 };
122
123 // Whether to overwrite the target filename in RenameFile().
124 enum RenameFileOverwrite {
125 OVERWRITE,
126 DONT_OVERWRITE
127 };
128
129 static const char* kTestData1;
130 static const char* kTestData2;
131 static const char* kTestData3;
132 static const char* kTestData4;
133 static const char* kTestData5;
134 static const char* kTestData6;
135 static const int32 kDummyDownloadId;
136 static const int32 kDummyDownloadId2;
137 static const int kDummyChildId;
138 static const int kDummyRequestId;
139
140 // We need a UI |BrowserThread| in order to destruct |download_manager_|,
141 // which has trait |BrowserThread::DeleteOnUIThread|. Without this,
142 // calling Release() on |download_manager_| won't ever result in its
143 // destructor being called and we get a leak.
144 DownloadFileManagerTest()
145 : last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
146 ui_thread_(BrowserThread::UI, &loop_),
147 file_thread_(BrowserThread::FILE, &loop_) {
148 }
149
150 ~DownloadFileManagerTest() {
151 }
152
153 virtual void SetUp() {
154 download_manager_ = new TestDownloadManager();
155 request_handle_.reset(new MockDownloadRequestHandle(download_manager_));
156 download_file_factory_ = new MockDownloadFileFactory;
157 download_file_manager_ = new DownloadFileManager(download_file_factory_);
158 }
159
160 virtual void TearDown() {
161 // When a DownloadManager's reference count drops to 0, it is not
162 // deleted immediately. Instead, a task is posted to the UI thread's
163 // message loop to delete it.
164 // So, drop the reference count to 0 and run the message loop once
165 // to ensure that all resources are cleaned up before the test exits.
166 download_manager_ = NULL;
167 ui_thread_.message_loop()->RunAllPending();
168 }
169
170 void ProcessAllPendingMessages() {
171 loop_.RunAllPending();
172 }
173
174 // Clears all gmock expectations for the download file |id| and the manager.
175 void ClearExpectations(DownloadId id) {
176 MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
177 Mock::VerifyAndClearExpectations(file);
178 Mock::VerifyAndClearExpectations(download_manager_);
179 }
180
181 void OnDownloadFileCreated(content::DownloadInterruptReason reason) {
182 last_reason_ = reason;
183 }
184
185 // Create a download item on the DFM.
186 // |info| is the information needed to create a new download file.
187 void CreateDownloadFile(scoped_ptr<DownloadCreateInfo> info) {
188 // Anything that isn't DOWNLOAD_INTERRUPT_REASON_NONE.
189 last_reason_ = content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
190
191 // Mostly null out args; they'll be passed to MockDownloadFileFactory
192 // to be ignored anyway.
193 download_file_manager_->CreateDownloadFile(
194 info.Pass(), scoped_ptr<content::ByteStreamReader>(),
195 download_manager_, true, net::BoundNetLog(),
196 base::Bind(&DownloadFileManagerTest::OnDownloadFileCreated,
197 // The test jig will outlive all download files.
198 base::Unretained(this)));
199
200 ProcessAllPendingMessages();
201 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, last_reason_);
202 }
203
204 // Renames the download file.
205 // |id| is the download ID of the download file.
206 // |new_path| is the new file path.
207 // |unique_path| is the actual path that the download file will be
208 // renamed to. If there is an existing file at
209 // |new_path| and |replace| is false, then |new_path|
210 // will be uniquified.
211 // |rename_error| is the error to inject. For no error,
212 // use content::DOWNLOAD_INTERRUPT_REASON_NONE.
213 // |state| whether we are renaming an in-progress download or a
214 // completed download.
215 // |should_overwrite| indicates whether to replace or uniquify the file.
216 void RenameFile(const DownloadId& id,
217 const FilePath& new_path,
218 bool should_overwrite) {
219 MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
220 ASSERT_TRUE(file != NULL);
221 content::DownloadFile::RenameCompletionCallback rename_callback;
222
223 EXPECT_CALL(*file, Rename(new_path, should_overwrite, _))
224 .WillOnce(SaveArg<2>(&rename_callback));
225
226 content::DownloadFile::RenameCompletionCallback passed_callback(
227 base::Bind(&TestDownloadManager::OnDownloadRenamed,
228 download_manager_, id.local()));
229
230 download_file_manager_->RenameDownloadFile(
231 id, new_path, should_overwrite, passed_callback);
232
233 EXPECT_TRUE(rename_callback.Equals(passed_callback));
234 }
235
236 void Complete(DownloadId id) {
237 MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
238 ASSERT_TRUE(file != NULL);
239
240 EXPECT_CALL(*file, Detach(_))
241 .WillOnce(Return());
242 int num_downloads = download_file_manager_->NumberOfActiveDownloads();
243 EXPECT_LT(0, num_downloads);
244 download_file_manager_->CompleteDownload(id, base::Bind(NullCallback));
245 EXPECT_EQ(num_downloads - 1,
246 download_file_manager_->NumberOfActiveDownloads());
247 EXPECT_EQ(NULL, download_file_manager_->GetDownloadFile(id));
248 }
249
250 void CleanUp(DownloadId id) {
251 // Expected calls:
252 // DownloadFileManager::CancelDownload
253 // DownloadFile::Cancel
254 // DownloadFileManager::EraseDownload
255 // if no more downloads:
256 // DownloadFileManager::StopUpdateTimer
257 MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
258 ASSERT_TRUE(file != NULL);
259
260 EXPECT_CALL(*file, Cancel());
261
262 download_file_manager_->CancelDownload(id);
263
264 EXPECT_EQ(NULL, download_file_manager_->GetDownloadFile(id));
265 }
266
267 protected:
268 scoped_refptr<TestDownloadManager> download_manager_;
269 scoped_ptr<MockDownloadRequestHandle> request_handle_;
270 MockDownloadFileFactory* download_file_factory_;
271 scoped_refptr<DownloadFileManager> download_file_manager_;
272
273 // Error from creating download file.
274 content::DownloadInterruptReason last_reason_;
275
276 // Per-download statistics.
277 std::map<DownloadId, int64> byte_count_;
278 std::map<DownloadId, int> error_count_;
279
280 private:
281 MessageLoop loop_;
282
283 // UI thread.
284 BrowserThreadImpl ui_thread_;
285
286 // File thread to satisfy debug checks in DownloadFile.
287 BrowserThreadImpl file_thread_;
288 };
289
290 const char* DownloadFileManagerTest::kTestData1 =
291 "Let's write some data to the file!\n";
292 const char* DownloadFileManagerTest::kTestData2 = "Writing more data.\n";
293 const char* DownloadFileManagerTest::kTestData3 = "Final line.";
294 const char* DownloadFileManagerTest::kTestData4 = "Writing, writing, writing\n";
295 const char* DownloadFileManagerTest::kTestData5 = "All we do is writing,\n";
296 const char* DownloadFileManagerTest::kTestData6 = "Rawhide!";
297
298 const int32 DownloadFileManagerTest::kDummyDownloadId = 23;
299 const int32 DownloadFileManagerTest::kDummyDownloadId2 = 77;
300 const int DownloadFileManagerTest::kDummyChildId = 3;
301 const int DownloadFileManagerTest::kDummyRequestId = 67;
302
303 TEST_F(DownloadFileManagerTest, Cancel) {
304 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
305 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
306 info->download_id = dummy_id;
307
308 CreateDownloadFile(info.Pass());
309
310 CleanUp(dummy_id);
311 }
312
313 TEST_F(DownloadFileManagerTest, Complete) {
314 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
315 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
316 info->download_id = dummy_id;
317
318 CreateDownloadFile(info.Pass());
319
320 Complete(dummy_id);
321 }
322
323 TEST_F(DownloadFileManagerTest, Rename) {
324 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
325 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
326 info->download_id = dummy_id;
327 ScopedTempDir download_dir;
328 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
329
330 CreateDownloadFile(info.Pass());
331
332 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
333 RenameFile(dummy_id, foo, true);
334
335 CleanUp(dummy_id);
336 }
337
338 TEST_F(DownloadFileManagerTest, RenameNoOverwrite) {
339 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
340 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
341 info->download_id = dummy_id;
342 ScopedTempDir download_dir;
343 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
344
345 CreateDownloadFile(info.Pass());
346
347 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
348 RenameFile(dummy_id, foo, false);
349
350 CleanUp(dummy_id);
351 }
352
353 TEST_F(DownloadFileManagerTest, RenameTwice) {
354 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
355 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
356 info->download_id = dummy_id;
357 ScopedTempDir download_dir;
358 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
359
360 CreateDownloadFile(info.Pass());
361
362 FilePath crfoo(download_dir.path().Append(
363 FILE_PATH_LITERAL("foo.txt.crdownload")));
364 RenameFile(dummy_id, crfoo, true);
365
366 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
367 RenameFile(dummy_id, foo, true);
368
369 CleanUp(dummy_id);
370 }
371
372 TEST_F(DownloadFileManagerTest, TwoDownloads) {
373 // Same as StartDownload, at first.
374 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
375 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
376 info->download_id = dummy_id;
377 scoped_ptr<DownloadCreateInfo> info2(new DownloadCreateInfo);
378 DownloadId dummy_id2(download_manager_.get(), kDummyDownloadId2);
379 info2->download_id = dummy_id2;
380 ScopedTempDir download_dir;
381 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
382
383 CreateDownloadFile(info.Pass());
384 CreateDownloadFile(info2.Pass());
385
386 FilePath crbar(download_dir.path().Append(
387 FILE_PATH_LITERAL("bar.txt.crdownload")));
388 RenameFile(dummy_id2, crbar, true);
389
390 FilePath crfoo(download_dir.path().Append(
391 FILE_PATH_LITERAL("foo.txt.crdownload")));
392 RenameFile(dummy_id, crfoo, true);
393
394
395 FilePath bar(download_dir.path().Append(FILE_PATH_LITERAL("bar.txt")));
396 RenameFile(dummy_id2, bar, true);
397
398 CleanUp(dummy_id2);
399
400 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
401 RenameFile(dummy_id, foo, true);
402
403 CleanUp(dummy_id);
404 }
405
406 // TODO(ahendrickson) -- A test for download manager shutdown.
407 // Expected call sequence:
408 // OnDownloadManagerShutdown
409 // DownloadFile::GetDownloadManager
410 // DownloadFile::CancelDownloadRequest
411 // DownloadFile::~DownloadFile
OLDNEW
« no previous file with comments | « content/browser/download/download_file_manager.cc ('k') | content/browser/download/download_file_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698