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