Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: content/browser/download/base_file_unittest.cc

Issue 7646025: Detect file system errors during downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed comment. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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; }
wtc 2011/08/23 00:18:35 Nit: it may be better to use net::OK instead of 0
cbentzel 2011/08/23 01:34:01 +1
ahendrickson 2011/08/25 21:55:15 Done.
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 }
wtc 2011/08/23 00:18:35 Nit: add a blank line after this line.
ahendrickson 2011/08/25 21:55:15 Done.
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 }
wtc 2011/08/23 00:18:35 All the net::FileStream virtual methods that you o
ahendrickson 2011/08/25 21:55:15 Done.
58
59 const FilePath& get_path() const { return path_; }
60
61 private:
62 int get_error(int function_error) {
cbentzel 2011/08/23 01:34:01 Perhaps GetError or even ReturnError() since this
ahendrickson 2011/08/25 21:55:15 Done.
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
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.
cbentzel 2011/08/23 01:34:01 What does the "if it is not provided" mean? When
ahendrickson 2011/08/25 21:55:15 Removed.
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 19 matching lines...) Expand all
93 EXPECT_TRUE(file_util::PathExists(base_file_->full_path())); 197 EXPECT_TRUE(file_util::PathExists(base_file_->full_path()));
94 base_file_->Cancel(); 198 base_file_->Cancel();
95 EXPECT_FALSE(file_util::PathExists(base_file_->full_path())); 199 EXPECT_FALSE(file_util::PathExists(base_file_->full_path()));
96 EXPECT_NE(FilePath().value(), base_file_->full_path().value()); 200 EXPECT_NE(FilePath().value(), base_file_->full_path().value());
97 } 201 }
98 202
99 // Write data to the file and detach it, so it doesn't get deleted 203 // Write data to the file and detach it, so it doesn't get deleted
100 // automatically when base_file_ is destructed. 204 // automatically when base_file_ is destructed.
101 TEST_F(BaseFileTest, WriteAndDetach) { 205 TEST_F(BaseFileTest, WriteAndDetach) {
102 ASSERT_TRUE(base_file_->Initialize(false)); 206 ASSERT_TRUE(base_file_->Initialize(false));
103 AppendDataToFile(kTestData1); 207 AppendDataToFile(kTestData1);
cbentzel 2011/08/23 01:34:01 All calls to AppendDataToFile should be wrapped in
ahendrickson 2011/08/25 21:55:15 Done.
104 base_file_->Finish(); 208 base_file_->Finish();
105 base_file_->Detach(); 209 base_file_->Detach();
106 expect_file_survives_ = true; 210 expect_file_survives_ = true;
107 } 211 }
108 212
109 // Write data to the file and detach it, and calculate its sha256 hash. 213 // Write data to the file and detach it, and calculate its sha256 hash.
110 TEST_F(BaseFileTest, WriteWithHashAndDetach) { 214 TEST_F(BaseFileTest, WriteWithHashAndDetach) {
111 ASSERT_TRUE(base_file_->Initialize(true)); 215 ASSERT_TRUE(base_file_->Initialize(true));
112 AppendDataToFile(kTestData1); 216 AppendDataToFile(kTestData1);
113 base_file_->Finish(); 217 base_file_->Finish();
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
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);
cbentzel 2011/08/23 01:34:01 Should you use one of the more likely ERR's here?
ahendrickson 2011/08/25 21:55:15 Yes, they will.
343 ASSERT_FALSE(AppendDataToFile(kTestData3));
344 std::string hash;
345 EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
346 base_file_->Finish();
347 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698