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

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

Issue 10344024: Rewrite download manager unit to be actual unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Modified creation comment. Created 8 years, 6 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 #include <string> 6 #include <string>
7 7
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/scoped_ptr.h"
asanka 2012/06/07 17:04:53 Duplicate
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Whoops; done.
11 #include "base/message_loop.h" 12 #include "base/message_loop.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/scoped_temp_dir.h" 13 #include "base/scoped_temp_dir.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/string16.h" 15 #include "base/string16.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "content/browser/download/byte_stream.h"
19 #include "content/browser/download/download_create_info.h" 20 #include "content/browser/download/download_create_info.h"
20 #include "content/browser/download/download_file_impl.h"
21 #include "content/browser/download/download_file_manager.h" 21 #include "content/browser/download/download_file_manager.h"
22 #include "content/browser/download/download_manager_impl.h" 22 #include "content/browser/download/download_manager_impl.h"
23 #include "content/browser/download/download_request_handle.h" 23 #include "content/browser/download/download_request_handle.h"
24 #include "content/browser/download/mock_download_file.h" 24 #include "content/browser/download/mock_download_file.h"
25 #include "content/browser/power_save_blocker.h" 25 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/download_interrupt_reasons.h" 26 #include "content/public/browser/download_interrupt_reasons.h"
27 #include "content/public/browser/download_item.h" 27 #include "content/public/browser/download_item.h"
28 #include "content/public/browser/download_manager_delegate.h" 28 #include "content/public/browser/download_manager_delegate.h"
29 #include "content/public/test/mock_download_manager.h" 29 #include "content/public/test/mock_download_item.h"
30 #include "content/public/test/test_browser_context.h" 30 #include "content/public/test/test_browser_context.h"
31 #include "content/public/test/test_browser_thread.h" 31 #include "content/public/test/test_browser_thread.h"
32 #include "net/base/io_buffer.h"
33 #include "net/base/net_util.h" 32 #include "net/base/net_util.h"
34 #include "testing/gmock/include/gmock/gmock.h" 33 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gmock_mutant.h" 34 #include "testing/gmock_mutant.h"
36 #include "testing/gtest/include/gtest/gtest.h" 35 #include "testing/gtest/include/gtest/gtest.h"
37 36
38 #if defined(USE_AURA) && defined(OS_WIN) 37 using ::testing::DoAll;
39 // http://crbug.com/105200 38 using ::testing::Ref;
40 #define MAYBE_StartDownload DISABLED_StartDownload 39 using ::testing::Return;
41 #define MAYBE_DownloadOverwriteTest DISABLED_DownloadOverwriteTest 40 using ::testing::ReturnRef;
42 #define MAYBE_DownloadRemoveTest DISABLED_DownloadRemoveTest 41 using ::testing::SetArgPointee;
43 #define MAYBE_DownloadFileErrorTest DownloadFileErrorTest 42 using ::testing::StrictMock;
44 #elif defined(OS_LINUX) 43 using ::testing::_;
45 // http://crbug.com/110886 for Linux
46 #define MAYBE_StartDownload DISABLED_StartDownload
47 #define MAYBE_DownloadOverwriteTest DISABLED_DownloadOverwriteTest
48 #define MAYBE_DownloadRemoveTest DISABLED_DownloadRemoveTest
49 #define MAYBE_DownloadFileErrorTest DISABLED_DownloadFileErrorTest
50 #else
51 #define MAYBE_StartDownload StartDownload
52 #define MAYBE_DownloadOverwriteTest DownloadOverwriteTest
53 #define MAYBE_DownloadRemoveTest DownloadRemoveTest
54 #define MAYBE_DownloadFileErrorTest DownloadFileErrorTest
55 #endif
56
57 using content::BrowserContext;
58 using content::BrowserThread;
59 using content::DownloadFile;
60 using content::DownloadId;
61 using content::DownloadItem; 44 using content::DownloadItem;
62 using content::DownloadManager; 45 using content::DownloadManager;
63 using content::WebContents; 46 using content::WebContents;
64 using ::testing::NiceMock;
65 using ::testing::ReturnRef;
66 using ::testing::Return;
67 47
68 namespace content { 48 namespace content {
69 class ByteStreamReader; 49 class ByteStreamReader;
70 } 50 }
71 51
72 namespace { 52 namespace {
73 53
74 FilePath GetTempDownloadPath(const FilePath& suggested_path) { 54 class MockDownloadManagerDelegate : public content::DownloadManagerDelegate {
75 return FilePath(suggested_path.value() + FILE_PATH_LITERAL(".temp"));
76 }
77
78 class MockDownloadFileFactory
79 : public DownloadFileManager::DownloadFileFactory {
80 public: 55 public:
81 MockDownloadFileFactory() {} 56 MockDownloadManagerDelegate();
82 57 virtual ~MockDownloadManagerDelegate();
83 virtual DownloadFile* CreateFile( 58
84 DownloadCreateInfo* info, 59 MOCK_METHOD0(Shutdown, void());
85 scoped_ptr<content::ByteStreamReader> stream, 60 MOCK_METHOD0(GetNextId, content::DownloadId());
86 const DownloadRequestHandle& request_handle, 61 MOCK_METHOD1(ShouldStartDownload, bool(int32));
87 DownloadManager* download_manager, 62 MOCK_METHOD3(ChooseDownloadPath, void(WebContents*, const FilePath&, int32));
88 bool calculate_hash, 63 MOCK_METHOD2(GetIntermediatePath, FilePath(const DownloadItem&, bool*));
64 MOCK_METHOD0(GetAlternativeWebContentsToNotifyForDownload, WebContents*());
65 MOCK_METHOD1(ShouldOpenFileBasedOnExtension, bool(const FilePath&));
66 MOCK_METHOD2(ShouldCompleteDownload, bool(
67 DownloadItem*, const base::Closure&));
68 MOCK_METHOD1(ShouldOpenDownload, bool(DownloadItem*));
69 MOCK_METHOD0(GenerateFileHash, bool());
70 MOCK_METHOD1(AddItemToPersistentStore, void(DownloadItem*));
71 MOCK_METHOD1(UpdateItemInPersistentStore, void(DownloadItem*));
72 MOCK_METHOD2(UpdatePathForItemInPersistentStore,
73 void(DownloadItem*, const FilePath&));
74 MOCK_METHOD1(RemoveItemFromPersistentStore, void(DownloadItem*));
75 MOCK_METHOD2(RemoveItemsFromPersistentStoreBetween, void(
76 base::Time remove_begin, base::Time remove_end));
77 MOCK_METHOD3(GetSaveDir, void(WebContents*, FilePath*, FilePath*));
78 MOCK_METHOD5(ChooseSavePath, void(
79 WebContents*, const FilePath&, const FilePath::StringType&,
80 bool, const content::SavePackagePathPickedCallback&));
81 };
82
83 MockDownloadManagerDelegate::MockDownloadManagerDelegate() { }
84
85 MockDownloadManagerDelegate::~MockDownloadManagerDelegate() { }
86
87 class MockDownloadFileManager : public DownloadFileManager {
88 public:
89 MockDownloadFileManager();
90
91 MOCK_METHOD0(Shutdown, void());
92 MOCK_METHOD3(MockStartDownload, void(DownloadCreateInfo*,
93 content::ByteStreamReader* stream,
94 const DownloadRequestHandle&));
95
96 virtual void StartDownload(scoped_ptr<DownloadCreateInfo> info,
97 scoped_ptr<content::ByteStreamReader> stream,
98 const DownloadRequestHandle& request_handle) {
asanka 2012/06/07 17:04:53 Nit: OVERRIDE
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Done.
99 MockStartDownload(info.get(), stream.get(), request_handle);
100 }
101
102 MOCK_METHOD1(CancelDownload, void(content::DownloadId));
103 MOCK_METHOD1(CompleteDownload, void(content::DownloadId));
104 MOCK_METHOD1(OnDownloadManagerShutdown, void(content::DownloadManager*));
105 MOCK_METHOD4(RenameInProgressDownloadFile,
106 void(content::DownloadId,
107 const FilePath&,
108 bool,
109 const RenameCompletionCallback&));
110 MOCK_METHOD4(RenameCompletingDownloadFile,
111 void(content::DownloadId,
112 const FilePath&,
113 bool,
114 const RenameCompletionCallback&));
115 MOCK_CONST_METHOD0(NumberOfActiveDownloads, int());
116 protected:
117 virtual ~MockDownloadFileManager();
118 };
119
120 MockDownloadFileManager::MockDownloadFileManager()
121 : DownloadFileManager(NULL) { }
122
123 MockDownloadFileManager::~MockDownloadFileManager() { }
124
125 class MockDownloadItemFactory
126 : public DownloadManagerImpl::DownloadItemFactory {
127 public:
128 class Observer {
asanka 2012/06/07 17:04:53 Nit: Would it be cleaner if MockDownloadItemFactor
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Good idea. I'm not certain about the best way to
129 public:
130 virtual ~Observer() = 0;
131 virtual void PersistedItemCreated(
132 content::MockDownloadItem* item,
133 const content::DownloadPersistentStoreInfo& info) = 0;
134 virtual void ActiveItemCreated(
135 content::MockDownloadItem* item,
136 const DownloadCreateInfo& info,
137 DownloadRequestHandleInterface* request_handle,
138 bool is_otr) = 0;
139 virtual void SavePageItemCreated(
140 content::MockDownloadItem* item,
141 const FilePath& path,
142 const GURL& url,
143 bool is_otr) = 0;
144 };
145
146 // |observer| must outlive the factory.
147 explicit MockDownloadItemFactory(Observer* observer);
148 virtual ~MockDownloadItemFactory();
149
150 virtual content::DownloadItem* CreatePersistedItem(
151 DownloadItemImpl::Delegate* delegate,
152 content::DownloadId download_id,
153 const content::DownloadPersistentStoreInfo& info,
89 const net::BoundNetLog& bound_net_log) OVERRIDE; 154 const net::BoundNetLog& bound_net_log) OVERRIDE;
155
156 virtual content::DownloadItem* CreateActiveItem(
157 DownloadItemImpl::Delegate* delegate,
158 const DownloadCreateInfo& info,
159 DownloadRequestHandleInterface* request_handle,
160 bool is_otr,
161 const net::BoundNetLog& bound_net_log) OVERRIDE;
162
163 virtual content::DownloadItem* CreateSavePageItem(
164 DownloadItemImpl::Delegate* delegate,
165 const FilePath& path,
166 const GURL& url,
167 bool is_otr,
168 content::DownloadId download_id,
169 const std::string& mime_type,
170 const net::BoundNetLog& bound_net_log) OVERRIDE;
171
172 private:
173 Observer* observer_;
174
175 DISALLOW_COPY_AND_ASSIGN(MockDownloadItemFactory);
90 }; 176 };
91 177
92 DownloadFile* MockDownloadFileFactory::CreateFile( 178 MockDownloadItemFactory::Observer::~Observer() { }
93 DownloadCreateInfo* info, 179
94 scoped_ptr<content::ByteStreamReader> stream, 180 MockDownloadItemFactory::MockDownloadItemFactory(
95 const DownloadRequestHandle& request_handle, 181 MockDownloadItemFactory::Observer* observer) : observer_(observer) { }
96 DownloadManager* download_manager, 182
97 bool calculate_hash, 183 MockDownloadItemFactory::~MockDownloadItemFactory() { }
184
185 content::DownloadItem* MockDownloadItemFactory::CreatePersistedItem(
186 DownloadItemImpl::Delegate* delegate,
187 content::DownloadId download_id,
188 const content::DownloadPersistentStoreInfo& info,
98 const net::BoundNetLog& bound_net_log) { 189 const net::BoundNetLog& bound_net_log) {
99 NOTREACHED(); 190 content::MockDownloadItem* result =
100 return NULL; 191 new StrictMock<content::MockDownloadItem>;
101 } 192 EXPECT_CALL(*result, GetId())
102 193 .WillRepeatedly(Return(download_id.local()));
103 DownloadId::Domain kValidIdDomain = "valid DownloadId::Domain"; 194 observer_->PersistedItemCreated(result, info);
104 195 return result;
105 class TestDownloadManagerDelegate : public content::DownloadManagerDelegate { 196 }
197
198 content::DownloadItem* MockDownloadItemFactory::CreateActiveItem(
199 DownloadItemImpl::Delegate* delegate,
200 const DownloadCreateInfo& info,
201 DownloadRequestHandleInterface* request_handle,
202 bool is_otr,
203 const net::BoundNetLog& bound_net_log) {
204 content::MockDownloadItem* result =
205 new StrictMock<content::MockDownloadItem>;
206 EXPECT_CALL(*result, GetId())
207 .WillRepeatedly(Return(info.download_id.local()));
208 observer_->ActiveItemCreated(result, info, request_handle, is_otr);
209 return result;
210 }
211
212 content::DownloadItem* MockDownloadItemFactory::CreateSavePageItem(
213 DownloadItemImpl::Delegate* delegate,
214 const FilePath& path,
215 const GURL& url,
216 bool is_otr,
217 content::DownloadId download_id,
218 const std::string& mime_type,
219 const net::BoundNetLog& bound_net_log) {
220 content::MockDownloadItem* result =
221 new StrictMock<content::MockDownloadItem>;
222 EXPECT_CALL(*result, GetId())
223 .WillRepeatedly(Return(download_id.local()));
224 observer_->SavePageItemCreated(result, path, url, is_otr);
225 return result;
226 }
227
228 class MockBrowserContext : public content::BrowserContext {
106 public: 229 public:
107 TestDownloadManagerDelegate() 230 MockBrowserContext() { }
108 : mark_content_dangerous_(false), 231 ~MockBrowserContext() { }
109 prompt_user_for_save_location_(false), 232
110 should_complete_download_(true), 233 MOCK_METHOD0(GetPath, FilePath());
111 download_manager_(NULL) { 234 MOCK_CONST_METHOD0(IsOffTheRecord, bool());
112 } 235 MOCK_METHOD0(GetDownloadManager, content::DownloadManager*());
113 236 MOCK_METHOD0(GetRequestContext, net::URLRequestContextGetter*());
114 void set_download_directory(const FilePath& path) { 237 MOCK_METHOD1(GetRequestContextForRenderProcess,
115 download_directory_ = path; 238 net::URLRequestContextGetter*(int renderer_child_id));
116 } 239 MOCK_METHOD0(GetRequestContextForMedia, net::URLRequestContextGetter*());
117 240 MOCK_METHOD0(GetResourceContext, content::ResourceContext*());
118 void set_download_manager(content::DownloadManager* dm) { 241 MOCK_METHOD0(GetGeolocationPermissionContext,
119 download_manager_ = dm; 242 content::GeolocationPermissionContext* ());
120 } 243 MOCK_METHOD0(GetSpeechRecognitionPreferences,
121 244 content::SpeechRecognitionPreferences* ());
122 void set_prompt_user_for_save_location(bool value) { 245 MOCK_METHOD0(DidLastSessionExitCleanly, bool());
123 prompt_user_for_save_location_ = value; 246 MOCK_METHOD0(GetSpecialStoragePolicy, quota::SpecialStoragePolicy*());
124 }
125
126 virtual bool ShouldStartDownload(int32 download_id) OVERRIDE {
127 DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id);
128 FilePath path = net::GenerateFileName(item->GetURL(),
129 item->GetContentDisposition(),
130 item->GetReferrerCharset(),
131 item->GetSuggestedFilename(),
132 item->GetMimeType(),
133 std::string());
134 DownloadItem::TargetDisposition disposition = item->GetTargetDisposition();
135 if (!ShouldOpenFileBasedOnExtension(path) && prompt_user_for_save_location_)
136 disposition = DownloadItem::TARGET_DISPOSITION_PROMPT;
137 item->OnTargetPathDetermined(download_directory_.Append(path),
138 disposition,
139 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
140 return true;
141 }
142
143 virtual FilePath GetIntermediatePath(const DownloadItem& item,
144 bool* ok_to_overwrite) OVERRIDE {
145 if (intermediate_path_.empty()) {
146 *ok_to_overwrite = true;
147 return GetTempDownloadPath(item.GetTargetFilePath());
148 } else {
149 *ok_to_overwrite = overwrite_intermediate_path_;
150 return intermediate_path_;
151 }
152 }
153
154 virtual void ChooseDownloadPath(WebContents* web_contents,
155 const FilePath& suggested_path,
156 int32 download_id) OVERRIDE {
157 if (!expected_suggested_path_.empty()) {
158 EXPECT_STREQ(expected_suggested_path_.value().c_str(),
159 suggested_path.value().c_str());
160 }
161 if (file_selection_response_.empty()) {
162 BrowserThread::PostTask(
163 BrowserThread::UI, FROM_HERE,
164 base::Bind(&DownloadManager::FileSelectionCanceled,
165 download_manager_,
166 download_id));
167 } else {
168 BrowserThread::PostTask(
169 BrowserThread::UI, FROM_HERE,
170 base::Bind(&DownloadManager::FileSelected,
171 download_manager_,
172 file_selection_response_,
173 download_id));
174 }
175 expected_suggested_path_.clear();
176 file_selection_response_.clear();
177 }
178
179 virtual bool ShouldOpenFileBasedOnExtension(const FilePath& path) OVERRIDE {
180 return path.Extension() == FilePath::StringType(FILE_PATH_LITERAL(".pdf"));
181 }
182
183 virtual void AddItemToPersistentStore(DownloadItem* item) OVERRIDE {
184 static int64 db_handle = DownloadItem::kUninitializedHandle;
185 download_manager_->OnItemAddedToPersistentStore(item->GetId(), --db_handle);
186 }
187
188 void SetFileSelectionExpectation(const FilePath& suggested_path,
189 const FilePath& response) {
190 expected_suggested_path_ = suggested_path;
191 file_selection_response_ = response;
192 }
193
194 void SetMarkContentsDangerous(bool dangerous) {
195 mark_content_dangerous_ = dangerous;
196 }
197
198 void SetIntermediatePath(const FilePath& intermediate_path,
199 bool overwrite_intermediate_path) {
200 intermediate_path_ = intermediate_path;
201 overwrite_intermediate_path_ = overwrite_intermediate_path;
202 }
203
204 void SetShouldCompleteDownload(bool value) {
205 should_complete_download_ = value;
206 }
207
208 void InvokeDownloadCompletionCallback() {
209 EXPECT_FALSE(download_completion_callback_.is_null());
210 download_completion_callback_.Run();
211 download_completion_callback_.Reset();
212 }
213
214 virtual bool ShouldCompleteDownload(
215 DownloadItem* item,
216 const base::Closure& complete_callback) OVERRIDE {
217 download_completion_callback_ = complete_callback;
218 if (mark_content_dangerous_) {
219 CHECK(!complete_callback.is_null());
220 BrowserThread::PostTask(
221 BrowserThread::UI, FROM_HERE,
222 base::Bind(&TestDownloadManagerDelegate::MarkContentDangerous,
223 base::Unretained(this), item->GetId()));
224 mark_content_dangerous_ = false;
225 return false;
226 } else {
227 return should_complete_download_;
228 }
229 }
230
231 private:
232 void MarkContentDangerous(
233 int32 download_id) {
234 DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id);
235 if (!item)
236 return;
237 item->OnContentCheckCompleted(
238 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT);
239 InvokeDownloadCompletionCallback();
240 }
241
242 FilePath download_directory_;
243 FilePath expected_suggested_path_;
244 FilePath file_selection_response_;
245 FilePath intermediate_path_;
246 bool overwrite_intermediate_path_;
247 bool mark_content_dangerous_;
248 bool prompt_user_for_save_location_;
249 bool should_complete_download_;
250 DownloadManager* download_manager_;
251 base::Closure download_completion_callback_;
252
253 DISALLOW_COPY_AND_ASSIGN(TestDownloadManagerDelegate);
254 }; 247 };
255 248
256 } // namespace 249 } // namespace
257 250
258 class DownloadManagerTest : public testing::Test { 251 class DownloadManagerTest
252 : public testing::Test, MockDownloadItemFactory::Observer {
259 public: 253 public:
260 static const char* kTestData; 254 static const char* kTestData;
261 static const size_t kTestDataLen; 255 static const size_t kTestDataLen;
262 256
263 DownloadManagerTest() 257 DownloadManagerTest()
264 : browser_context(new content::TestBrowserContext()), 258 : ui_thread_(content::BrowserThread::UI, &message_loop_),
265 download_manager_delegate_(new TestDownloadManagerDelegate()), 259 file_thread_(content::BrowserThread::FILE, &message_loop_),
266 download_manager_(new DownloadManagerImpl( 260 next_download_id_(0) {
asanka 2012/06/07 17:04:53 Nit: Initialize scalars (mock_download_item_factor
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Done.
267 download_manager_delegate_.get(), NULL)), 261 }
268 ui_thread_(BrowserThread::UI, &message_loop_), 262
269 file_thread_(BrowserThread::FILE, &message_loop_) { 263 // We tear down everything in TearDown().
270 download_manager_->Init(browser_context.get()); 264 ~DownloadManagerTest() {}
271 download_manager_delegate_->set_download_manager(download_manager_); 265
272 } 266 // *** New helper functions targeted at new mock classes.
273 267
274 ~DownloadManagerTest() { 268 // Create a MockDownloadItemFactory, MockDownloadManagerDelegate,
269 // and MockDownloadFileManager, then create a DownloadManager that points
270 // at all of those.
271 virtual void SetUp() {
272 DCHECK(!download_manager_.get());
273
274 mock_download_item_factory_ = new MockDownloadItemFactory(this);
275 mock_download_manager_delegate_.reset(
276 new StrictMock<MockDownloadManagerDelegate>);
277 EXPECT_CALL(*mock_download_manager_delegate_.get(), Shutdown())
278 .WillOnce(Return());
279 mock_download_file_manager_ = new StrictMock<MockDownloadFileManager>;
280 EXPECT_CALL(*mock_download_file_manager_.get(),
281 OnDownloadManagerShutdown(_));
282 mock_browser_context_.reset(new StrictMock<MockBrowserContext>);
283 EXPECT_CALL(*mock_browser_context_.get(), IsOffTheRecord())
284 .WillRepeatedly(Return(false));
285
286 download_manager_ = new DownloadManagerImpl(
287 mock_download_manager_delegate_.get(),
288 mock_download_file_manager_.get(),
289 mock_download_item_factory_,
290 NULL);
291 download_manager_->Init(mock_browser_context_.get());
292 }
293
294 virtual void TearDown() {
295 // Setup all download items for Shutdown.
296 for (std::map<int32, content::MockDownloadItem*>::iterator it =
297 items_.begin(); it != items_.end(); ++it) {
298 EXPECT_CALL(*(it->second), GetSafetyState())
299 .WillOnce(Return(content::DownloadItem::SAFE));
300 EXPECT_CALL(*(it->second), IsPartialDownload())
301 .WillOnce(Return(false));
302 }
303 items_.clear();
304
305 mock_download_item_factory_ = NULL; // Owned by DownloadManager.
asanka 2012/06/07 17:04:53 Could we test that it gets deleted? Perhaps stuff
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Done. That also makes me feel more comfortable ab
275 download_manager_->Shutdown(); 306 download_manager_->Shutdown();
276 // browser_context must outlive download_manager_, so we explicitly delete
277 // download_manager_ first.
278 download_manager_ = NULL; 307 download_manager_ = NULL;
279 download_manager_delegate_.reset();
280 browser_context.reset(NULL);
281 message_loop_.RunAllPending(); 308 message_loop_.RunAllPending();
282 } 309 mock_download_manager_delegate_.reset();
283 310 mock_download_file_manager_ = NULL;
284 // Create a temporary directory as the downloads directory. 311 mock_browser_context_.reset();
285 bool CreateTempDownloadsDirectory() { 312 }
286 if (!scoped_download_dir_.CreateUniqueTempDir()) 313
287 return false; 314 // Returns download id.
288 download_manager_delegate_->set_download_directory( 315 int AddItemToManager() {
asanka 2012/06/07 17:04:53 Why not return a MockDownloadItem& directly?
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Done.
289 scoped_download_dir_.path()); 316 DownloadCreateInfo info;
290 return true; 317 DownloadRequestHandle handle;
291 } 318
292 319 // Args are ignored except for download id, so everything else can be
293 void AddDownloadToFileManager(int id, DownloadFile* download_file) { 320 // null.
294 file_manager()->downloads_[DownloadId(kValidIdDomain, id)] = 321 int id = next_download_id_;
295 download_file; 322 ++next_download_id_;
296 } 323 info.download_id = content::DownloadId(NULL, id);
297 324 download_manager_->CreateDownloadItem(&info, handle);
298 void AddMockDownloadToFileManager(int id, MockDownloadFile* download_file) { 325 DCHECK(items_[id]);
299 AddDownloadToFileManager(id, download_file); 326 ON_CALL(*items_[id], GetId())
300 EXPECT_CALL(*download_file, GetDownloadManager()) 327 .WillByDefault(Return(id));
301 .WillRepeatedly(Return(download_manager_)); 328 return id;
302 } 329 }
303 330
304 void OnResponseCompleted(int32 download_id, int64 size, 331 content::MockDownloadItem& GetMockDownloadItem(int id) {
305 const std::string& hash) { 332 DCHECK(items_[id]);
306 download_manager_->OnResponseCompleted(download_id, size, hash); 333 return *items_[id];
307 } 334 }
308 335
309 void FileSelected(const FilePath& path, int32 download_id) { 336 void RemoveMockDownloadItem(int id) {
310 download_manager_->FileSelected(path, download_id); 337 // Owned by DownloadManager; should be deleted there.
311 } 338 DCHECK(items_[id]);
312 339 items_.erase(id);
313 void ContinueDownloadWithPath(DownloadItem* download, const FilePath& path) { 340 }
314 download->OnTargetPathDetermined( 341
315 path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, 342 MockDownloadManagerDelegate& GetMockDownloadManagerDelegate() {
316 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); 343 return *mock_download_manager_delegate_;
317 download_manager_->OnTargetPathAvailable(download); 344 }
318 } 345
319 346 MockDownloadFileManager& GetMockDownloadFileManager() {
320 void OnDownloadInterrupted(int32 download_id, int64 size, 347 return *mock_download_file_manager_;
321 const std::string& hash_state, 348 }
322 content::DownloadInterruptReason reason) { 349
323 download_manager_->OnDownloadInterrupted(download_id, size, 350 // Probe at private internals.
324 hash_state, reason);
325 }
326
327 // Get the download item with ID |id|.
328 DownloadItem* GetActiveDownloadItem(int32 id) { 351 DownloadItem* GetActiveDownloadItem(int32 id) {
329 return download_manager_->GetActiveDownload(id); 352 return download_manager_->GetActiveDownload(id);
330 } 353 }
331 354
332 FilePath GetPathInDownloadsDir(const FilePath::StringType& fragment) { 355 // From MockDownloadItemFactory::Observer
333 DCHECK(scoped_download_dir_.IsValid()); 356 virtual void PersistedItemCreated(
334 FilePath full_path(scoped_download_dir_.path().Append(fragment)); 357 content::MockDownloadItem* item,
335 return full_path.NormalizePathSeparators(); 358 const content::DownloadPersistentStoreInfo& info) OVERRIDE {
359 int32 id = item->GetId();
360 DCHECK(items_.find(id) == items_.end());
361 items_[id] = item;
362 }
363
364 virtual void ActiveItemCreated(
365 content::MockDownloadItem* item,
366 const DownloadCreateInfo& info,
367 DownloadRequestHandleInterface* request_handle,
368 bool is_otr) OVERRIDE {
369 int32 id = item->GetId();
370 DCHECK(items_.find(id) == items_.end());
371 items_[id] = item;
372 }
373
374 virtual void SavePageItemCreated(
375 content::MockDownloadItem* item,
376 const FilePath& path,
377 const GURL& url,
378 bool is_otr) OVERRIDE {
379 int32 id = item->GetId();
380 DCHECK(items_.find(id) == items_.end());
381 items_[id] = item;
382 }
383
384 void AddItemToHistory(int download_id, int64 db_handle) {
385 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
386
387 // For DCHECK in AddDownloadItemToHistory. Don't want to use
388 // WillRepeatedly as it may have to return true after this.
389 if (DCHECK_IS_ON())
390 EXPECT_CALL(item, IsPersisted())
391 .WillOnce(Return(false));
392
393 EXPECT_CALL(item, SetDbHandle(db_handle));
394 EXPECT_CALL(item, SetIsPersisted());
395 EXPECT_CALL(item, GetDbHandle())
396 .WillRepeatedly(Return(db_handle));
397
398 // Null out ShowDownloadInBrowser
399 EXPECT_CALL(item, GetWebContents())
400 .WillOnce(Return(static_cast<WebContents*>(NULL)));
401 EXPECT_CALL(GetMockDownloadManagerDelegate(),
402 GetAlternativeWebContentsToNotifyForDownload())
403 .WillOnce(Return(static_cast<WebContents*>(NULL)));
404
405 EXPECT_CALL(item, IsInProgress())
406 .WillOnce(Return(true));
407
408 // Null out MaybeCompleteDownload
409 EXPECT_CALL(item, AllDataSaved())
410 .WillOnce(Return(false));
411
412 download_manager_->OnItemAddedToPersistentStore(download_id, db_handle);
336 } 413 }
337 414
338 protected: 415 protected:
339 scoped_ptr<content::TestBrowserContext> browser_context; 416 // Key test variable; we'll keep it available to sub-classes.
340 scoped_ptr<TestDownloadManagerDelegate> download_manager_delegate_;
341 scoped_refptr<DownloadManagerImpl> download_manager_; 417 scoped_refptr<DownloadManagerImpl> download_manager_;
342 scoped_refptr<DownloadFileManager> file_manager_; 418
419 private:
343 MessageLoopForUI message_loop_; 420 MessageLoopForUI message_loop_;
344 content::TestBrowserThread ui_thread_; 421 content::TestBrowserThread ui_thread_;
345 content::TestBrowserThread file_thread_; 422 content::TestBrowserThread file_thread_;
346 ScopedTempDir scoped_download_dir_; 423 MockDownloadItemFactory* mock_download_item_factory_;
347 424 scoped_ptr<MockDownloadManagerDelegate> mock_download_manager_delegate_;
348 DownloadFileManager* file_manager() { 425 scoped_refptr<MockDownloadFileManager> mock_download_file_manager_;
349 if (!file_manager_) { 426 scoped_ptr<MockBrowserContext> mock_browser_context_;
350 file_manager_ = new DownloadFileManager(new MockDownloadFileFactory); 427 std::map<int32, content::MockDownloadItem*> items_;
351 download_manager_->SetFileManagerForTesting(file_manager_); 428 int next_download_id_;
352 }
353 return file_manager_;
354 }
355 429
356 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest); 430 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest);
357 }; 431 };
358 432
359 const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad"; 433 // Does the DownloadManager prompt when requested?
360 const size_t DownloadManagerTest::kTestDataLen = 434 TEST_F(DownloadManagerTest, RestartDownload) {
361 strlen(DownloadManagerTest::kTestData); 435 // Put a mock we have a handle to on the download manager.
362 436 int download_id = AddItemToManager();
363 // A DownloadFile that we can inject errors into. 437 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
364 class DownloadFileWithErrors : public DownloadFileImpl { 438
365 public: 439 ScopedTempDir download_dir;
366 DownloadFileWithErrors(DownloadCreateInfo* info, 440 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
367 scoped_ptr<content::ByteStreamReader> stream, 441 FilePath expected_path(download_dir.path().Append(
368 DownloadManager* manager, 442 FILE_PATH_LITERAL("location")));
369 bool calculate_hash); 443
370 virtual ~DownloadFileWithErrors() {} 444 EXPECT_CALL(item, GetTargetDisposition())
371 445 .WillOnce(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
372 // BaseFile delegated functions. 446 EXPECT_CALL(item, GetWebContents())
373 virtual net::Error Initialize() OVERRIDE; 447 .WillOnce(Return(reinterpret_cast<WebContents*>(0x44)));
374 virtual net::Error AppendDataToFile(const char* data, 448 EXPECT_CALL(item, GetTargetFilePath())
375 size_t data_len) OVERRIDE; 449 .WillOnce(ReturnRef(expected_path));
376 virtual net::Error Rename(const FilePath& full_path) OVERRIDE; 450 EXPECT_CALL(GetMockDownloadManagerDelegate(), ChooseDownloadPath(
377 451 reinterpret_cast<WebContents*>(0x44), expected_path, download_id));
378 void set_forced_error(net::Error error) { forced_error_ = error; } 452 download_manager_->RestartDownload(download_id);
379 void clear_forced_error() { forced_error_ = net::OK; } 453
380 net::Error forced_error() const { return forced_error_; } 454 // The alternative pathway goes straight to OnTargetPathAvailable,
381 455 // so it more naturally belongs below.
382 private: 456 }
383 net::Error ReturnError(net::Error function_error) { 457
384 if (forced_error_ != net::OK) { 458 // Do the results of GetIntermediatePath get passed through to the
385 net::Error ret = forced_error_; 459 // download? Note that this path is tested from RestartDownload
386 clear_forced_error(); 460 // to test the non-prompting path in RestartDownload as well.
387 return ret; 461 TEST_F(DownloadManagerTest, OnTargetPathAvailable) {
388 } 462 // Put a mock we have a handle to on the download manager.
389 463 int download_id = AddItemToManager();
390 return function_error; 464 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
391 } 465
392 466 ScopedTempDir download_dir;
393 net::Error forced_error_; 467 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
394 }; 468 FilePath target_path(download_dir.path().Append(
395 469 FILE_PATH_LITERAL("location")));
396 DownloadFileWithErrors::DownloadFileWithErrors( 470 FilePath intermediate_path(download_dir.path().Append(
397 DownloadCreateInfo* info, 471 FILE_PATH_LITERAL("location.crdownload")));
398 scoped_ptr<content::ByteStreamReader> stream, 472
399 DownloadManager* manager, 473 EXPECT_CALL(item, GetTargetDisposition())
400 bool calculate_hash) 474 .WillOnce(Return(DownloadItem::TARGET_DISPOSITION_UNIQUIFY));
401 : DownloadFileImpl(info, 475 EXPECT_CALL(GetMockDownloadManagerDelegate(),
402 stream.Pass(), 476 GetIntermediatePath(Ref(item), _))
403 new DownloadRequestHandle(), 477 .WillOnce(DoAll(SetArgPointee<1>(true), Return(intermediate_path)));
404 manager, 478 // Finesse DCHECK with WillRepeatedly.
405 calculate_hash, 479 EXPECT_CALL(item, GetTargetFilePath())
406 scoped_ptr<PowerSaveBlocker>(NULL).Pass(), 480 .WillRepeatedly(ReturnRef(target_path));
407 net::BoundNetLog()), 481 EXPECT_CALL(item, OnIntermediatePathDetermined(
408 forced_error_(net::OK) { 482 &GetMockDownloadFileManager(), intermediate_path, true));
409 } 483 download_manager_->RestartDownload(download_id);
410 484 }
411 net::Error DownloadFileWithErrors::Initialize() { 485
412 return ReturnError(DownloadFileImpl::Initialize()); 486 // Do the results of an OnDownloadInterrupted get passed through properly
413 } 487 // to the DownloadItem? This test tests non-persisted downloads.
414 488 TEST_F(DownloadManagerTest, OnDownloadInterrupted_NonPersisted) {
415 net::Error DownloadFileWithErrors::AppendDataToFile(const char* data, 489 // Put a mock we have a handle to on the download manager.
416 size_t data_len) { 490 int download_id = AddItemToManager();
417 return ReturnError(DownloadFileImpl::AppendDataToFile(data, data_len)); 491 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
418 } 492
419 493 EXPECT_EQ(&item, GetActiveDownloadItem(download_id));
420 net::Error DownloadFileWithErrors::Rename(const FilePath& full_path) { 494
421 return ReturnError(DownloadFileImpl::Rename(full_path)); 495 int64 size = 0xdeadbeef;
422 } 496 const std::string hash_state("Undead beef");
423 497 content::DownloadInterruptReason reason(
424 namespace { 498 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
425 499
426 const struct { 500 EXPECT_CALL(item, Interrupted(size, hash_state, reason));
427 const char* url; 501 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
428 const char* mime_type; 502 EXPECT_CALL(item, IsPersisted())
429 bool save_as; 503 .WillOnce(Return(false));
430 bool prompt_for_download; 504 download_manager_->OnDownloadInterrupted(
431 bool expected_save_as; 505 download_id, size, hash_state, reason);
432 } kStartDownloadCases[] = { 506 EXPECT_EQ(&item, GetActiveDownloadItem(download_id));
433 { "http://www.foo.com/dont-open.html", 507 }
434 "text/html", 508
435 false, 509 // Do the results of an OnDownloadInterrupted get passed through properly
436 false, 510 // to the DownloadItem? This test tests persisted downloads.
437 false, }, 511 TEST_F(DownloadManagerTest, OnDownloadInterrupted_Persisted) {
438 { "http://www.foo.com/save-as.html", 512 // Put a mock we have a handle to on the download manager.
439 "text/html", 513 int download_id = AddItemToManager();
440 true, 514 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
441 false, 515 int64 db_handle = 0x7;
442 true, }, 516 AddItemToHistory(download_id, db_handle);
443 { "http://www.foo.com/always-prompt.html", 517
444 "text/html", 518 EXPECT_EQ(&item, GetActiveDownloadItem(download_id));
445 false, 519
446 true, 520 int64 size = 0xdeadbeef;
447 true, }, 521 const std::string hash_state("Undead beef");
448 { "http://www.foo.com/user-script-text-html-mimetype.user.js", 522 content::DownloadInterruptReason reason(
449 "text/html", 523 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
450 false, 524
451 false, 525 EXPECT_CALL(item, Interrupted(size, hash_state, reason));
452 false, }, 526 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
453 { "http://www.foo.com/extensionless-extension", 527 EXPECT_CALL(item, IsPersisted())
454 "application/x-chrome-extension", 528 .WillOnce(Return(true));
455 true, 529 EXPECT_CALL(GetMockDownloadManagerDelegate(),
456 false, 530 UpdateItemInPersistentStore(&item));
457 true, }, 531 download_manager_->OnDownloadInterrupted(
458 { "http://www.foo.com/save-as.pdf", 532 download_id, size, hash_state, reason);
459 "application/pdf", 533 EXPECT_EQ(NULL, GetActiveDownloadItem(download_id));
460 true, 534
461 false, 535 // Remove so we don't get errors on shutdown.
462 true, }, 536 EXPECT_CALL(GetMockDownloadManagerDelegate(),
463 { "http://www.foo.com/sometimes_prompt.pdf", 537 RemoveItemFromPersistentStore(&item));
464 "application/pdf", 538 download_manager_->DownloadRemoved(&item);
465 false, 539 RemoveMockDownloadItem(download_id);
466 true, 540 }
467 false, }, 541
468 { "http://www.foo.com/always_prompt.jar", 542 // Does DownloadCancelled remove Download from appropriate queues?
469 "application/jar", 543 // This test tests non-persisted downloads.
470 false, 544 TEST_F(DownloadManagerTest, OnDownloadCancelled_NonPersisted) {
471 true, 545 // Put a mock we have a handle to on the download manager.
472 true, }, 546 int download_id = AddItemToManager();
473 }; 547 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
474 548
475 // This is an observer that records what download IDs have opened a select 549 EXPECT_CALL(item, IsPersisted())
476 // file dialog. 550 .WillRepeatedly(Return(false));
477 class SelectFileObserver : public DownloadManager::Observer { 551 EXPECT_CALL(item, GetState())
478 public: 552 .WillRepeatedly(Return(DownloadItem::CANCELLED));
479 explicit SelectFileObserver(DownloadManager* download_manager) 553 EXPECT_CALL(item, GetDbHandle())
480 : download_manager_(download_manager) { 554 .WillRepeatedly(Return(DownloadItem::kUninitializedHandle));
481 DCHECK(download_manager_.get()); 555
482 download_manager_->AddObserver(this); 556 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
483 } 557 download_manager_->DownloadCancelled(&item);
asanka 2012/06/07 17:04:53 Check GetActiveDownloadItem() afterwards?
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 The current behavior (which is that non-persisted
484 558 }
485 ~SelectFileObserver() { 559
486 download_manager_->RemoveObserver(this); 560 // Does DownloadCancelled remove Download from appropriate queues?
487 } 561 // This test tests persisted downloads.
488 562 TEST_F(DownloadManagerTest, OnDownloadCancelled_Persisted) {
489 // Downloadmanager::Observer functions. 563 // Put a mock we have a handle to on the download manager.
490 virtual void ModelChanged(DownloadManager* manager) OVERRIDE {} 564 int download_id = AddItemToManager();
491 virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {} 565 content::MockDownloadItem& item(GetMockDownloadItem(download_id));
492 virtual void SelectFileDialogDisplayed( 566 int64 db_handle = 0x7;
493 DownloadManager* manager, int32 id) OVERRIDE { 567 AddItemToHistory(download_id, db_handle);
494 file_dialog_ids_.insert(id); 568
495 } 569 EXPECT_CALL(item, IsPersisted())
496 570 .WillRepeatedly(Return(true));
497 bool ShowedFileDialogForId(int32 id) { 571 EXPECT_CALL(GetMockDownloadManagerDelegate(),
498 return file_dialog_ids_.find(id) != file_dialog_ids_.end(); 572 UpdateItemInPersistentStore(&item));
499 } 573 EXPECT_CALL(item, GetState())
500 574 .WillRepeatedly(Return(DownloadItem::CANCELLED));
501 private: 575 EXPECT_CALL(item, GetDbHandle())
502 std::set<int32> file_dialog_ids_; 576 .WillRepeatedly(Return(db_handle));
503 scoped_refptr<DownloadManager> download_manager_; 577
504 }; 578 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
505 579 download_manager_->DownloadCancelled(&item);
asanka 2012/06/07 17:04:53 Check GetActiveDownloadItem() afterwards?
Randy Smith (Not in Mondays) 2012/06/07 23:27:21 Done.
506 // This observer tracks the progress of |DownloadItem|s. 580 }
507 class ItemObserver : public DownloadItem::Observer {
508 public:
509 explicit ItemObserver(DownloadItem* tracked)
510 : tracked_(tracked), states_hit_(0),
511 was_updated_(false), was_opened_(false) {
512 DCHECK(tracked_);
513 tracked_->AddObserver(this);
514 // Record the initial state.
515 OnDownloadUpdated(tracked_);
516 }
517 ~ItemObserver() {
518 tracked_->RemoveObserver(this);
519 }
520
521 bool hit_state(int state) const {
522 return (1 << state) & states_hit_;
523 }
524 bool was_updated() const { return was_updated_; }
525 bool was_opened() const { return was_opened_; }
526
527 private:
528 // DownloadItem::Observer methods
529 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
530 DCHECK_EQ(tracked_, download);
531 states_hit_ |= (1 << download->GetState());
532 was_updated_ = true;
533 }
534 virtual void OnDownloadOpened(DownloadItem* download) OVERRIDE{
535 DCHECK_EQ(tracked_, download);
536 states_hit_ |= (1 << download->GetState());
537 was_opened_ = true;
538 }
539
540 DownloadItem* tracked_;
541 int states_hit_;
542 bool was_updated_;
543 bool was_opened_;
544 };
545
546 } // namespace
547
548 TEST_F(DownloadManagerTest, MAYBE_StartDownload) {
549 content::TestBrowserThread io_thread(BrowserThread::IO, &message_loop_);
550 ASSERT_TRUE(CreateTempDownloadsDirectory());
551 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) {
552 DVLOG(1) << "Test case " << i;
553 download_manager_delegate_->set_prompt_user_for_save_location(
554 kStartDownloadCases[i].prompt_for_download);
555
556 SelectFileObserver observer(download_manager_);
557 // Normally, the download system takes ownership of info, and is
558 // responsible for deleting it. In these unit tests, however, we
559 // don't call the function that deletes it, so we do so ourselves.
560 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
561 const DownloadId id = DownloadId(kValidIdDomain, static_cast<int>(i));
562 info->download_id = id;
563 info->prompt_user_for_save_location = kStartDownloadCases[i].save_as;
564 info->url_chain.push_back(GURL(kStartDownloadCases[i].url));
565 info->mime_type = kStartDownloadCases[i].mime_type;
566 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
567
568 scoped_ptr<content::ByteStreamWriter> stream_writer;
569 scoped_ptr<content::ByteStreamReader> stream_reader;
570 content::CreateByteStream(message_loop_.message_loop_proxy(),
571 message_loop_.message_loop_proxy(),
572 kTestDataLen, &stream_writer, &stream_reader);
573
574 DownloadFile* download_file(
575 new DownloadFileImpl(info.get(),
576 stream_reader.Pass(),
577 new DownloadRequestHandle(),
578 download_manager_, false,
579 scoped_ptr<PowerSaveBlocker>(NULL).Pass(),
580 net::BoundNetLog()));
581 AddDownloadToFileManager(info->download_id.local(), download_file);
582 download_file->Initialize();
583 download_manager_->StartDownload(info->download_id.local());
584 message_loop_.RunAllPending();
585
586 // SelectFileObserver will have recorded any attempt to open the
587 // select file dialog.
588 // Note that DownloadManager::FileSelectionCanceled() is never called.
589 EXPECT_EQ(kStartDownloadCases[i].expected_save_as,
590 observer.ShowedFileDialogForId(i));
591
592 file_manager()->CancelDownload(id);
593 }
594 }
595
596 namespace {
597
598 enum OverwriteDownloadPath {
599 DONT_OVERWRITE,
600 OVERWRITE
601 };
602
603 enum ResponseCompletionTime {
604 COMPLETES_BEFORE_RENAME,
605 COMPLETES_AFTER_RENAME
606 };
607
608 // Test cases to be used with DownloadFilenameTest. The paths are relative to
609 // the temporary downloads directory used for testing.
610 const struct DownloadFilenameTestCase {
611 // DownloadItem properties prior to calling RestartDownload().
612 const FilePath::CharType* target_path;
613 DownloadItem::TargetDisposition target_disposition;
614
615 // If we receive a ChooseDownloadPath() call to prompt the user for a download
616 // location, |expected_prompt_path| is the expected prompt path. The
617 // TestDownloadManagerDelegate will respond with |chosen_path|. If
618 // |chosen_path| is empty, then the file choose dialog be cancelled.
619 const FilePath::CharType* expected_prompt_path;
620 const FilePath::CharType* chosen_path;
621
622 // Response to GetIntermediatePath(). If |intermediate_path| is empty, then a
623 // temporary path is constructed with
624 // GetTempDownloadPath(item->GetTargetFilePath()).
625 const FilePath::CharType* intermediate_path;
626 OverwriteDownloadPath overwrite_intermediate_path;
627
628 // Determines when OnResponseCompleted() is called. If this is
629 // COMPLETES_BEFORE_RENAME, then the response completes before the filename is
630 // determines.
631 ResponseCompletionTime completion;
632
633 // The expected intermediate path for the download.
634 const FilePath::CharType* expected_intermediate_path;
635
636 // The expected final path for the download.
637 const FilePath::CharType* expected_final_path;
638 } kDownloadFilenameTestCases[] = {
639
640 #define TARGET FILE_PATH_LITERAL
641 #define INTERMEDIATE FILE_PATH_LITERAL
642 #define EXPECTED_PROMPT FILE_PATH_LITERAL
643 #define PROMPT_RESPONSE FILE_PATH_LITERAL
644 #define EXPECTED_INTERMEDIATE FILE_PATH_LITERAL
645 #define EXPECTED_FINAL FILE_PATH_LITERAL
646
647 {
648 // 0: No prompting.
649 TARGET("foo.txt"),
650 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
651
652 EXPECTED_PROMPT(""),
653 PROMPT_RESPONSE(""),
654
655 INTERMEDIATE("foo.txt.intermediate"),
656 OVERWRITE,
657
658 COMPLETES_AFTER_RENAME,
659 EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
660 EXPECTED_FINAL("foo.txt"),
661 },
662 {
663 // 1: With prompting. No rename.
664 TARGET("foo.txt"),
665 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
666
667 EXPECTED_PROMPT("foo.txt"),
668 PROMPT_RESPONSE("foo.txt"),
669
670 INTERMEDIATE("foo.txt.intermediate"),
671 OVERWRITE,
672
673 COMPLETES_AFTER_RENAME,
674 EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
675 EXPECTED_FINAL("foo.txt"),
676 },
677 {
678 // 2: With prompting. Download is renamed.
679 TARGET("foo.txt"),
680 DownloadItem::TARGET_DISPOSITION_PROMPT,
681
682 EXPECTED_PROMPT("foo.txt"),
683 PROMPT_RESPONSE("bar.txt"),
684
685 INTERMEDIATE("bar.txt.intermediate"),
686 OVERWRITE,
687
688 COMPLETES_AFTER_RENAME,
689 EXPECTED_INTERMEDIATE("bar.txt.intermediate"),
690 EXPECTED_FINAL("bar.txt"),
691 },
692 {
693 // 3: With prompting. Download path is changed.
694 TARGET("foo.txt"),
695 DownloadItem::TARGET_DISPOSITION_PROMPT,
696
697 EXPECTED_PROMPT("foo.txt"),
698 PROMPT_RESPONSE("Foo/bar.txt"),
699
700 INTERMEDIATE("Foo/bar.txt.intermediate"),
701 OVERWRITE,
702
703 COMPLETES_AFTER_RENAME,
704 EXPECTED_INTERMEDIATE("Foo/bar.txt.intermediate"),
705 EXPECTED_FINAL("Foo/bar.txt"),
706 },
707 {
708 // 4: No prompting. Intermediate path exists. Doesn't overwrite
709 // intermediate path.
710 TARGET("exists.png"),
711 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
712
713 EXPECTED_PROMPT(""),
714 PROMPT_RESPONSE(""),
715
716 INTERMEDIATE("exists.png.temp"),
717 DONT_OVERWRITE,
718
719 COMPLETES_AFTER_RENAME,
720 EXPECTED_INTERMEDIATE("exists.png (1).temp"),
721 EXPECTED_FINAL("exists.png"),
722 },
723 {
724 // 5: No prompting. Intermediate path exists. Overwrites.
725 TARGET("exists.png"),
726 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
727
728 EXPECTED_PROMPT(""),
729 PROMPT_RESPONSE(""),
730
731 INTERMEDIATE("exists.png.temp"),
732 OVERWRITE,
733
734 COMPLETES_AFTER_RENAME,
735 EXPECTED_INTERMEDIATE("exists.png.temp"),
736 EXPECTED_FINAL("exists.png"),
737 },
738 {
739 // 6: No prompting. Final path exists. Doesn't overwrite.
740 TARGET("exists.txt"),
741 DownloadItem::TARGET_DISPOSITION_UNIQUIFY,
742
743 EXPECTED_PROMPT(""),
744 PROMPT_RESPONSE(""),
745
746 INTERMEDIATE("exists.txt.temp"),
747 OVERWRITE,
748
749 COMPLETES_AFTER_RENAME,
750 EXPECTED_INTERMEDIATE("exists.txt.temp"),
751 EXPECTED_FINAL("exists (1).txt"),
752 },
753 {
754 // 7: No prompting. Final path exists. Overwrites.
755 TARGET("exists.txt"),
756 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
757
758 EXPECTED_PROMPT(""),
759 PROMPT_RESPONSE(""),
760
761 INTERMEDIATE("exists.txt.temp"),
762 OVERWRITE,
763
764 COMPLETES_AFTER_RENAME,
765 EXPECTED_INTERMEDIATE("exists.txt.temp"),
766 EXPECTED_FINAL("exists.txt"),
767 },
768 {
769 // 8: No prompting. Response completes before filename determination.
770 TARGET("foo.txt"),
771 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
772
773 EXPECTED_PROMPT(""),
774 PROMPT_RESPONSE(""),
775
776 INTERMEDIATE("foo.txt.intermediate"),
777 OVERWRITE,
778
779 COMPLETES_BEFORE_RENAME,
780 EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
781 EXPECTED_FINAL("foo.txt"),
782 },
783 {
784 // 9: With prompting. Download path is changed. Response completes before
785 // filename determination.
786 TARGET("foo.txt"),
787 DownloadItem::TARGET_DISPOSITION_PROMPT,
788
789 EXPECTED_PROMPT("foo.txt"),
790 PROMPT_RESPONSE("Foo/bar.txt"),
791
792 INTERMEDIATE("Foo/bar.txt.intermediate"),
793 OVERWRITE,
794
795 COMPLETES_BEFORE_RENAME,
796 EXPECTED_INTERMEDIATE("Foo/bar.txt.intermediate"),
797 EXPECTED_FINAL("Foo/bar.txt"),
798 },
799
800 #undef TARGET
801 #undef INTERMEDIATE
802 #undef EXPECTED_PROMPT
803 #undef PROMPT_RESPONSE
804 #undef EXPECTED_INTERMEDIATE
805 #undef EXPECTED_FINAL
806 };
807
808 } // namespace
809
810 TEST_F(DownloadManagerTest, DownloadFilenameTest) {
811 ASSERT_TRUE(CreateTempDownloadsDirectory());
812
813 // We create a known file to test file uniquification.
814 ASSERT_TRUE(file_util::WriteFile(
815 GetPathInDownloadsDir(FILE_PATH_LITERAL("exists.txt")), "", 0) == 0);
816 ASSERT_TRUE(file_util::WriteFile(
817 GetPathInDownloadsDir(FILE_PATH_LITERAL("exists.png.temp")), "", 0) == 0);
818
819 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadFilenameTestCases); ++i) {
820 const DownloadFilenameTestCase& test_case = kDownloadFilenameTestCases[i];
821 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
822
823 SCOPED_TRACE(testing::Message() << "Running test case " << i);
824 info->download_id = DownloadId(kValidIdDomain, i);
825 info->url_chain.push_back(GURL());
826
827 MockDownloadFile* download_file(
828 new ::testing::StrictMock<MockDownloadFile>());
829 FilePath target_path = GetPathInDownloadsDir(test_case.target_path);
830 FilePath expected_prompt_path =
831 GetPathInDownloadsDir(test_case.expected_prompt_path);
832 FilePath chosen_path = GetPathInDownloadsDir(test_case.chosen_path);
833 FilePath intermediate_path =
834 GetPathInDownloadsDir(test_case.intermediate_path);
835 FilePath expected_intermediate_path =
836 GetPathInDownloadsDir(test_case.expected_intermediate_path);
837 FilePath expected_final_path =
838 GetPathInDownloadsDir(test_case.expected_final_path);
839
840 AddMockDownloadToFileManager(info->download_id.local(), download_file);
841 EXPECT_CALL(*download_file, Rename(expected_intermediate_path))
842 .WillOnce(Return(net::OK));
843 EXPECT_CALL(*download_file, Rename(expected_final_path))
844 .WillOnce(Return(net::OK));
845 #if defined(OS_MACOSX)
846 EXPECT_CALL(*download_file, AnnotateWithSourceInformation());
847 #endif
848 EXPECT_CALL(*download_file, Detach());
849
850 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
851 DownloadItem* download = GetActiveDownloadItem(i);
852 ASSERT_TRUE(download != NULL);
853
854 if (test_case.completion == COMPLETES_BEFORE_RENAME)
855 OnResponseCompleted(i, 1024, std::string("fake_hash"));
856
857 download->OnTargetPathDetermined(
858 target_path, test_case.target_disposition,
859 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
860 download_manager_delegate_->SetFileSelectionExpectation(
861 expected_prompt_path, chosen_path);
862 download_manager_delegate_->SetIntermediatePath(
863 intermediate_path, test_case.overwrite_intermediate_path);
864 download_manager_delegate_->SetShouldCompleteDownload(false);
865 download_manager_->RestartDownload(i);
866 message_loop_.RunAllPending();
867
868 if (test_case.completion == COMPLETES_AFTER_RENAME) {
869 OnResponseCompleted(i, 1024, std::string("fake_hash"));
870 message_loop_.RunAllPending();
871 }
872
873 EXPECT_EQ(expected_intermediate_path.value(),
874 download->GetFullPath().value());
875 download_manager_delegate_->SetShouldCompleteDownload(true);
876 download_manager_delegate_->InvokeDownloadCompletionCallback();
877 message_loop_.RunAllPending();
878 EXPECT_EQ(expected_final_path.value(),
879 download->GetTargetFilePath().value());
880 }
881 }
882
883 void WriteCopyToStream(const char *source,
884 size_t len, content::ByteStreamWriter* stream) {
885 scoped_refptr<net::IOBuffer> copy(new net::IOBuffer(len));
886 memcpy(copy.get()->data(), source, len);
887 stream->Write(copy, len);
888 }
889
890 TEST_F(DownloadManagerTest, DownloadInterruptTest) {
891 using ::testing::_;
892 using ::testing::CreateFunctor;
893 using ::testing::Invoke;
894 using ::testing::Return;
895
896 // Normally, the download system takes ownership of info, and is
897 // responsible for deleting it. In these unit tests, however, we
898 // don't call the function that deletes it, so we do so ourselves.
899 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
900 info->download_id = DownloadId(kValidIdDomain, 0);
901 info->prompt_user_for_save_location = false;
902 info->url_chain.push_back(GURL());
903 info->total_bytes = static_cast<int64>(kTestDataLen);
904 const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
905 const FilePath cr_path(GetTempDownloadPath(new_path));
906
907 MockDownloadFile* download_file(new NiceMock<MockDownloadFile>());
908
909 // |download_file| is owned by DownloadFileManager.
910 AddMockDownloadToFileManager(info->download_id.local(), download_file);
911
912 EXPECT_CALL(*download_file, Rename(cr_path))
913 .WillOnce(Return(net::OK));
914 EXPECT_CALL(*download_file, Cancel());
915
916 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
917
918 DownloadItem* download = GetActiveDownloadItem(0);
919 ASSERT_TRUE(download != NULL);
920 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
921 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
922
923 ContinueDownloadWithPath(download, new_path);
924 message_loop_.RunAllPending();
925 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
926
927 int64 error_size = 3;
928 OnDownloadInterrupted(0, error_size, "",
929 content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
930 message_loop_.RunAllPending();
931
932 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
933 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
934 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
935 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
936 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
937 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
938 EXPECT_TRUE(observer->was_updated());
939 EXPECT_FALSE(observer->was_opened());
940 EXPECT_FALSE(download->GetFileExternallyRemoved());
941 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
942
943 download->Cancel(true);
944
945 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
946 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
947 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
948 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
949 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
950 EXPECT_TRUE(observer->was_updated());
951 EXPECT_FALSE(observer->was_opened());
952 EXPECT_FALSE(download->GetFileExternallyRemoved());
953 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
954 EXPECT_EQ(download->GetReceivedBytes(), error_size);
955 EXPECT_EQ(download->GetTotalBytes(), static_cast<int64>(kTestDataLen));
956 }
957
958 // Test the behavior of DownloadFileManager and DownloadManager in the event
959 // of a file error while writing the download to disk.
960 TEST_F(DownloadManagerTest, MAYBE_DownloadFileErrorTest) {
961 // Create a temporary file and a mock stream.
962 FilePath path;
963 ASSERT_TRUE(file_util::CreateTemporaryFile(&path));
964
965 // This file stream will be used, until the first rename occurs.
966 net::FileStream* stream = new net::FileStream(NULL);
967 ASSERT_EQ(0, stream->OpenSync(
968 path,
969 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE));
970
971 // Make sure the DFM exists; we'll need it later.
972 // TODO(rdsmith): This is ugly and should be rewritten, but a large
973 // rewrite of this test is in progress in a different CL, so doing it
974 // the hacky way for now.
975 (void) file_manager();
976
977 // Normally, the download system takes ownership of info, and is
978 // responsible for deleting it. In these unit tests, however, we
979 // don't call the function that deletes it, so we do so ourselves.
980 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
981 static const int32 local_id = 0;
982 info->download_id = DownloadId(kValidIdDomain, local_id);
983 info->prompt_user_for_save_location = false;
984 info->url_chain.push_back(GURL());
985 info->total_bytes = static_cast<int64>(kTestDataLen * 3);
986 info->save_info.file_path = path;
987 info->save_info.file_stream.reset(stream);
988 scoped_ptr<content::ByteStreamWriter> stream_input;
989 scoped_ptr<content::ByteStreamReader> stream_output;
990 content::CreateByteStream(message_loop_.message_loop_proxy(),
991 message_loop_.message_loop_proxy(),
992 kTestDataLen, &stream_input, &stream_output);
993
994 // Create a download file that we can insert errors into.
995 scoped_ptr<DownloadFileWithErrors> download_file(new DownloadFileWithErrors(
996 info.get(), stream_output.Pass(), download_manager_, false));
997 download_file->Initialize();
998
999 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1000
1001 DownloadItem* download = GetActiveDownloadItem(0);
1002 ASSERT_TRUE(download != NULL);
1003
1004 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1005 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1006
1007 // Add some data before finalizing the file name.
1008 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1009
1010 // Finalize the file name.
1011 ContinueDownloadWithPath(download, path);
1012 message_loop_.RunAllPending();
1013 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
1014
1015 // Add more data.
1016 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1017
1018 // Add more data, but an error occurs.
1019 download_file->set_forced_error(net::ERR_FAILED);
1020 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1021 message_loop_.RunAllPending();
1022
1023 // Check the state. The download should have been interrupted.
1024 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
1025 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1026 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
1027 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
1028 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1029 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1030 EXPECT_TRUE(observer->was_updated());
1031 EXPECT_FALSE(observer->was_opened());
1032 EXPECT_FALSE(download->GetFileExternallyRemoved());
1033 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1034
1035 // Clean up.
1036 download->Cancel(true);
1037 message_loop_.RunAllPending();
1038 }
1039
1040 TEST_F(DownloadManagerTest, DownloadCancelTest) {
1041 using ::testing::_;
1042 using ::testing::CreateFunctor;
1043 using ::testing::Invoke;
1044 using ::testing::Return;
1045
1046 // Normally, the download system takes ownership of info, and is
1047 // responsible for deleting it. In these unit tests, however, we
1048 // don't call the function that deletes it, so we do so ourselves.
1049 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
1050 DownloadId id = DownloadId(kValidIdDomain, 0);
1051 info->download_id = id;
1052 info->prompt_user_for_save_location = false;
1053 info->url_chain.push_back(GURL());
1054 const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
1055 const FilePath cr_path(GetTempDownloadPath(new_path));
1056
1057 MockDownloadFile* download_file(new NiceMock<MockDownloadFile>());
1058 AddMockDownloadToFileManager(info->download_id.local(), download_file);
1059
1060 // |download_file| is owned by DownloadFileManager.
1061 EXPECT_CALL(*download_file, Rename(cr_path))
1062 .WillOnce(Return(net::OK));
1063 EXPECT_CALL(*download_file, Cancel());
1064
1065 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1066
1067 DownloadItem* download = GetActiveDownloadItem(0);
1068 ASSERT_TRUE(download != NULL);
1069
1070 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1071 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1072
1073 ContinueDownloadWithPath(download, new_path);
1074 message_loop_.RunAllPending();
1075 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
1076
1077 download->Cancel(false);
1078 message_loop_.RunAllPending();
1079
1080 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
1081 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1082 EXPECT_TRUE(observer->hit_state(DownloadItem::CANCELLED));
1083 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1084 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
1085 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1086 EXPECT_TRUE(observer->was_updated());
1087 EXPECT_FALSE(observer->was_opened());
1088 EXPECT_FALSE(download->GetFileExternallyRemoved());
1089 EXPECT_EQ(DownloadItem::CANCELLED, download->GetState());
1090
1091 file_manager()->CancelDownload(id);
1092
1093 EXPECT_FALSE(file_util::PathExists(new_path));
1094 EXPECT_FALSE(file_util::PathExists(cr_path));
1095 }
1096
1097 TEST_F(DownloadManagerTest, MAYBE_DownloadOverwriteTest) {
1098 using ::testing::_;
1099 using ::testing::CreateFunctor;
1100 using ::testing::Invoke;
1101 using ::testing::Return;
1102
1103 ASSERT_TRUE(CreateTempDownloadsDirectory());
1104 // File names we're using.
1105 const FilePath new_path(GetPathInDownloadsDir(FILE_PATH_LITERAL("foo.txt")));
1106 const FilePath cr_path(GetTempDownloadPath(new_path));
1107 EXPECT_FALSE(file_util::PathExists(new_path));
1108
1109 // Create the file that we will overwrite. Will be automatically cleaned
1110 // up when temp_dir_ is destroyed.
1111 FILE* fp = file_util::OpenFile(new_path, "w");
1112 file_util::CloseFile(fp);
1113 EXPECT_TRUE(file_util::PathExists(new_path));
1114
1115 // Construct the unique file name that normally would be created, but
1116 // which we will override.
1117 int uniquifier =
1118 file_util::GetUniquePathNumber(new_path, FILE_PATH_LITERAL(""));
1119 FilePath unique_new_path = new_path;
1120 EXPECT_NE(0, uniquifier);
1121 unique_new_path = unique_new_path.InsertBeforeExtensionASCII(
1122 StringPrintf(" (%d)", uniquifier));
1123
1124 // Normally, the download system takes ownership of info, and is
1125 // responsible for deleting it. In these unit tests, however, we
1126 // don't call the function that deletes it, so we do so ourselves.
1127 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
1128 info->download_id = DownloadId(kValidIdDomain, 0);
1129 info->prompt_user_for_save_location = true;
1130 info->url_chain.push_back(GURL());
1131 scoped_ptr<content::ByteStreamWriter> stream_input;
1132 scoped_ptr<content::ByteStreamReader> stream_output;
1133 content::CreateByteStream(message_loop_.message_loop_proxy(),
1134 message_loop_.message_loop_proxy(),
1135 kTestDataLen, &stream_input, &stream_output);
1136
1137 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1138
1139 DownloadItem* download = GetActiveDownloadItem(0);
1140 ASSERT_TRUE(download != NULL);
1141
1142 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1143 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1144
1145 // Create and initialize the download file. We're bypassing the first part
1146 // of the download process and skipping to the part after the final file
1147 // name has been chosen, so we need to initialize the download file
1148 // properly.
1149 DownloadFile* download_file(
1150 new DownloadFileImpl(info.get(), stream_output.Pass(),
1151 new DownloadRequestHandle(),
1152 download_manager_, false,
1153 scoped_ptr<PowerSaveBlocker>(NULL).Pass(),
1154 net::BoundNetLog()));
1155 download_file->Rename(cr_path);
1156 // This creates the .temp version of the file.
1157 download_file->Initialize();
1158 // |download_file| is owned by DownloadFileManager.
1159 AddDownloadToFileManager(info->download_id.local(), download_file);
1160
1161 ContinueDownloadWithPath(download, new_path);
1162 message_loop_.RunAllPending();
1163 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
1164
1165 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1166
1167 // Finish the download.
1168 OnResponseCompleted(0, kTestDataLen, "");
1169 message_loop_.RunAllPending();
1170
1171 // Download is complete.
1172 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
1173 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1174 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1175 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1176 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
1177 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1178 EXPECT_TRUE(observer->was_updated());
1179 EXPECT_FALSE(observer->was_opened());
1180 EXPECT_FALSE(download->GetFileExternallyRemoved());
1181 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
1182
1183 EXPECT_TRUE(file_util::PathExists(new_path));
1184 EXPECT_FALSE(file_util::PathExists(cr_path));
1185 EXPECT_FALSE(file_util::PathExists(unique_new_path));
1186 std::string file_contents;
1187 EXPECT_TRUE(file_util::ReadFileToString(new_path, &file_contents));
1188 EXPECT_EQ(std::string(kTestData), file_contents);
1189 }
1190
1191 TEST_F(DownloadManagerTest, MAYBE_DownloadRemoveTest) {
1192 using ::testing::_;
1193 using ::testing::CreateFunctor;
1194 using ::testing::Invoke;
1195 using ::testing::Return;
1196
1197 ASSERT_TRUE(CreateTempDownloadsDirectory());
1198
1199 // File names we're using.
1200 const FilePath new_path(GetPathInDownloadsDir(FILE_PATH_LITERAL("foo.txt")));
1201 const FilePath cr_path(GetTempDownloadPath(new_path));
1202 EXPECT_FALSE(file_util::PathExists(new_path));
1203
1204 // Normally, the download system takes ownership of info, and is
1205 // responsible for deleting it. In these unit tests, however, we
1206 // don't call the function that deletes it, so we do so ourselves.
1207 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
1208 info->download_id = DownloadId(kValidIdDomain, 0);
1209 info->prompt_user_for_save_location = true;
1210 info->url_chain.push_back(GURL());
1211 scoped_ptr<content::ByteStreamWriter> stream_input;
1212 scoped_ptr<content::ByteStreamReader> stream_output;
1213 content::CreateByteStream(message_loop_.message_loop_proxy(),
1214 message_loop_.message_loop_proxy(),
1215 kTestDataLen, &stream_input, &stream_output);
1216
1217 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1218
1219 DownloadItem* download = GetActiveDownloadItem(0);
1220 ASSERT_TRUE(download != NULL);
1221
1222 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1223 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1224
1225 // Create and initialize the download file. We're bypassing the first part
1226 // of the download process and skipping to the part after the final file
1227 // name has been chosen, so we need to initialize the download file
1228 // properly.
1229 DownloadFile* download_file(
1230 new DownloadFileImpl(info.get(), stream_output.Pass(),
1231 new DownloadRequestHandle(),
1232 download_manager_, false,
1233 scoped_ptr<PowerSaveBlocker>(NULL).Pass(),
1234 net::BoundNetLog()));
1235 download_file->Rename(cr_path);
1236 // This creates the .temp version of the file.
1237 download_file->Initialize();
1238 // |download_file| is owned by DownloadFileManager.
1239 AddDownloadToFileManager(info->download_id.local(), download_file);
1240
1241 ContinueDownloadWithPath(download, new_path);
1242 message_loop_.RunAllPending();
1243 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
1244
1245 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1246
1247 // Finish the download.
1248 OnResponseCompleted(0, kTestDataLen, "");
1249 message_loop_.RunAllPending();
1250
1251 // Download is complete.
1252 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
1253 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1254 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1255 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1256 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
1257 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1258 EXPECT_TRUE(observer->was_updated());
1259 EXPECT_FALSE(observer->was_opened());
1260 EXPECT_FALSE(download->GetFileExternallyRemoved());
1261 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
1262
1263 EXPECT_TRUE(file_util::PathExists(new_path));
1264 EXPECT_FALSE(file_util::PathExists(cr_path));
1265
1266 // Remove the downloaded file.
1267 ASSERT_TRUE(file_util::Delete(new_path, false));
1268 download->OnDownloadedFileRemoved();
1269 message_loop_.RunAllPending();
1270
1271 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
1272 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1273 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1274 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1275 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
1276 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1277 EXPECT_TRUE(observer->was_updated());
1278 EXPECT_FALSE(observer->was_opened());
1279 EXPECT_TRUE(download->GetFileExternallyRemoved());
1280 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
1281
1282 EXPECT_FALSE(file_util::PathExists(new_path));
1283 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698