Home | History | Annotate | Download | only in download
      1 // Copyright (c) 2011 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 "base/file_util.h"
      6 #include "base/memory/scoped_temp_dir.h"
      7 #include "base/message_loop.h"
      8 #include "base/string_number_conversions.h"
      9 #include "chrome/browser/download/base_file.h"
     10 #include "content/browser/browser_thread.h"
     11 #include "net/base/file_stream.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace {
     15 
     16 const char kTestData1[] = "Let's write some data to the file!\n";
     17 const char kTestData2[] = "Writing more data.\n";
     18 const char kTestData3[] = "Final line.";
     19 
     20 class BaseFileTest : public testing::Test {
     21  public:
     22   BaseFileTest()
     23       : expect_file_survives_(false),
     24         file_thread_(BrowserThread::FILE, &message_loop_) {
     25   }
     26 
     27   virtual void SetUp() {
     28     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     29     base_file_.reset(
     30         new BaseFile(FilePath(), GURL(), GURL(), 0, file_stream_));
     31   }
     32 
     33   virtual void TearDown() {
     34     EXPECT_FALSE(base_file_->in_progress());
     35     EXPECT_EQ(static_cast<int64>(expected_data_.size()),
     36               base_file_->bytes_so_far());
     37 
     38     FilePath full_path = base_file_->full_path();
     39 
     40     if (!expected_data_.empty()) {
     41       // Make sure the data has been properly written to disk.
     42       std::string disk_data;
     43       EXPECT_TRUE(file_util::ReadFileToString(full_path, &disk_data));
     44       EXPECT_EQ(expected_data_, disk_data);
     45     }
     46 
     47     // Make sure the mock BrowserThread outlives the BaseFile to satisfy
     48     // thread checks inside it.
     49     base_file_.reset();
     50 
     51     EXPECT_EQ(expect_file_survives_, file_util::PathExists(full_path));
     52   }
     53 
     54   void AppendDataToFile(const std::string& data) {
     55     ASSERT_TRUE(base_file_->in_progress());
     56     base_file_->AppendDataToFile(data.data(), data.size());
     57     expected_data_ += data;
     58     EXPECT_EQ(static_cast<int64>(expected_data_.size()),
     59               base_file_->bytes_so_far());
     60   }
     61 
     62  protected:
     63   linked_ptr<net::FileStream> file_stream_;
     64 
     65   // BaseClass instance we are testing.
     66   scoped_ptr<BaseFile> base_file_;
     67 
     68   // Temporary directory for renamed downloads.
     69   ScopedTempDir temp_dir_;
     70 
     71   // Expect the file to survive deletion of the BaseFile instance.
     72   bool expect_file_survives_;
     73 
     74  private:
     75   // Keep track of what data should be saved to the disk file.
     76   std::string expected_data_;
     77 
     78   // Mock file thread to satisfy debug checks in BaseFile.
     79   MessageLoop message_loop_;
     80   BrowserThread file_thread_;
     81 };
     82 
     83 // Test the most basic scenario: just create the object and do a sanity check
     84 // on all its accessors. This is actually a case that rarely happens
     85 // in production, where we would at least Initialize it.
     86 TEST_F(BaseFileTest, CreateDestroy) {
     87   EXPECT_EQ(FilePath().value(), base_file_->full_path().value());
     88 }
     89 
     90 // Cancel the download explicitly.
     91 TEST_F(BaseFileTest, Cancel) {
     92   ASSERT_TRUE(base_file_->Initialize(false));
     93   EXPECT_TRUE(file_util::PathExists(base_file_->full_path()));
     94   base_file_->Cancel();
     95   EXPECT_FALSE(file_util::PathExists(base_file_->full_path()));
     96   EXPECT_NE(FilePath().value(), base_file_->full_path().value());
     97 }
     98 
     99 // Write data to the file and detach it, so it doesn't get deleted
    100 // automatically when base_file_ is destructed.
    101 TEST_F(BaseFileTest, WriteAndDetach) {
    102   ASSERT_TRUE(base_file_->Initialize(false));
    103   AppendDataToFile(kTestData1);
    104   base_file_->Finish();
    105   base_file_->Detach();
    106   expect_file_survives_ = true;
    107 }
    108 
    109 // Write data to the file and detach it, and calculate its sha256 hash.
    110 TEST_F(BaseFileTest, WriteWithHashAndDetach) {
    111   ASSERT_TRUE(base_file_->Initialize(true));
    112   AppendDataToFile(kTestData1);
    113   base_file_->Finish();
    114 
    115   std::string hash;
    116   base_file_->GetSha256Hash(&hash);
    117   EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
    118             base::HexEncode(hash.data(), hash.size()));
    119 
    120   base_file_->Detach();
    121   expect_file_survives_ = true;
    122 }
    123 
    124 // Rename the file after writing to it, then detach.
    125 TEST_F(BaseFileTest, WriteThenRenameAndDetach) {
    126   ASSERT_TRUE(base_file_->Initialize(false));
    127 
    128   FilePath initial_path(base_file_->full_path());
    129   EXPECT_TRUE(file_util::PathExists(initial_path));
    130   FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
    131   EXPECT_FALSE(file_util::PathExists(new_path));
    132 
    133   AppendDataToFile(kTestData1);
    134 
    135   EXPECT_TRUE(base_file_->Rename(new_path));
    136   EXPECT_FALSE(file_util::PathExists(initial_path));
    137   EXPECT_TRUE(file_util::PathExists(new_path));
    138 
    139   base_file_->Finish();
    140   base_file_->Detach();
    141   expect_file_survives_ = true;
    142 }
    143 
    144 // Write data to the file once.
    145 TEST_F(BaseFileTest, SingleWrite) {
    146   ASSERT_TRUE(base_file_->Initialize(false));
    147   AppendDataToFile(kTestData1);
    148   base_file_->Finish();
    149 }
    150 
    151 // Write data to the file multiple times.
    152 TEST_F(BaseFileTest, MultipleWrites) {
    153   ASSERT_TRUE(base_file_->Initialize(false));
    154   AppendDataToFile(kTestData1);
    155   AppendDataToFile(kTestData2);
    156   AppendDataToFile(kTestData3);
    157   std::string hash;
    158   EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
    159   base_file_->Finish();
    160 }
    161 
    162 // Write data to the file once and calculate its sha256 hash.
    163 TEST_F(BaseFileTest, SingleWriteWithHash) {
    164   ASSERT_TRUE(base_file_->Initialize(true));
    165   AppendDataToFile(kTestData1);
    166   base_file_->Finish();
    167 
    168   std::string hash;
    169   base_file_->GetSha256Hash(&hash);
    170   EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
    171             base::HexEncode(hash.data(), hash.size()));
    172 }
    173 
    174 // Write data to the file multiple times and calculate its sha256 hash.
    175 TEST_F(BaseFileTest, MultipleWritesWithHash) {
    176   std::string hash;
    177 
    178   ASSERT_TRUE(base_file_->Initialize(true));
    179   AppendDataToFile(kTestData1);
    180   AppendDataToFile(kTestData2);
    181   AppendDataToFile(kTestData3);
    182   // no hash before Finish() is called either.
    183   EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
    184   base_file_->Finish();
    185 
    186   EXPECT_TRUE(base_file_->GetSha256Hash(&hash));
    187   EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
    188             base::HexEncode(hash.data(), hash.size()));
    189 }
    190 
    191 // Rename the file after all writes to it.
    192 TEST_F(BaseFileTest, WriteThenRename) {
    193   ASSERT_TRUE(base_file_->Initialize(false));
    194 
    195   FilePath initial_path(base_file_->full_path());
    196   EXPECT_TRUE(file_util::PathExists(initial_path));
    197   FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
    198   EXPECT_FALSE(file_util::PathExists(new_path));
    199 
    200   AppendDataToFile(kTestData1);
    201 
    202   EXPECT_TRUE(base_file_->Rename(new_path));
    203   EXPECT_FALSE(file_util::PathExists(initial_path));
    204   EXPECT_TRUE(file_util::PathExists(new_path));
    205 
    206   base_file_->Finish();
    207 }
    208 
    209 // Rename the file while the download is still in progress.
    210 TEST_F(BaseFileTest, RenameWhileInProgress) {
    211   ASSERT_TRUE(base_file_->Initialize(false));
    212 
    213   FilePath initial_path(base_file_->full_path());
    214   EXPECT_TRUE(file_util::PathExists(initial_path));
    215   FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
    216   EXPECT_FALSE(file_util::PathExists(new_path));
    217 
    218   AppendDataToFile(kTestData1);
    219 
    220   EXPECT_TRUE(base_file_->in_progress());
    221   EXPECT_TRUE(base_file_->Rename(new_path));
    222   EXPECT_FALSE(file_util::PathExists(initial_path));
    223   EXPECT_TRUE(file_util::PathExists(new_path));
    224 
    225   AppendDataToFile(kTestData2);
    226 
    227   base_file_->Finish();
    228 }
    229 
    230 }  // namespace
    231