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

Side by Side Diff: trunk/src/content/browser/download/download_file_unittest.cc

Issue 342233002: Revert 278483 "[Downloads] Retry renames after transient failures." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 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 "base/file_util.h" 5 #include "base/file_util.h"
6 #include "base/files/file.h"
7 #include "base/message_loop/message_loop.h" 6 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/strings/string_number_conversions.h" 7 #include "base/strings/string_number_conversions.h"
10 #include "base/test/test_file_util.h" 8 #include "base/test/test_file_util.h"
11 #include "content/browser/browser_thread_impl.h" 9 #include "content/browser/browser_thread_impl.h"
12 #include "content/browser/byte_stream.h" 10 #include "content/browser/byte_stream.h"
13 #include "content/browser/download/download_create_info.h" 11 #include "content/browser/download/download_create_info.h"
14 #include "content/browser/download/download_file_impl.h" 12 #include "content/browser/download/download_file_impl.h"
15 #include "content/browser/download/download_request_handle.h" 13 #include "content/browser/download/download_request_handle.h"
16 #include "content/public/browser/download_destination_observer.h" 14 #include "content/public/browser/download_destination_observer.h"
17 #include "content/public/browser/download_interrupt_reasons.h" 15 #include "content/public/browser/download_interrupt_reasons.h"
18 #include "content/public/browser/download_manager.h" 16 #include "content/public/browser/download_manager.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 52
55 // Doesn't override any methods in the base class. Used to make sure 53 // Doesn't override any methods in the base class. Used to make sure
56 // that the last DestinationUpdate before a Destination{Completed,Error} 54 // that the last DestinationUpdate before a Destination{Completed,Error}
57 // had the right values. 55 // had the right values.
58 MOCK_METHOD3(CurrentUpdateStatus, 56 MOCK_METHOD3(CurrentUpdateStatus,
59 void(int64, int64, const std::string&)); 57 void(int64, int64, const std::string&));
60 }; 58 };
61 59
62 MATCHER(IsNullCallback, "") { return (arg.is_null()); } 60 MATCHER(IsNullCallback, "") { return (arg.is_null()); }
63 61
64 typedef void (DownloadFile::*DownloadFileRenameMethodType)(
65 const base::FilePath&,
66 const DownloadFile::RenameCompletionCallback&);
67
68 // This is a test DownloadFileImpl that has no retry delay and, on Posix,
69 // retries renames failed due to ACCESS_DENIED.
70 class TestDownloadFileImpl : public DownloadFileImpl {
71 public:
72 TestDownloadFileImpl(scoped_ptr<DownloadSaveInfo> save_info,
73 const base::FilePath& default_downloads_directory,
74 const GURL& url,
75 const GURL& referrer_url,
76 bool calculate_hash,
77 scoped_ptr<ByteStreamReader> stream,
78 const net::BoundNetLog& bound_net_log,
79 base::WeakPtr<DownloadDestinationObserver> observer)
80 : DownloadFileImpl(save_info.Pass(),
81 default_downloads_directory,
82 url,
83 referrer_url,
84 calculate_hash,
85 stream.Pass(),
86 bound_net_log,
87 observer) {}
88
89 protected:
90 virtual base::TimeDelta GetRetryDelayForFailedRename(
91 int attempt_count) OVERRIDE {
92 return base::TimeDelta::FromMilliseconds(0);
93 }
94
95 #if !defined(OS_WIN)
96 // On Posix, we don't encounter transient errors during renames, except
97 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to
98 // simulating a transient error using ACCESS_DENIED instead.
99 virtual bool ShouldRetryFailedRename(
100 DownloadInterruptReason reason) OVERRIDE {
101 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
102 }
103 #endif
104 };
105
106 } // namespace 62 } // namespace
107 63
108 class DownloadFileTest : public testing::Test { 64 class DownloadFileTest : public testing::Test {
109 public: 65 public:
110 66
111 static const char* kTestData1; 67 static const char* kTestData1;
112 static const char* kTestData2; 68 static const char* kTestData2;
113 static const char* kTestData3; 69 static const char* kTestData3;
114 static const char* kDataHash; 70 static const char* kDataHash;
115 static const uint32 kDummyDownloadId; 71 static const uint32 kDummyDownloadId;
(...skipping 25 matching lines...) Expand all
141 observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_, hash_state_); 97 observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_, hash_state_);
142 } 98 }
143 99
144 virtual void SetUp() { 100 virtual void SetUp() {
145 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _)) 101 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
146 .Times(AnyNumber()) 102 .Times(AnyNumber())
147 .WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo)); 103 .WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo));
148 } 104 }
149 105
150 // Mock calls to this function are forwarded here. 106 // Mock calls to this function are forwarded here.
151 void RegisterCallback(const base::Closure& sink_callback) { 107 void RegisterCallback(base::Closure sink_callback) {
152 sink_callback_ = sink_callback; 108 sink_callback_ = sink_callback;
153 } 109 }
154 110
155 void SetInterruptReasonCallback(const base::Closure& closure, 111 void SetInterruptReasonCallback(bool* was_called,
156 DownloadInterruptReason* reason_p, 112 DownloadInterruptReason* reason_p,
157 DownloadInterruptReason reason) { 113 DownloadInterruptReason reason) {
114 *was_called = true;
158 *reason_p = reason; 115 *reason_p = reason;
159 closure.Run();
160 } 116 }
161 117
162 bool CreateDownloadFile(int offset, bool calculate_hash) { 118 bool CreateDownloadFile(int offset, bool calculate_hash) {
163 // There can be only one. 119 // There can be only one.
164 DCHECK(!download_file_.get()); 120 DCHECK(!download_file_.get());
165 121
166 input_stream_ = new StrictMock<MockByteStreamReader>(); 122 input_stream_ = new StrictMock<MockByteStreamReader>();
167 123
168 // TODO: Need to actually create a function that'll set the variables 124 // TODO: Need to actually create a function that'll set the variables
169 // based on the inputs from the callback. 125 // based on the inputs from the callback.
170 EXPECT_CALL(*input_stream_, RegisterCallback(_)) 126 EXPECT_CALL(*input_stream_, RegisterCallback(_))
171 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) 127 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback))
172 .RetiresOnSaturation(); 128 .RetiresOnSaturation();
173 129
174 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); 130 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
175 scoped_ptr<TestDownloadFileImpl> download_file_impl( 131 download_file_.reset(
176 new TestDownloadFileImpl(save_info.Pass(), 132 new DownloadFileImpl(save_info.Pass(),
177 base::FilePath(), 133 base::FilePath(),
178 GURL(), // Source 134 GURL(), // Source
179 GURL(), // Referrer 135 GURL(), // Referrer
180 calculate_hash, 136 calculate_hash,
181 scoped_ptr<ByteStreamReader>(input_stream_), 137 scoped_ptr<ByteStreamReader>(input_stream_),
182 net::BoundNetLog(), 138 net::BoundNetLog(),
183 observer_factory_.GetWeakPtr())); 139 observer_factory_.GetWeakPtr()));
184 download_file_impl->SetClientGuid("12345678-ABCD-1234-DCBA-123456789ABC"); 140 download_file_->SetClientGuid(
185 download_file_ = download_file_impl.PassAs<DownloadFile>(); 141 "12345678-ABCD-1234-DCBA-123456789ABC");
186 142
187 EXPECT_CALL(*input_stream_, Read(_, _)) 143 EXPECT_CALL(*input_stream_, Read(_, _))
188 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) 144 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
189 .RetiresOnSaturation(); 145 .RetiresOnSaturation();
190 146
191 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); 147 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
192 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; 148 bool called = false;
193 base::RunLoop loop_runner; 149 DownloadInterruptReason result;
194 download_file_->Initialize(base::Bind( 150 download_file_->Initialize(base::Bind(
195 &DownloadFileTest::SetInterruptReasonCallback, 151 &DownloadFileTest::SetInterruptReasonCallback,
196 weak_ptr_factory.GetWeakPtr(), loop_runner.QuitClosure(), &result)); 152 weak_ptr_factory.GetWeakPtr(), &called, &result));
197 loop_runner.Run(); 153 loop_.RunUntilIdle();
154 EXPECT_TRUE(called);
198 155
199 ::testing::Mock::VerifyAndClearExpectations(input_stream_); 156 ::testing::Mock::VerifyAndClearExpectations(input_stream_);
200 return result == DOWNLOAD_INTERRUPT_REASON_NONE; 157 return result == DOWNLOAD_INTERRUPT_REASON_NONE;
201 } 158 }
202 159
203 void DestroyDownloadFile(int offset) { 160 void DestroyDownloadFile(int offset) {
204 EXPECT_FALSE(download_file_->InProgress()); 161 EXPECT_FALSE(download_file_->InProgress());
205 162
206 // Make sure the data has been properly written to disk. 163 // Make sure the data has been properly written to disk.
207 std::string disk_data; 164 std::string disk_data;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _)) 236 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
280 .Times(AnyNumber()) 237 .Times(AnyNumber())
281 .WillRepeatedly(Invoke(this, 238 .WillRepeatedly(Invoke(this,
282 &DownloadFileTest::SetUpdateDownloadInfo)); 239 &DownloadFileTest::SetUpdateDownloadInfo));
283 } 240 }
284 } 241 }
285 242
286 DownloadInterruptReason RenameAndUniquify( 243 DownloadInterruptReason RenameAndUniquify(
287 const base::FilePath& full_path, 244 const base::FilePath& full_path,
288 base::FilePath* result_path_p) { 245 base::FilePath* result_path_p) {
289 return InvokeRenameMethodAndWaitForCallback( 246 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
290 &DownloadFile::RenameAndUniquify, full_path, result_path_p); 247 DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
248 bool callback_was_called(false);
249 base::FilePath result_path;
250
251 download_file_->RenameAndUniquify(
252 full_path, base::Bind(&DownloadFileTest::SetRenameResult,
253 weak_ptr_factory.GetWeakPtr(),
254 &callback_was_called,
255 &result_reason, result_path_p));
256 loop_.RunUntilIdle();
257
258 EXPECT_TRUE(callback_was_called);
259 return result_reason;
291 } 260 }
292 261
293 DownloadInterruptReason RenameAndAnnotate( 262 DownloadInterruptReason RenameAndAnnotate(
294 const base::FilePath& full_path, 263 const base::FilePath& full_path,
295 base::FilePath* result_path_p) { 264 base::FilePath* result_path_p) {
296 return InvokeRenameMethodAndWaitForCallback( 265 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
297 &DownloadFile::RenameAndAnnotate, full_path, result_path_p); 266 DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
267 bool callback_was_called(false);
268 base::FilePath result_path;
269
270 download_file_->RenameAndAnnotate(
271 full_path, base::Bind(&DownloadFileTest::SetRenameResult,
272 weak_ptr_factory.GetWeakPtr(),
273 &callback_was_called,
274 &result_reason, result_path_p));
275 loop_.RunUntilIdle();
276
277 EXPECT_TRUE(callback_was_called);
278 return result_reason;
298 } 279 }
299 280
300 protected: 281 protected:
301 DownloadInterruptReason InvokeRenameMethodAndWaitForCallback(
302 DownloadFileRenameMethodType method,
303 const base::FilePath& full_path,
304 base::FilePath* result_path_p) {
305 DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
306 base::FilePath result_path;
307
308 base::RunLoop loop_runner;
309 ((*download_file_).*method)(full_path,
310 base::Bind(&DownloadFileTest::SetRenameResult,
311 base::Unretained(this),
312 loop_runner.QuitClosure(),
313 &result_reason,
314 result_path_p));
315 loop_runner.Run();
316 return result_reason;
317 }
318
319 scoped_ptr<StrictMock<MockDownloadDestinationObserver> > observer_; 282 scoped_ptr<StrictMock<MockDownloadDestinationObserver> > observer_;
320 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; 283 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_;
321 284
322 // DownloadFile instance we are testing. 285 // DownloadFile instance we are testing.
323 scoped_ptr<DownloadFile> download_file_; 286 scoped_ptr<DownloadFile> download_file_;
324 287
325 // Stream for sending data into the download file. 288 // Stream for sending data into the download file.
326 // Owned by download_file_; will be alive for lifetime of download_file_. 289 // Owned by download_file_; will be alive for lifetime of download_file_.
327 StrictMock<MockByteStreamReader>* input_stream_; 290 StrictMock<MockByteStreamReader>* input_stream_;
328 291
329 // Sink callback data for stream. 292 // Sink callback data for stream.
330 base::Closure sink_callback_; 293 base::Closure sink_callback_;
331 294
332 // Latest update sent to the observer. 295 // Latest update sent to the observer.
333 int64 bytes_; 296 int64 bytes_;
334 int64 bytes_per_sec_; 297 int64 bytes_per_sec_;
335 std::string hash_state_; 298 std::string hash_state_;
336 299
337 base::MessageLoop loop_; 300 base::MessageLoop loop_;
338 301
339 private: 302 private:
340 void SetRenameResult(const base::Closure& closure, 303 void SetRenameResult(bool* called_p,
341 DownloadInterruptReason* reason_p, 304 DownloadInterruptReason* reason_p,
342 base::FilePath* result_path_p, 305 base::FilePath* result_path_p,
343 DownloadInterruptReason reason, 306 DownloadInterruptReason reason,
344 const base::FilePath& result_path) { 307 const base::FilePath& result_path) {
308 if (called_p)
309 *called_p = true;
345 if (reason_p) 310 if (reason_p)
346 *reason_p = reason; 311 *reason_p = reason;
347 if (result_path_p) 312 if (result_path_p)
348 *result_path_p = result_path; 313 *result_path_p = result_path;
349 closure.Run();
350 } 314 }
351 315
352 // UI thread. 316 // UI thread.
353 BrowserThreadImpl ui_thread_; 317 BrowserThreadImpl ui_thread_;
354 // File thread to satisfy debug checks in DownloadFile. 318 // File thread to satisfy debug checks in DownloadFile.
355 BrowserThreadImpl file_thread_; 319 BrowserThreadImpl file_thread_;
356 320
357 // Keep track of what data should be saved to the disk file. 321 // Keep track of what data should be saved to the disk file.
358 std::string expected_data_; 322 std::string expected_data_;
359 }; 323 };
360 324
361 // DownloadFile::RenameAndAnnotate and DownloadFile::RenameAndUniquify have a
362 // considerable amount of functional overlap. In order to re-use test logic, we
363 // are going to introduce this value parameterized test fixture. It will take a
364 // DownloadFileRenameMethodType value which can be either of the two rename
365 // methods.
366 class DownloadFileTestWithRename
367 : public DownloadFileTest,
368 public ::testing::WithParamInterface<DownloadFileRenameMethodType> {
369 protected:
370 DownloadInterruptReason InvokeSelectedRenameMethod(
371 const base::FilePath& full_path,
372 base::FilePath* result_path_p) {
373 return InvokeRenameMethodAndWaitForCallback(
374 GetParam(), full_path, result_path_p);
375 }
376 };
377
378 // And now instantiate all DownloadFileTestWithRename tests using both
379 // DownloadFile rename methods. Each test of the form
380 // DownloadFileTestWithRename.<FooTest> will be instantiated once with
381 // RenameAndAnnotate as the value parameter and once with RenameAndUniquify as
382 // the value parameter.
383 INSTANTIATE_TEST_CASE_P(DownloadFile,
384 DownloadFileTestWithRename,
385 ::testing::Values(&DownloadFile::RenameAndAnnotate,
386 &DownloadFile::RenameAndUniquify));
387
388 const char* DownloadFileTest::kTestData1 = 325 const char* DownloadFileTest::kTestData1 =
389 "Let's write some data to the file!\n"; 326 "Let's write some data to the file!\n";
390 const char* DownloadFileTest::kTestData2 = "Writing more data.\n"; 327 const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
391 const char* DownloadFileTest::kTestData3 = "Final line."; 328 const char* DownloadFileTest::kTestData3 = "Final line.";
392 const char* DownloadFileTest::kDataHash = 329 const char* DownloadFileTest::kDataHash =
393 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; 330 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
394 331
395 const uint32 DownloadFileTest::kDummyDownloadId = 23; 332 const uint32 DownloadFileTest::kDummyDownloadId = 23;
396 const int DownloadFileTest::kDummyChildId = 3; 333 const int DownloadFileTest::kDummyChildId = 3;
397 const int DownloadFileTest::kDummyRequestId = 67; 334 const int DownloadFileTest::kDummyRequestId = 67;
398 335
399 // Rename the file before any data is downloaded, after some has, after it all 336 // Rename the file before any data is downloaded, after some has, after it all
400 // has, and after it's closed. 337 // has, and after it's closed.
401 TEST_P(DownloadFileTestWithRename, RenameFileFinal) { 338 TEST_F(DownloadFileTest, RenameFileFinal) {
402 ASSERT_TRUE(CreateDownloadFile(0, true)); 339 ASSERT_TRUE(CreateDownloadFile(0, true));
403 base::FilePath initial_path(download_file_->FullPath()); 340 base::FilePath initial_path(download_file_->FullPath());
404 EXPECT_TRUE(base::PathExists(initial_path)); 341 EXPECT_TRUE(base::PathExists(initial_path));
405 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); 342 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
406 base::FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2")); 343 base::FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2"));
407 base::FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3")); 344 base::FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3"));
408 base::FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4")); 345 base::FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4"));
346 base::FilePath path_5(initial_path.InsertBeforeExtensionASCII("_5"));
409 base::FilePath output_path; 347 base::FilePath output_path;
410 348
411 // Rename the file before downloading any data. 349 // Rename the file before downloading any data.
412 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 350 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
413 InvokeSelectedRenameMethod(path_1, &output_path)); 351 RenameAndUniquify(path_1, &output_path));
414 base::FilePath renamed_path = download_file_->FullPath(); 352 base::FilePath renamed_path = download_file_->FullPath();
415 EXPECT_EQ(path_1, renamed_path); 353 EXPECT_EQ(path_1, renamed_path);
416 EXPECT_EQ(path_1, output_path); 354 EXPECT_EQ(path_1, output_path);
417 355
418 // Check the files. 356 // Check the files.
419 EXPECT_FALSE(base::PathExists(initial_path)); 357 EXPECT_FALSE(base::PathExists(initial_path));
420 EXPECT_TRUE(base::PathExists(path_1)); 358 EXPECT_TRUE(base::PathExists(path_1));
421 359
422 // Download the data. 360 // Download the data.
423 const char* chunks1[] = { kTestData1, kTestData2 }; 361 const char* chunks1[] = { kTestData1, kTestData2 };
424 AppendDataToFile(chunks1, 2); 362 AppendDataToFile(chunks1, 2);
425 363
426 // Rename the file after downloading some data. 364 // Rename the file after downloading some data.
427 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 365 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
428 InvokeSelectedRenameMethod(path_2, &output_path)); 366 RenameAndUniquify(path_2, &output_path));
429 renamed_path = download_file_->FullPath(); 367 renamed_path = download_file_->FullPath();
430 EXPECT_EQ(path_2, renamed_path); 368 EXPECT_EQ(path_2, renamed_path);
431 EXPECT_EQ(path_2, output_path); 369 EXPECT_EQ(path_2, output_path);
432 370
433 // Check the files. 371 // Check the files.
434 EXPECT_FALSE(base::PathExists(path_1)); 372 EXPECT_FALSE(base::PathExists(path_1));
435 EXPECT_TRUE(base::PathExists(path_2)); 373 EXPECT_TRUE(base::PathExists(path_2));
436 374
437 const char* chunks2[] = { kTestData3 }; 375 const char* chunks2[] = { kTestData3 };
438 AppendDataToFile(chunks2, 1); 376 AppendDataToFile(chunks2, 1);
439 377
440 // Rename the file after downloading all the data. 378 // Rename the file after downloading all the data.
441 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 379 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
442 InvokeSelectedRenameMethod(path_3, &output_path)); 380 RenameAndUniquify(path_3, &output_path));
443 renamed_path = download_file_->FullPath(); 381 renamed_path = download_file_->FullPath();
444 EXPECT_EQ(path_3, renamed_path); 382 EXPECT_EQ(path_3, renamed_path);
445 EXPECT_EQ(path_3, output_path); 383 EXPECT_EQ(path_3, output_path);
446 384
447 // Check the files. 385 // Check the files.
448 EXPECT_FALSE(base::PathExists(path_2)); 386 EXPECT_FALSE(base::PathExists(path_2));
449 EXPECT_TRUE(base::PathExists(path_3)); 387 EXPECT_TRUE(base::PathExists(path_3));
450 388
451 // Should not be able to get the hash until the file is closed. 389 // Should not be able to get the hash until the file is closed.
452 std::string hash; 390 std::string hash;
453 EXPECT_FALSE(download_file_->GetHash(&hash)); 391 EXPECT_FALSE(download_file_->GetHash(&hash));
454 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); 392 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
455 loop_.RunUntilIdle(); 393 loop_.RunUntilIdle();
456 394
457 // Rename the file after downloading all the data and closing the file. 395 // Rename the file after downloading all the data and closing the file.
458 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 396 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
459 InvokeSelectedRenameMethod(path_4, &output_path)); 397 RenameAndUniquify(path_4, &output_path));
460 renamed_path = download_file_->FullPath(); 398 renamed_path = download_file_->FullPath();
461 EXPECT_EQ(path_4, renamed_path); 399 EXPECT_EQ(path_4, renamed_path);
462 EXPECT_EQ(path_4, output_path); 400 EXPECT_EQ(path_4, output_path);
463 401
464 // Check the files. 402 // Check the files.
465 EXPECT_FALSE(base::PathExists(path_3)); 403 EXPECT_FALSE(base::PathExists(path_3));
466 EXPECT_TRUE(base::PathExists(path_4)); 404 EXPECT_TRUE(base::PathExists(path_4));
467 405
468 // Check the hash. 406 // Check the hash.
469 EXPECT_TRUE(download_file_->GetHash(&hash)); 407 EXPECT_TRUE(download_file_->GetHash(&hash));
470 EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size())); 408 EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));
471 409
410 // Check that a rename with overwrite to an existing file succeeds.
411 std::string file_contents;
412 ASSERT_FALSE(base::PathExists(path_5));
413 static const char file_data[] = "xyzzy";
414 ASSERT_EQ(static_cast<int>(sizeof(file_data) - 1),
415 base::WriteFile(path_5, file_data, sizeof(file_data) - 1));
416 ASSERT_TRUE(base::PathExists(path_5));
417 EXPECT_TRUE(base::ReadFileToString(path_5, &file_contents));
418 EXPECT_EQ(std::string(file_data), file_contents);
419
420 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
421 RenameAndAnnotate(path_5, &output_path));
422 EXPECT_EQ(path_5, output_path);
423
424 file_contents = "";
425 EXPECT_TRUE(base::ReadFileToString(path_5, &file_contents));
426 EXPECT_NE(std::string(file_data), file_contents);
427
472 DestroyDownloadFile(0); 428 DestroyDownloadFile(0);
473 } 429 }
474 430
475 // Test to make sure the rename overwrites when requested. This is separate from
476 // the above test because it only applies to RenameAndAnnotate().
477 // RenameAndUniquify() doesn't overwrite by design.
478 TEST_F(DownloadFileTest, RenameOverwrites) {
479 ASSERT_TRUE(CreateDownloadFile(0, true));
480 base::FilePath initial_path(download_file_->FullPath());
481 EXPECT_TRUE(base::PathExists(initial_path));
482 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
483
484 ASSERT_FALSE(base::PathExists(path_1));
485 static const char file_data[] = "xyzzy";
486 ASSERT_EQ(static_cast<int>(sizeof(file_data)),
487 base::WriteFile(path_1, file_data, sizeof(file_data)));
488 ASSERT_TRUE(base::PathExists(path_1));
489
490 base::FilePath new_path;
491 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
492 RenameAndAnnotate(path_1, &new_path));
493 EXPECT_EQ(path_1.value(), new_path.value());
494
495 std::string file_contents;
496 ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
497 EXPECT_NE(std::string(file_data), file_contents);
498
499 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
500 loop_.RunUntilIdle();
501 DestroyDownloadFile(0);
502 }
503
504 // Test to make sure the rename uniquifies if we aren't overwriting 431 // Test to make sure the rename uniquifies if we aren't overwriting
505 // and there's a file where we're aiming. As above, not a 432 // and there's a file where we're aiming.
506 // DownloadFileTestWithRename test because this only applies to
507 // RenameAndUniquify().
508 TEST_F(DownloadFileTest, RenameUniquifies) { 433 TEST_F(DownloadFileTest, RenameUniquifies) {
509 ASSERT_TRUE(CreateDownloadFile(0, true)); 434 ASSERT_TRUE(CreateDownloadFile(0, true));
510 base::FilePath initial_path(download_file_->FullPath()); 435 base::FilePath initial_path(download_file_->FullPath());
511 EXPECT_TRUE(base::PathExists(initial_path)); 436 EXPECT_TRUE(base::PathExists(initial_path));
512 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); 437 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
513 base::FilePath path_1_suffixed(path_1.InsertBeforeExtensionASCII(" (1)")); 438 base::FilePath path_1_suffixed(path_1.InsertBeforeExtensionASCII(" (1)"));
514 439
515 ASSERT_FALSE(base::PathExists(path_1)); 440 ASSERT_FALSE(base::PathExists(path_1));
516 static const char file_data[] = "xyzzy"; 441 static const char file_data[] = "xyzzy";
517 ASSERT_EQ(static_cast<int>(sizeof(file_data)), 442 ASSERT_EQ(static_cast<int>(sizeof(file_data)),
518 base::WriteFile(path_1, file_data, sizeof(file_data))); 443 base::WriteFile(path_1, file_data, sizeof(file_data)));
519 ASSERT_TRUE(base::PathExists(path_1)); 444 ASSERT_TRUE(base::PathExists(path_1));
520 445
521 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, RenameAndUniquify(path_1, NULL)); 446 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, RenameAndUniquify(path_1, NULL));
522 EXPECT_TRUE(base::PathExists(path_1_suffixed)); 447 EXPECT_TRUE(base::PathExists(path_1_suffixed));
523 448
524 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); 449 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
525 loop_.RunUntilIdle(); 450 loop_.RunUntilIdle();
526 DestroyDownloadFile(0); 451 DestroyDownloadFile(0);
527 } 452 }
528 453
529 // Test that RenameAndUniquify doesn't try to uniquify in the case where the
530 // target filename is the same as the current filename.
531 TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) {
532 ASSERT_TRUE(CreateDownloadFile(0, true));
533 base::FilePath initial_path(download_file_->FullPath());
534 EXPECT_TRUE(base::PathExists(initial_path));
535
536 base::FilePath new_path;
537 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
538 RenameAndUniquify(initial_path, &new_path));
539 EXPECT_TRUE(base::PathExists(initial_path));
540
541 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
542 loop_.RunUntilIdle();
543 DestroyDownloadFile(0);
544 EXPECT_EQ(initial_path.value(), new_path.value());
545 }
546
547 // Test to make sure we get the proper error on failure. 454 // Test to make sure we get the proper error on failure.
548 TEST_P(DownloadFileTestWithRename, RenameError) { 455 TEST_F(DownloadFileTest, RenameError) {
549 ASSERT_TRUE(CreateDownloadFile(0, true)); 456 ASSERT_TRUE(CreateDownloadFile(0, true));
550 base::FilePath initial_path(download_file_->FullPath()); 457 base::FilePath initial_path(download_file_->FullPath());
551 458
552 // Create a subdirectory. 459 // Create a subdirectory.
553 base::FilePath target_dir( 460 base::FilePath tempdir(
554 initial_path.DirName().Append(FILE_PATH_LITERAL("TargetDir"))); 461 initial_path.DirName().Append(FILE_PATH_LITERAL("tempdir")));
555 ASSERT_FALSE(base::DirectoryExists(target_dir)); 462 ASSERT_TRUE(base::CreateDirectory(tempdir));
556 ASSERT_TRUE(base::CreateDirectory(target_dir)); 463 base::FilePath target_path(tempdir.Append(initial_path.BaseName()));
557 base::FilePath target_path(target_dir.Append(initial_path.BaseName()));
558 464
559 // Targets 465 // Targets
560 base::FilePath target_path_suffixed( 466 base::FilePath target_path_suffixed(
561 target_path.InsertBeforeExtensionASCII(" (1)")); 467 target_path.InsertBeforeExtensionASCII(" (1)"));
562 ASSERT_FALSE(base::PathExists(target_path)); 468 ASSERT_FALSE(base::PathExists(target_path));
563 ASSERT_FALSE(base::PathExists(target_path_suffixed)); 469 ASSERT_FALSE(base::PathExists(target_path_suffixed));
564 470
565 // Make the directory unwritable and try to rename within it. 471 // Make the directory unwritable and try to rename within it.
566 { 472 {
567 file_util::PermissionRestorer restorer(target_dir); 473 file_util::PermissionRestorer restorer(tempdir);
568 ASSERT_TRUE(file_util::MakeFileUnwritable(target_dir)); 474 ASSERT_TRUE(file_util::MakeFileUnwritable(tempdir));
569 475
570 // Expect nulling out of further processing. 476 // Expect nulling out of further processing.
571 EXPECT_CALL(*input_stream_, RegisterCallback(IsNullCallback())); 477 EXPECT_CALL(*input_stream_, RegisterCallback(IsNullCallback()));
572 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED, 478 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
573 InvokeSelectedRenameMethod(target_path, NULL)); 479 RenameAndAnnotate(target_path, NULL));
574 EXPECT_FALSE(base::PathExists(target_path_suffixed)); 480 EXPECT_FALSE(base::PathExists(target_path_suffixed));
575 } 481 }
576 482
577 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); 483 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
578 loop_.RunUntilIdle(); 484 loop_.RunUntilIdle();
579 DestroyDownloadFile(0); 485 DestroyDownloadFile(0);
580 } 486 }
581 487
582 namespace {
583
584 void TestRenameCompletionCallback(const base::Closure& closure,
585 bool* did_run_callback,
586 DownloadInterruptReason interrupt_reason,
587 const base::FilePath& new_path) {
588 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
589 *did_run_callback = true;
590 closure.Run();
591 }
592
593 } // namespace
594
595 // Test that the retry logic works. This test assumes that DownloadFileImpl will
596 // post tasks to the current message loop (acting as the FILE thread)
597 // asynchronously to retry the renames. We will stuff RunLoop::QuitClosures()
598 // in between the retry tasks to stagger them and then allow the rename to
599 // succeed.
600 //
601 // Note that there is only one queue of tasks to run, and that is in the tests'
602 // base::MessageLoop::current(). Each RunLoop processes that queue until it sees
603 // a QuitClosure() targeted at itself, at which point it stops processing.
604 TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
605 ASSERT_TRUE(CreateDownloadFile(0, true));
606 base::FilePath initial_path(download_file_->FullPath());
607
608 // Create a subdirectory.
609 base::FilePath target_dir(
610 initial_path.DirName().Append(FILE_PATH_LITERAL("TargetDir")));
611 ASSERT_FALSE(base::DirectoryExists(target_dir));
612 ASSERT_TRUE(base::CreateDirectory(target_dir));
613 base::FilePath target_path(target_dir.Append(initial_path.BaseName()));
614
615 bool did_run_callback = false;
616
617 // Each RunLoop can be used the run the MessageLoop until the corresponding
618 // QuitClosure() is run. This one is used to produce the QuitClosure() that
619 // will be run when the entire rename operation is complete.
620 base::RunLoop succeeding_run;
621 {
622 // (Scope for the base::File or file_util::PermissionRestorer below.)
623 #if defined(OS_WIN)
624 // On Windows we test with an actual transient error, a sharing violation.
625 // The rename will fail because we are holding the file open for READ. On
626 // Posix this doesn't cause a failure.
627 base::File locked_file(initial_path,
628 base::File::FLAG_OPEN | base::File::FLAG_READ);
629 ASSERT_TRUE(locked_file.IsValid());
630 #else
631 // Simulate a transient failure by revoking write permission for target_dir.
632 // The TestDownloadFileImpl class treats this error as transient even though
633 // DownloadFileImpl itself doesn't.
634 file_util::PermissionRestorer restore_permissions_for(target_dir);
635 ASSERT_TRUE(file_util::MakeFileUnwritable(target_dir));
636 #endif
637
638 // The Rename() should fail here and enqueue a retry task without invoking
639 // the completion callback.
640 ((*download_file_).*GetParam())(target_path,
641 base::Bind(&TestRenameCompletionCallback,
642 succeeding_run.QuitClosure(),
643 &did_run_callback));
644 EXPECT_FALSE(did_run_callback);
645
646 base::RunLoop first_failing_run;
647 // Queue the QuitClosure() on the MessageLoop now. Any tasks queued by the
648 // Rename() will be in front of the QuitClosure(). Running the message loop
649 // now causes the just the first retry task to be run. The rename still
650 // fails, so another retry task would get queued behind the QuitClosure().
651 base::MessageLoop::current()->PostTask(FROM_HERE,
652 first_failing_run.QuitClosure());
653 first_failing_run.Run();
654 EXPECT_FALSE(did_run_callback);
655
656 // Running another loop should have the same effect as the above as long as
657 // kMaxRenameRetries is greater than 2.
658 base::RunLoop second_failing_run;
659 base::MessageLoop::current()->PostTask(FROM_HERE,
660 second_failing_run.QuitClosure());
661 second_failing_run.Run();
662 EXPECT_FALSE(did_run_callback);
663 }
664
665 // This time the QuitClosure from succeeding_run should get executed.
666 succeeding_run.Run();
667 EXPECT_TRUE(did_run_callback);
668
669 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
670 loop_.RunUntilIdle();
671 DestroyDownloadFile(0);
672 }
673
674 // Various tests of the StreamActive method. 488 // Various tests of the StreamActive method.
675 TEST_F(DownloadFileTest, StreamEmptySuccess) { 489 TEST_F(DownloadFileTest, StreamEmptySuccess) {
676 ASSERT_TRUE(CreateDownloadFile(0, true)); 490 ASSERT_TRUE(CreateDownloadFile(0, true));
677 base::FilePath initial_path(download_file_->FullPath()); 491 base::FilePath initial_path(download_file_->FullPath());
678 EXPECT_TRUE(base::PathExists(initial_path)); 492 EXPECT_TRUE(base::PathExists(initial_path));
679 493
680 // Test that calling the sink_callback_ on an empty stream shouldn't 494 // Test that calling the sink_callback_ on an empty stream shouldn't
681 // do anything. 495 // do anything.
682 AppendDataToFile(NULL, 0); 496 AppendDataToFile(NULL, 0);
683 497
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 594
781 EXPECT_EQ(static_cast<int64>(strlen(kTestData1) + strlen(kTestData2)), 595 EXPECT_EQ(static_cast<int64>(strlen(kTestData1) + strlen(kTestData2)),
782 bytes_); 596 bytes_);
783 EXPECT_EQ(download_file_->GetHashState(), hash_state_); 597 EXPECT_EQ(download_file_->GetHashState(), hash_state_);
784 598
785 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); 599 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
786 DestroyDownloadFile(0); 600 DestroyDownloadFile(0);
787 } 601 }
788 602
789 } // namespace content 603 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698