Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / download / base_file_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/download/base_file.h"
6
7 #include "base/files/file.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/test_file_util.h"
14 #include "content/browser/browser_thread_impl.h"
15 #include "content/public/browser/download_interrupt_reasons.h"
16 #include "crypto/secure_hash.h"
17 #include "crypto/sha2.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace content {
21 namespace {
22
23 const char kTestData1[] = "Let's write some data to the file!\n";
24 const char kTestData2[] = "Writing more data.\n";
25 const char kTestData3[] = "Final line.";
26 const char kTestData4[] = "supercalifragilisticexpialidocious";
27 const int kTestDataLength1 = arraysize(kTestData1) - 1;
28 const int kTestDataLength2 = arraysize(kTestData2) - 1;
29 const int kTestDataLength3 = arraysize(kTestData3) - 1;
30 const int kTestDataLength4 = arraysize(kTestData4) - 1;
31 const int kElapsedTimeSeconds = 5;
32 const base::TimeDelta kElapsedTimeDelta = base::TimeDelta::FromSeconds(
33     kElapsedTimeSeconds);
34
35 }  // namespace
36
37 class BaseFileTest : public testing::Test {
38  public:
39   static const unsigned char kEmptySha256Hash[crypto::kSHA256Length];
40
41   BaseFileTest()
42       : expect_file_survives_(false),
43         expect_in_progress_(true),
44         expected_error_(DOWNLOAD_INTERRUPT_REASON_NONE),
45         file_thread_(BrowserThread::FILE, &message_loop_) {
46   }
47
48   void SetUp() override {
49     ResetHash();
50     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
51     base_file_.reset(new BaseFile(base::FilePath(),
52                                   GURL(),
53                                   GURL(),
54                                   0,
55                                   false,
56                                   std::string(),
57                                   base::File(),
58                                   net::BoundNetLog()));
59   }
60
61   void TearDown() override {
62     EXPECT_FALSE(base_file_->in_progress());
63     if (!expected_error_) {
64       EXPECT_EQ(static_cast<int64>(expected_data_.size()),
65                 base_file_->bytes_so_far());
66     }
67
68     base::FilePath full_path = base_file_->full_path();
69
70     if (!expected_data_.empty() && !expected_error_) {
71       // Make sure the data has been properly written to disk.
72       std::string disk_data;
73       EXPECT_TRUE(base::ReadFileToString(full_path, &disk_data));
74       EXPECT_EQ(expected_data_, disk_data);
75     }
76
77     // Make sure the mock BrowserThread outlives the BaseFile to satisfy
78     // thread checks inside it.
79     base_file_.reset();
80
81     EXPECT_EQ(expect_file_survives_, base::PathExists(full_path));
82   }
83
84   void ResetHash() {
85     secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
86     memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length);
87   }
88
89   void UpdateHash(const char* data, size_t length) {
90     secure_hash_->Update(data, length);
91   }
92
93   std::string GetFinalHash() {
94     std::string hash;
95     secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length);
96     hash.assign(reinterpret_cast<const char*>(sha256_hash_),
97                 sizeof(sha256_hash_));
98     return hash;
99   }
100
101   void MakeFileWithHash() {
102     base_file_.reset(new BaseFile(base::FilePath(),
103                                   GURL(),
104                                   GURL(),
105                                   0,
106                                   true,
107                                   std::string(),
108                                   base::File(),
109                                   net::BoundNetLog()));
110   }
111
112   bool InitializeFile() {
113     DownloadInterruptReason result = base_file_->Initialize(temp_dir_.path());
114     EXPECT_EQ(expected_error_, result);
115     return result == DOWNLOAD_INTERRUPT_REASON_NONE;
116   }
117
118   bool AppendDataToFile(const std::string& data) {
119     EXPECT_EQ(expect_in_progress_, base_file_->in_progress());
120     DownloadInterruptReason result =
121         base_file_->AppendDataToFile(data.data(), data.size());
122     if (result == DOWNLOAD_INTERRUPT_REASON_NONE)
123       EXPECT_TRUE(expect_in_progress_) << " result = " << result;
124
125     EXPECT_EQ(expected_error_, result);
126     if (base_file_->in_progress()) {
127       expected_data_ += data;
128       if (expected_error_ == DOWNLOAD_INTERRUPT_REASON_NONE) {
129         EXPECT_EQ(static_cast<int64>(expected_data_.size()),
130                   base_file_->bytes_so_far());
131       }
132     }
133     return result == DOWNLOAD_INTERRUPT_REASON_NONE;
134   }
135
136   void set_expected_data(const std::string& data) { expected_data_ = data; }
137
138   // Helper functions.
139   // Create a file.  Returns the complete file path.
140   base::FilePath CreateTestFile() {
141     base::FilePath file_name;
142     BaseFile file(base::FilePath(),
143                   GURL(),
144                   GURL(),
145                   0,
146                   false,
147                   std::string(),
148                   base::File(),
149                   net::BoundNetLog());
150
151     EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
152               file.Initialize(temp_dir_.path()));
153     file_name = file.full_path();
154     EXPECT_NE(base::FilePath::StringType(), file_name.value());
155
156     EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
157               file.AppendDataToFile(kTestData4, kTestDataLength4));
158
159     // Keep the file from getting deleted when existing_file_name is deleted.
160     file.Detach();
161
162     return file_name;
163   }
164
165   // Create a file with the specified file name.
166   void CreateFileWithName(const base::FilePath& file_name) {
167     EXPECT_NE(base::FilePath::StringType(), file_name.value());
168     BaseFile duplicate_file(file_name,
169                             GURL(),
170                             GURL(),
171                             0,
172                             false,
173                             std::string(),
174                             base::File(),
175                             net::BoundNetLog());
176     EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
177               duplicate_file.Initialize(temp_dir_.path()));
178     // Write something into it.
179     duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4);
180     // Detach the file so it isn't deleted on destruction of |duplicate_file|.
181     duplicate_file.Detach();
182   }
183
184   int64 CurrentSpeedAtTime(base::TimeTicks current_time) {
185     EXPECT_TRUE(base_file_.get());
186     return base_file_->CurrentSpeedAtTime(current_time);
187   }
188
189   base::TimeTicks StartTick() {
190     EXPECT_TRUE(base_file_.get());
191     return base_file_->start_tick_;
192   }
193
194   void set_expected_error(DownloadInterruptReason err) {
195     expected_error_ = err;
196   }
197
198   void ExpectPermissionError(DownloadInterruptReason err) {
199     EXPECT_TRUE(err == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR ||
200                 err == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED)
201         << "Interrupt reason = " << err;
202   }
203
204  protected:
205   // BaseClass instance we are testing.
206   scoped_ptr<BaseFile> base_file_;
207
208   // Temporary directory for renamed downloads.
209   base::ScopedTempDir temp_dir_;
210
211   // Expect the file to survive deletion of the BaseFile instance.
212   bool expect_file_survives_;
213
214   // Expect the file to be in progress.
215   bool expect_in_progress_;
216
217   // Hash calculator.
218   scoped_ptr<crypto::SecureHash> secure_hash_;
219
220   unsigned char sha256_hash_[crypto::kSHA256Length];
221
222  private:
223   // Keep track of what data should be saved to the disk file.
224   std::string expected_data_;
225   DownloadInterruptReason expected_error_;
226
227   // Mock file thread to satisfy debug checks in BaseFile.
228   base::MessageLoop message_loop_;
229   BrowserThreadImpl file_thread_;
230 };
231
232 // This will initialize the entire array to zero.
233 const unsigned char BaseFileTest::kEmptySha256Hash[] = { 0 };
234
235 // Test the most basic scenario: just create the object and do a sanity check
236 // on all its accessors. This is actually a case that rarely happens
237 // in production, where we would at least Initialize it.
238 TEST_F(BaseFileTest, CreateDestroy) {
239   EXPECT_EQ(base::FilePath().value(), base_file_->full_path().value());
240 }
241
242 // Cancel the download explicitly.
243 TEST_F(BaseFileTest, Cancel) {
244   ASSERT_TRUE(InitializeFile());
245   EXPECT_TRUE(base::PathExists(base_file_->full_path()));
246   base_file_->Cancel();
247   EXPECT_FALSE(base::PathExists(base_file_->full_path()));
248   EXPECT_NE(base::FilePath().value(), base_file_->full_path().value());
249 }
250
251 // Write data to the file and detach it, so it doesn't get deleted
252 // automatically when base_file_ is destructed.
253 TEST_F(BaseFileTest, WriteAndDetach) {
254   ASSERT_TRUE(InitializeFile());
255   ASSERT_TRUE(AppendDataToFile(kTestData1));
256   base_file_->Finish();
257   base_file_->Detach();
258   expect_file_survives_ = true;
259 }
260
261 // Write data to the file and detach it, and calculate its sha256 hash.
262 TEST_F(BaseFileTest, WriteWithHashAndDetach) {
263   // Calculate the final hash.
264   ResetHash();
265   UpdateHash(kTestData1, kTestDataLength1);
266   std::string expected_hash = GetFinalHash();
267   std::string expected_hash_hex =
268       base::HexEncode(expected_hash.data(), expected_hash.size());
269
270   MakeFileWithHash();
271   ASSERT_TRUE(InitializeFile());
272   ASSERT_TRUE(AppendDataToFile(kTestData1));
273   base_file_->Finish();
274
275   std::string hash;
276   base_file_->GetHash(&hash);
277   EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
278             expected_hash_hex);
279   EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
280
281   base_file_->Detach();
282   expect_file_survives_ = true;
283 }
284
285 // Rename the file after writing to it, then detach.
286 TEST_F(BaseFileTest, WriteThenRenameAndDetach) {
287   ASSERT_TRUE(InitializeFile());
288
289   base::FilePath initial_path(base_file_->full_path());
290   EXPECT_TRUE(base::PathExists(initial_path));
291   base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
292   EXPECT_FALSE(base::PathExists(new_path));
293
294   ASSERT_TRUE(AppendDataToFile(kTestData1));
295
296   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
297   EXPECT_FALSE(base::PathExists(initial_path));
298   EXPECT_TRUE(base::PathExists(new_path));
299
300   base_file_->Finish();
301   base_file_->Detach();
302   expect_file_survives_ = true;
303 }
304
305 // Write data to the file once.
306 TEST_F(BaseFileTest, SingleWrite) {
307   ASSERT_TRUE(InitializeFile());
308   ASSERT_TRUE(AppendDataToFile(kTestData1));
309   base_file_->Finish();
310 }
311
312 // Write data to the file multiple times.
313 TEST_F(BaseFileTest, MultipleWrites) {
314   ASSERT_TRUE(InitializeFile());
315   ASSERT_TRUE(AppendDataToFile(kTestData1));
316   ASSERT_TRUE(AppendDataToFile(kTestData2));
317   ASSERT_TRUE(AppendDataToFile(kTestData3));
318   std::string hash;
319   EXPECT_FALSE(base_file_->GetHash(&hash));
320   base_file_->Finish();
321 }
322
323 // Write data to the file once and calculate its sha256 hash.
324 TEST_F(BaseFileTest, SingleWriteWithHash) {
325   // Calculate the final hash.
326   ResetHash();
327   UpdateHash(kTestData1, kTestDataLength1);
328   std::string expected_hash = GetFinalHash();
329   std::string expected_hash_hex =
330       base::HexEncode(expected_hash.data(), expected_hash.size());
331
332   MakeFileWithHash();
333   ASSERT_TRUE(InitializeFile());
334   // Can get partial hash states before Finish() is called.
335   EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
336   ASSERT_TRUE(AppendDataToFile(kTestData1));
337   EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
338   base_file_->Finish();
339
340   std::string hash;
341   base_file_->GetHash(&hash);
342   EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
343 }
344
345 // Write data to the file multiple times and calculate its sha256 hash.
346 TEST_F(BaseFileTest, MultipleWritesWithHash) {
347   // Calculate the final hash.
348   ResetHash();
349   UpdateHash(kTestData1, kTestDataLength1);
350   UpdateHash(kTestData2, kTestDataLength2);
351   UpdateHash(kTestData3, kTestDataLength3);
352   std::string expected_hash = GetFinalHash();
353   std::string expected_hash_hex =
354       base::HexEncode(expected_hash.data(), expected_hash.size());
355
356   std::string hash;
357   MakeFileWithHash();
358   ASSERT_TRUE(InitializeFile());
359   ASSERT_TRUE(AppendDataToFile(kTestData1));
360   ASSERT_TRUE(AppendDataToFile(kTestData2));
361   ASSERT_TRUE(AppendDataToFile(kTestData3));
362   // No hash before Finish() is called.
363   EXPECT_FALSE(base_file_->GetHash(&hash));
364   base_file_->Finish();
365
366   EXPECT_TRUE(base_file_->GetHash(&hash));
367   EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
368             expected_hash_hex);
369   EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
370 }
371
372 // Write data to the file multiple times, interrupt it, and continue using
373 // another file.  Calculate the resulting combined sha256 hash.
374 TEST_F(BaseFileTest, MultipleWritesInterruptedWithHash) {
375   // Calculate the final hash.
376   ResetHash();
377   UpdateHash(kTestData1, kTestDataLength1);
378   UpdateHash(kTestData2, kTestDataLength2);
379   UpdateHash(kTestData3, kTestDataLength3);
380   std::string expected_hash = GetFinalHash();
381   std::string expected_hash_hex =
382       base::HexEncode(expected_hash.data(), expected_hash.size());
383
384   MakeFileWithHash();
385   ASSERT_TRUE(InitializeFile());
386   // Write some data
387   ASSERT_TRUE(AppendDataToFile(kTestData1));
388   ASSERT_TRUE(AppendDataToFile(kTestData2));
389   // Get the hash state and file name.
390   std::string hash_state;
391   hash_state = base_file_->GetHashState();
392   // Finish the file.
393   base_file_->Finish();
394
395   base::FilePath new_file_path(temp_dir_.path().Append(
396       base::FilePath(FILE_PATH_LITERAL("second_file"))));
397
398   ASSERT_TRUE(base::CopyFile(base_file_->full_path(), new_file_path));
399
400   // Create another file
401   BaseFile second_file(new_file_path,
402                        GURL(),
403                        GURL(),
404                        base_file_->bytes_so_far(),
405                        true,
406                        hash_state,
407                        base::File(),
408                        net::BoundNetLog());
409   ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
410             second_file.Initialize(base::FilePath()));
411   std::string data(kTestData3);
412   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
413             second_file.AppendDataToFile(data.data(), data.size()));
414   second_file.Finish();
415
416   std::string hash;
417   EXPECT_TRUE(second_file.GetHash(&hash));
418   // This will fail until getting the hash state is supported in SecureHash.
419   EXPECT_STREQ(expected_hash_hex.c_str(),
420                base::HexEncode(hash.data(), hash.size()).c_str());
421 }
422
423 // Rename the file after all writes to it.
424 TEST_F(BaseFileTest, WriteThenRename) {
425   ASSERT_TRUE(InitializeFile());
426
427   base::FilePath initial_path(base_file_->full_path());
428   EXPECT_TRUE(base::PathExists(initial_path));
429   base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
430   EXPECT_FALSE(base::PathExists(new_path));
431
432   ASSERT_TRUE(AppendDataToFile(kTestData1));
433
434   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
435             base_file_->Rename(new_path));
436   EXPECT_FALSE(base::PathExists(initial_path));
437   EXPECT_TRUE(base::PathExists(new_path));
438
439   base_file_->Finish();
440 }
441
442 // Rename the file while the download is still in progress.
443 TEST_F(BaseFileTest, RenameWhileInProgress) {
444   ASSERT_TRUE(InitializeFile());
445
446   base::FilePath initial_path(base_file_->full_path());
447   EXPECT_TRUE(base::PathExists(initial_path));
448   base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
449   EXPECT_FALSE(base::PathExists(new_path));
450
451   ASSERT_TRUE(AppendDataToFile(kTestData1));
452
453   EXPECT_TRUE(base_file_->in_progress());
454   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
455   EXPECT_FALSE(base::PathExists(initial_path));
456   EXPECT_TRUE(base::PathExists(new_path));
457
458   ASSERT_TRUE(AppendDataToFile(kTestData2));
459
460   base_file_->Finish();
461 }
462
463 // Test that a failed rename reports the correct error.
464 TEST_F(BaseFileTest, RenameWithError) {
465   ASSERT_TRUE(InitializeFile());
466
467   // TestDir is a subdirectory in |temp_dir_| that we will make read-only so
468   // that the rename will fail.
469   base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir"));
470   ASSERT_TRUE(base::CreateDirectory(test_dir));
471
472   base::FilePath new_path(test_dir.AppendASCII("TestFile"));
473   EXPECT_FALSE(base::PathExists(new_path));
474
475   {
476     base::FilePermissionRestorer restore_permissions_for(test_dir);
477     ASSERT_TRUE(base::MakeFileUnwritable(test_dir));
478     ExpectPermissionError(base_file_->Rename(new_path));
479   }
480
481   base_file_->Finish();
482 }
483
484 // Test that if a rename fails for an in-progress BaseFile, it remains writeable
485 // and renameable.
486 TEST_F(BaseFileTest, RenameWithErrorInProgress) {
487   ASSERT_TRUE(InitializeFile());
488
489   base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir"));
490   ASSERT_TRUE(base::CreateDirectory(test_dir));
491
492   base::FilePath new_path(test_dir.AppendASCII("TestFile"));
493   EXPECT_FALSE(base::PathExists(new_path));
494
495   // Write some data to start with.
496   ASSERT_TRUE(AppendDataToFile(kTestData1));
497   ASSERT_TRUE(base_file_->in_progress());
498
499   base::FilePath old_path = base_file_->full_path();
500
501   {
502     base::FilePermissionRestorer restore_permissions_for(test_dir);
503     ASSERT_TRUE(base::MakeFileUnwritable(test_dir));
504     ExpectPermissionError(base_file_->Rename(new_path));
505
506     // The file should still be open and we should be able to continue writing
507     // to it.
508     ASSERT_TRUE(base_file_->in_progress());
509     ASSERT_TRUE(AppendDataToFile(kTestData2));
510     ASSERT_EQ(old_path.value(), base_file_->full_path().value());
511
512     // Try to rename again, just for kicks. It should still fail.
513     ExpectPermissionError(base_file_->Rename(new_path));
514   }
515
516   // Now that TestDir is writeable again, we should be able to successfully
517   // rename the file.
518   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
519   ASSERT_EQ(new_path.value(), base_file_->full_path().value());
520   ASSERT_TRUE(AppendDataToFile(kTestData3));
521
522   base_file_->Finish();
523
524   // The contents of the file should be intact.
525   std::string file_contents;
526   std::string expected_contents(kTestData1);
527   expected_contents += kTestData2;
528   expected_contents += kTestData3;
529   ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
530   EXPECT_EQ(expected_contents, file_contents);
531 }
532
533 // Test that a failed write reports an error.
534 TEST_F(BaseFileTest, WriteWithError) {
535   base::FilePath path;
536   ASSERT_TRUE(base::CreateTemporaryFile(&path));
537
538   // Pass a file handle which was opened without the WRITE flag.
539   // This should result in an error when writing.
540   base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
541   base_file_.reset(new BaseFile(path,
542                                 GURL(),
543                                 GURL(),
544                                 0,
545                                 false,
546                                 std::string(),
547                                 file.Pass(),
548                                 net::BoundNetLog()));
549   ASSERT_TRUE(InitializeFile());
550 #if defined(OS_WIN)
551   set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
552 #elif defined (OS_POSIX)
553   set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
554 #endif
555   ASSERT_FALSE(AppendDataToFile(kTestData1));
556   base_file_->Finish();
557 }
558
559 // Try to write to uninitialized file.
560 TEST_F(BaseFileTest, UninitializedFile) {
561   expect_in_progress_ = false;
562   set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
563   EXPECT_FALSE(AppendDataToFile(kTestData1));
564 }
565
566 // Create two |BaseFile|s with the same file, and attempt to write to both.
567 // Overwrite base_file_ with another file with the same name and
568 // non-zero contents, and make sure the last file to close 'wins'.
569 TEST_F(BaseFileTest, DuplicateBaseFile) {
570   ASSERT_TRUE(InitializeFile());
571
572   // Create another |BaseFile| referring to the file that |base_file_| owns.
573   CreateFileWithName(base_file_->full_path());
574
575   ASSERT_TRUE(AppendDataToFile(kTestData1));
576   base_file_->Finish();
577 }
578
579 // Create a file and append to it.
580 TEST_F(BaseFileTest, AppendToBaseFile) {
581   // Create a new file.
582   base::FilePath existing_file_name = CreateTestFile();
583
584   set_expected_data(kTestData4);
585
586   // Use the file we've just created.
587   base_file_.reset(new BaseFile(existing_file_name,
588                                 GURL(),
589                                 GURL(),
590                                 kTestDataLength4,
591                                 false,
592                                 std::string(),
593                                 base::File(),
594                                 net::BoundNetLog()));
595
596   ASSERT_TRUE(InitializeFile());
597
598   const base::FilePath file_name = base_file_->full_path();
599   EXPECT_NE(base::FilePath::StringType(), file_name.value());
600
601   // Write into the file.
602   EXPECT_TRUE(AppendDataToFile(kTestData1));
603
604   base_file_->Finish();
605   base_file_->Detach();
606   expect_file_survives_ = true;
607 }
608
609 // Create a read-only file and attempt to write to it.
610 TEST_F(BaseFileTest, ReadonlyBaseFile) {
611   // Create a new file.
612   base::FilePath readonly_file_name = CreateTestFile();
613
614   // Restore permissions to the file when we are done with this test.
615   base::FilePermissionRestorer restore_permissions(readonly_file_name);
616
617   // Make it read-only.
618   EXPECT_TRUE(base::MakeFileUnwritable(readonly_file_name));
619
620   // Try to overwrite it.
621   base_file_.reset(new BaseFile(readonly_file_name,
622                                 GURL(),
623                                 GURL(),
624                                 0,
625                                 false,
626                                 std::string(),
627                                 base::File(),
628                                 net::BoundNetLog()));
629
630   expect_in_progress_ = false;
631   set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
632   EXPECT_FALSE(InitializeFile());
633
634   const base::FilePath file_name = base_file_->full_path();
635   EXPECT_NE(base::FilePath::StringType(), file_name.value());
636
637   // Write into the file.
638   set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
639   EXPECT_FALSE(AppendDataToFile(kTestData1));
640
641   base_file_->Finish();
642   base_file_->Detach();
643   expect_file_survives_ = true;
644 }
645
646 TEST_F(BaseFileTest, IsEmptyHash) {
647   std::string empty(crypto::kSHA256Length, '\x00');
648   EXPECT_TRUE(BaseFile::IsEmptyHash(empty));
649   std::string not_empty(crypto::kSHA256Length, '\x01');
650   EXPECT_FALSE(BaseFile::IsEmptyHash(not_empty));
651   EXPECT_FALSE(BaseFile::IsEmptyHash(std::string()));
652
653   std::string also_not_empty = empty;
654   also_not_empty[crypto::kSHA256Length - 1] = '\x01';
655   EXPECT_FALSE(BaseFile::IsEmptyHash(also_not_empty));
656 }
657
658 // Test that a temporary file is created in the default download directory.
659 TEST_F(BaseFileTest, CreatedInDefaultDirectory) {
660   ASSERT_TRUE(base_file_->full_path().empty());
661   ASSERT_TRUE(InitializeFile());
662   EXPECT_FALSE(base_file_->full_path().empty());
663
664   // On Windows, CreateTemporaryFileInDir() will cause a path with short names
665   // to be expanded into a path with long names. Thus temp_dir.path() might not
666   // be a string-wise match to base_file_->full_path().DirName() even though
667   // they are in the same directory.
668   base::FilePath temp_file;
669   ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
670   ASSERT_FALSE(temp_file.empty());
671   EXPECT_STREQ(temp_file.DirName().value().c_str(),
672                base_file_->full_path().DirName().value().c_str());
673   base_file_->Finish();
674 }
675
676 TEST_F(BaseFileTest, NoDoubleDeleteAfterCancel) {
677   ASSERT_TRUE(InitializeFile());
678   base::FilePath full_path = base_file_->full_path();
679   ASSERT_FALSE(full_path.empty());
680   ASSERT_TRUE(base::PathExists(full_path));
681
682   base_file_->Cancel();
683   ASSERT_FALSE(base::PathExists(full_path));
684
685   const char kData[] = "hello";
686   const int kDataLength = static_cast<int>(arraysize(kData) - 1);
687   ASSERT_EQ(kDataLength, base::WriteFile(full_path, kData, kDataLength));
688   // The file that we created here should stick around when the BaseFile is
689   // destroyed during TearDown.
690   expect_file_survives_ = true;
691 }
692
693 }  // namespace content