OLD | NEW |
---|---|
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 } | |
OLD | NEW |