OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/message_loop.h" | 6 #include "base/message_loop.h" |
7 #include "base/scoped_temp_dir.h" | 7 #include "base/scoped_temp_dir.h" |
8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
| 9 #include "chrome/browser/download/download_util.h" |
9 #include "content/browser/browser_thread.h" | 10 #include "content/browser/browser_thread.h" |
10 #include "content/browser/download/base_file.h" | 11 #include "content/browser/download/base_file.h" |
11 #include "net/base/file_stream.h" | 12 #include "net/base/file_stream.h" |
| 13 #include "net/base/net_errors.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
13 | 15 |
14 namespace { | 16 namespace { |
15 | 17 |
| 18 class MockFileStream : public net::FileStream { |
| 19 public: |
| 20 MockFileStream() : forced_error_(0) {} |
| 21 MockFileStream(base::PlatformFile file, int flags) |
| 22 : net::FileStream(file, flags), forced_error_(0) {} |
| 23 |
| 24 void set_forced_error(int error) { forced_error_ = error; } |
| 25 void clear_forced_error() { forced_error_ = 0; } |
| 26 |
| 27 int Open(const FilePath& path, int open_flags) { |
| 28 path_ = path; |
| 29 return get_error(net::FileStream::Open(path, open_flags)); |
| 30 } |
| 31 |
| 32 int64 Seek(net::Whence whence, int64 offset) { |
| 33 return get_error64(net::FileStream::Seek(whence, offset)); |
| 34 } |
| 35 |
| 36 int64 Available() { |
| 37 return get_error64(net::FileStream::Available()); |
| 38 } |
| 39 |
| 40 int Read(char* buf, int buf_len, net::CompletionCallback* callback) { |
| 41 return get_error(net::FileStream::Read(buf, buf_len, callback)); |
| 42 } |
| 43 |
| 44 int ReadUntilComplete(char *buf, int buf_len) { |
| 45 return get_error(net::FileStream::ReadUntilComplete(buf, buf_len)); |
| 46 } |
| 47 |
| 48 int Write(const char* buf, int buf_len, net::CompletionCallback* callback) { |
| 49 return get_error(net::FileStream::Write(buf, buf_len, callback)); |
| 50 } |
| 51 int64 Truncate(int64 bytes) { |
| 52 return get_error64(net::FileStream::Truncate(bytes)); |
| 53 } |
| 54 |
| 55 int Flush() { |
| 56 return get_error(net::FileStream::Flush()); |
| 57 } |
| 58 |
| 59 const FilePath& get_path() const { return path_; } |
| 60 |
| 61 private: |
| 62 int get_error(int function_error) { |
| 63 if (forced_error_ != 0) { |
| 64 int ret = forced_error_; |
| 65 clear_forced_error(); |
| 66 return ret; |
| 67 } |
| 68 |
| 69 return function_error; |
| 70 } |
| 71 |
| 72 int64 get_error64(int64 function_error) { |
| 73 if (forced_error_ != 0) { |
| 74 int64 ret = forced_error_; |
| 75 clear_forced_error(); |
| 76 return ret; |
| 77 } |
| 78 |
| 79 return function_error; |
| 80 } |
| 81 |
| 82 int forced_error_; |
| 83 FilePath path_; |
| 84 }; |
| 85 |
16 const char kTestData1[] = "Let's write some data to the file!\n"; | 86 const char kTestData1[] = "Let's write some data to the file!\n"; |
17 const char kTestData2[] = "Writing more data.\n"; | 87 const char kTestData2[] = "Writing more data.\n"; |
18 const char kTestData3[] = "Final line."; | 88 const char kTestData3[] = "Final line."; |
19 | 89 |
| 90 } // namespace |
| 91 |
20 class BaseFileTest : public testing::Test { | 92 class BaseFileTest : public testing::Test { |
21 public: | 93 public: |
22 BaseFileTest() | 94 BaseFileTest() |
23 : expect_file_survives_(false), | 95 : expect_file_survives_(false), |
24 file_thread_(BrowserThread::FILE, &message_loop_) { | 96 file_thread_(BrowserThread::FILE, &message_loop_) { |
25 } | 97 } |
26 | 98 |
27 virtual void SetUp() { | 99 virtual void SetUp() { |
28 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 100 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
29 base_file_.reset( | 101 base_file_.reset( |
(...skipping 14 matching lines...) Expand all Loading... |
44 EXPECT_EQ(expected_data_, disk_data); | 116 EXPECT_EQ(expected_data_, disk_data); |
45 } | 117 } |
46 | 118 |
47 // Make sure the mock BrowserThread outlives the BaseFile to satisfy | 119 // Make sure the mock BrowserThread outlives the BaseFile to satisfy |
48 // thread checks inside it. | 120 // thread checks inside it. |
49 base_file_.reset(); | 121 base_file_.reset(); |
50 | 122 |
51 EXPECT_EQ(expect_file_survives_, file_util::PathExists(full_path)); | 123 EXPECT_EQ(expect_file_survives_, file_util::PathExists(full_path)); |
52 } | 124 } |
53 | 125 |
54 void AppendDataToFile(const std::string& data) { | 126 bool OpenMockFileStream() { |
55 ASSERT_TRUE(base_file_->in_progress()); | 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
56 base_file_->AppendDataToFile(data.data(), data.size()); | 128 |
| 129 FilePath path; |
| 130 if (!download_util::CreateTemporaryFileForDownload(&path)) |
| 131 return false; |
| 132 |
| 133 // Create a new file stream if it is not provided. |
| 134 mock_file_stream_.reset(new MockFileStream); |
| 135 if (mock_file_stream_->Open( |
| 136 path, |
| 137 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE) != 0) { |
| 138 mock_file_stream_.reset(); |
| 139 return false; |
| 140 } |
| 141 |
| 142 // We may be re-opening the file after rename. Always make sure we're |
| 143 // writing at the end of the file. |
| 144 if (mock_file_stream_->Seek(net::FROM_END, 0) < 0) { |
| 145 mock_file_stream_.reset(); |
| 146 return false; |
| 147 } |
| 148 |
| 149 return true; |
| 150 } |
| 151 |
| 152 void ForceError(net::Error error) { |
| 153 mock_file_stream_->set_forced_error(error); |
| 154 } |
| 155 |
| 156 bool AppendDataToFile(const std::string& data) { |
| 157 EXPECT_TRUE(base_file_->in_progress()); |
| 158 bool appended = base_file_->AppendDataToFile(data.data(), data.size()); |
57 expected_data_ += data; | 159 expected_data_ += data; |
58 EXPECT_EQ(static_cast<int64>(expected_data_.size()), | 160 EXPECT_EQ(static_cast<int64>(expected_data_.size()), |
59 base_file_->bytes_so_far()); | 161 base_file_->bytes_so_far()); |
| 162 return appended; |
60 } | 163 } |
61 | 164 |
62 protected: | 165 protected: |
63 linked_ptr<net::FileStream> file_stream_; | 166 linked_ptr<net::FileStream> file_stream_; |
| 167 linked_ptr<MockFileStream> mock_file_stream_; |
64 | 168 |
65 // BaseClass instance we are testing. | 169 // BaseClass instance we are testing. |
66 scoped_ptr<BaseFile> base_file_; | 170 scoped_ptr<BaseFile> base_file_; |
67 | 171 |
68 // Temporary directory for renamed downloads. | 172 // Temporary directory for renamed downloads. |
69 ScopedTempDir temp_dir_; | 173 ScopedTempDir temp_dir_; |
70 | 174 |
71 // Expect the file to survive deletion of the BaseFile instance. | 175 // Expect the file to survive deletion of the BaseFile instance. |
72 bool expect_file_survives_; | 176 bool expect_file_survives_; |
73 | 177 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 EXPECT_TRUE(base_file_->in_progress()); | 324 EXPECT_TRUE(base_file_->in_progress()); |
221 EXPECT_TRUE(base_file_->Rename(new_path)); | 325 EXPECT_TRUE(base_file_->Rename(new_path)); |
222 EXPECT_FALSE(file_util::PathExists(initial_path)); | 326 EXPECT_FALSE(file_util::PathExists(initial_path)); |
223 EXPECT_TRUE(file_util::PathExists(new_path)); | 327 EXPECT_TRUE(file_util::PathExists(new_path)); |
224 | 328 |
225 AppendDataToFile(kTestData2); | 329 AppendDataToFile(kTestData2); |
226 | 330 |
227 base_file_->Finish(); | 331 base_file_->Finish(); |
228 } | 332 } |
229 | 333 |
230 } // namespace | 334 // Write data to the file multiple times. |
| 335 TEST_F(BaseFileTest, MultipleWritesWithError) { |
| 336 ASSERT_TRUE(OpenMockFileStream()); |
| 337 base_file_.reset(new BaseFile(mock_file_stream_->get_path(), |
| 338 GURL(), GURL(), 0, mock_file_stream_)); |
| 339 ASSERT_TRUE(base_file_->Initialize(false)); |
| 340 ASSERT_TRUE(AppendDataToFile(kTestData1)); |
| 341 ASSERT_TRUE(AppendDataToFile(kTestData2)); |
| 342 ForceError(net::ERR_FAILED); |
| 343 ASSERT_FALSE(AppendDataToFile(kTestData3)); |
| 344 std::string hash; |
| 345 EXPECT_FALSE(base_file_->GetSha256Hash(&hash)); |
| 346 base_file_->Finish(); |
| 347 } |
OLD | NEW |