1 // Copyright 2014 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.
5 #include "base/files/file_proxy.h"
10 #include "base/file_util.h"
11 #include "base/files/file.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/logging.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/threading/thread.h"
17 #include "testing/gtest/include/gtest/gtest.h"
21 class FileProxyTest : public testing::Test {
24 : file_thread_("FileProxyTestFileThread"),
25 error_(File::FILE_OK),
27 weak_factory_(this) {}
29 virtual void SetUp() OVERRIDE {
30 ASSERT_TRUE(dir_.CreateUniqueTempDir());
31 ASSERT_TRUE(file_thread_.Start());
34 void DidFinish(File::Error error) {
36 MessageLoop::current()->QuitWhenIdle();
39 void DidCreateOrOpen(File::Error error) {
41 MessageLoop::current()->QuitWhenIdle();
44 void DidCreateTemporary(File::Error error,
45 const FilePath& path) {
48 MessageLoop::current()->QuitWhenIdle();
51 void DidGetFileInfo(File::Error error,
52 const File::Info& file_info) {
54 file_info_ = file_info;
55 MessageLoop::current()->QuitWhenIdle();
58 void DidRead(File::Error error,
62 buffer_.resize(bytes_read);
63 memcpy(&buffer_[0], data, bytes_read);
64 MessageLoop::current()->QuitWhenIdle();
67 void DidWrite(File::Error error,
70 bytes_written_ = bytes_written;
71 MessageLoop::current()->QuitWhenIdle();
75 void CreateProxy(uint32 flags, FileProxy* proxy) {
78 Bind(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
79 MessageLoop::current()->Run();
80 EXPECT_TRUE(proxy->IsValid());
83 TaskRunner* file_task_runner() const {
84 return file_thread_.message_loop_proxy().get();
86 const FilePath& test_dir_path() const { return dir_.path(); }
87 const FilePath test_path() const { return dir_.path().AppendASCII("test"); }
89 MessageLoopForIO message_loop_;
95 File::Info file_info_;
96 std::vector<char> buffer_;
98 WeakPtrFactory<FileProxyTest> weak_factory_;
101 TEST_F(FileProxyTest, CreateOrOpen_Create) {
102 FileProxy proxy(file_task_runner());
105 File::FLAG_CREATE | File::FLAG_READ,
106 Bind(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
107 MessageLoop::current()->Run();
109 EXPECT_EQ(File::FILE_OK, error_);
110 EXPECT_TRUE(proxy.IsValid());
111 EXPECT_TRUE(proxy.created());
112 EXPECT_TRUE(PathExists(test_path()));
115 TEST_F(FileProxyTest, CreateOrOpen_Open) {
117 base::WriteFile(test_path(), NULL, 0);
118 ASSERT_TRUE(PathExists(test_path()));
120 // Opens the created file.
121 FileProxy proxy(file_task_runner());
124 File::FLAG_OPEN | File::FLAG_READ,
125 Bind(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
126 MessageLoop::current()->Run();
128 EXPECT_EQ(File::FILE_OK, error_);
129 EXPECT_TRUE(proxy.IsValid());
130 EXPECT_FALSE(proxy.created());
133 TEST_F(FileProxyTest, CreateOrOpen_OpenNonExistent) {
134 FileProxy proxy(file_task_runner());
137 File::FLAG_OPEN | File::FLAG_READ,
138 Bind(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
139 MessageLoop::current()->Run();
140 EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, error_);
141 EXPECT_FALSE(proxy.IsValid());
142 EXPECT_FALSE(proxy.created());
143 EXPECT_FALSE(PathExists(test_path()));
146 TEST_F(FileProxyTest, Close) {
148 FileProxy proxy(file_task_runner());
149 CreateProxy(File::FLAG_CREATE | File::FLAG_WRITE, &proxy);
152 // This fails on Windows if the file is not closed.
153 EXPECT_FALSE(base::Move(test_path(), test_dir_path().AppendASCII("new")));
156 proxy.Close(Bind(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
157 MessageLoop::current()->Run();
158 EXPECT_EQ(File::FILE_OK, error_);
159 EXPECT_FALSE(proxy.IsValid());
161 // Now it should pass on all platforms.
162 EXPECT_TRUE(base::Move(test_path(), test_dir_path().AppendASCII("new")));
165 TEST_F(FileProxyTest, CreateTemporary) {
167 FileProxy proxy(file_task_runner());
168 proxy.CreateTemporary(
169 0 /* additional_file_flags */,
170 Bind(&FileProxyTest::DidCreateTemporary, weak_factory_.GetWeakPtr()));
171 MessageLoop::current()->Run();
173 EXPECT_TRUE(proxy.IsValid());
174 EXPECT_EQ(File::FILE_OK, error_);
175 EXPECT_TRUE(PathExists(path_));
177 // The file should be writable.
178 proxy.Write(0, "test", 4,
179 Bind(&FileProxyTest::DidWrite, weak_factory_.GetWeakPtr()));
180 MessageLoop::current()->Run();
181 EXPECT_EQ(File::FILE_OK, error_);
182 EXPECT_EQ(4, bytes_written_);
185 // Make sure the written data can be read from the returned path.
187 EXPECT_TRUE(ReadFileToString(path_, &data));
188 EXPECT_EQ("test", data);
190 // Make sure we can & do delete the created file to prevent leaks on the bots.
191 EXPECT_TRUE(base::DeleteFile(path_, false));
194 TEST_F(FileProxyTest, GetInfo) {
196 ASSERT_EQ(4, base::WriteFile(test_path(), "test", 4));
197 File::Info expected_info;
198 GetFileInfo(test_path(), &expected_info);
201 FileProxy proxy(file_task_runner());
202 CreateProxy(File::FLAG_OPEN | File::FLAG_READ, &proxy);
204 Bind(&FileProxyTest::DidGetFileInfo, weak_factory_.GetWeakPtr()));
205 MessageLoop::current()->Run();
208 EXPECT_EQ(File::FILE_OK, error_);
209 EXPECT_EQ(expected_info.size, file_info_.size);
210 EXPECT_EQ(expected_info.is_directory, file_info_.is_directory);
211 EXPECT_EQ(expected_info.is_symbolic_link, file_info_.is_symbolic_link);
213 File file = proxy.TakeFile();
214 EXPECT_TRUE(file.GetInfo(&expected_info));
215 EXPECT_EQ(expected_info.last_modified, file_info_.last_modified);
216 EXPECT_EQ(expected_info.creation_time, file_info_.creation_time);
219 TEST_F(FileProxyTest, Read) {
221 const char expected_data[] = "bleh";
222 int expected_bytes = arraysize(expected_data);
223 ASSERT_EQ(expected_bytes,
224 base::WriteFile(test_path(), expected_data, expected_bytes));
227 FileProxy proxy(file_task_runner());
228 CreateProxy(File::FLAG_OPEN | File::FLAG_READ, &proxy);
230 proxy.Read(0, 128, Bind(&FileProxyTest::DidRead, weak_factory_.GetWeakPtr()));
231 MessageLoop::current()->Run();
234 EXPECT_EQ(File::FILE_OK, error_);
235 EXPECT_EQ(expected_bytes, static_cast<int>(buffer_.size()));
236 for (size_t i = 0; i < buffer_.size(); ++i) {
237 EXPECT_EQ(expected_data[i], buffer_[i]);
241 TEST_F(FileProxyTest, WriteAndFlush) {
242 FileProxy proxy(file_task_runner());
243 CreateProxy(File::FLAG_CREATE | File::FLAG_WRITE, &proxy);
245 const char data[] = "foo!";
246 int data_bytes = ARRAYSIZE_UNSAFE(data);
247 proxy.Write(0, data, data_bytes,
248 Bind(&FileProxyTest::DidWrite, weak_factory_.GetWeakPtr()));
249 MessageLoop::current()->Run();
250 EXPECT_EQ(File::FILE_OK, error_);
251 EXPECT_EQ(data_bytes, bytes_written_);
253 // Flush the written data. (So that the following read should always
254 // succeed. On some platforms it may work with or without this flush.)
255 proxy.Flush(Bind(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
256 MessageLoop::current()->Run();
257 EXPECT_EQ(File::FILE_OK, error_);
259 // Verify the written data.
261 EXPECT_EQ(data_bytes, base::ReadFile(test_path(), buffer, data_bytes));
262 for (int i = 0; i < data_bytes; ++i) {
263 EXPECT_EQ(data[i], buffer[i]);
267 TEST_F(FileProxyTest, SetTimes) {
268 FileProxy proxy(file_task_runner());
270 File::FLAG_CREATE | File::FLAG_WRITE | File::FLAG_WRITE_ATTRIBUTES,
273 Time last_accessed_time = Time::Now() - TimeDelta::FromDays(12345);
274 Time last_modified_time = Time::Now() - TimeDelta::FromHours(98765);
276 proxy.SetTimes(last_accessed_time, last_modified_time,
277 Bind(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
278 MessageLoop::current()->Run();
279 EXPECT_EQ(File::FILE_OK, error_);
282 GetFileInfo(test_path(), &info);
284 // The returned values may only have the seconds precision, so we cast
285 // the double values to int here.
286 EXPECT_EQ(static_cast<int>(last_modified_time.ToDoubleT()),
287 static_cast<int>(info.last_modified.ToDoubleT()));
288 EXPECT_EQ(static_cast<int>(last_accessed_time.ToDoubleT()),
289 static_cast<int>(info.last_accessed.ToDoubleT()));
292 TEST_F(FileProxyTest, SetLength_Shrink) {
294 const char kTestData[] = "0123456789";
295 ASSERT_EQ(10, base::WriteFile(test_path(), kTestData, 10));
297 GetFileInfo(test_path(), &info);
298 ASSERT_EQ(10, info.size);
301 FileProxy proxy(file_task_runner());
302 CreateProxy(File::FLAG_OPEN | File::FLAG_WRITE, &proxy);
304 Bind(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
305 MessageLoop::current()->Run();
308 GetFileInfo(test_path(), &info);
309 ASSERT_EQ(7, info.size);
312 EXPECT_EQ(7, base::ReadFile(test_path(), buffer, 7));
315 EXPECT_EQ(kTestData[i], buffer[i]);
318 TEST_F(FileProxyTest, SetLength_Expand) {
320 const char kTestData[] = "9876543210";
321 ASSERT_EQ(10, base::WriteFile(test_path(), kTestData, 10));
323 GetFileInfo(test_path(), &info);
324 ASSERT_EQ(10, info.size);
327 FileProxy proxy(file_task_runner());
328 CreateProxy(File::FLAG_OPEN | File::FLAG_WRITE, &proxy);
330 Bind(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
331 MessageLoop::current()->Run();
334 GetFileInfo(test_path(), &info);
335 ASSERT_EQ(53, info.size);
338 EXPECT_EQ(53, base::ReadFile(test_path(), buffer, 53));
341 EXPECT_EQ(kTestData[i], buffer[i]);
343 EXPECT_EQ(0, buffer[i]);