• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • 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:
BaseFileTest()22   BaseFileTest()
23       : expect_file_survives_(false),
24         file_thread_(BrowserThread::FILE, &message_loop_) {
25   }
26 
SetUp()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 
TearDown()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 
AppendDataToFile(const std::string & data)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.
TEST_F(BaseFileTest,CreateDestroy)86 TEST_F(BaseFileTest, CreateDestroy) {
87   EXPECT_EQ(FilePath().value(), base_file_->full_path().value());
88 }
89 
90 // Cancel the download explicitly.
TEST_F(BaseFileTest,Cancel)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.
TEST_F(BaseFileTest,WriteAndDetach)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.
TEST_F(BaseFileTest,WriteWithHashAndDetach)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.
TEST_F(BaseFileTest,WriteThenRenameAndDetach)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.
TEST_F(BaseFileTest,SingleWrite)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.
TEST_F(BaseFileTest,MultipleWrites)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.
TEST_F(BaseFileTest,SingleWriteWithHash)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.
TEST_F(BaseFileTest,MultipleWritesWithHash)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.
TEST_F(BaseFileTest,WriteThenRename)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.
TEST_F(BaseFileTest,RenameWhileInProgress)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