1 // Copyright (c) 2012 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_util_proxy.h"
10 #include "base/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/logging.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/message_loop.h"
15 #include "base/platform_file.h"
16 #include "base/threading/thread.h"
17 #include "testing/gtest/include/gtest/gtest.h"
21 class FileUtilProxyTest
: public testing::Test
{
24 : message_loop_(MessageLoop::TYPE_IO
),
25 file_thread_("FileUtilProxyTestFileThread"),
26 error_(PLATFORM_FILE_OK
),
28 file_(kInvalidPlatformFileValue
),
30 weak_factory_(this) {}
32 virtual void SetUp() OVERRIDE
{
33 ASSERT_TRUE(dir_
.CreateUniqueTempDir());
34 ASSERT_TRUE(file_thread_
.Start());
37 virtual void TearDown() OVERRIDE
{
38 if (file_
!= kInvalidPlatformFileValue
)
39 ClosePlatformFile(file_
);
42 void DidFinish(PlatformFileError error
) {
44 MessageLoop::current()->QuitWhenIdle();
47 void DidCreateOrOpen(PlatformFileError error
,
48 PassPlatformFile file
,
51 file_
= file
.ReleaseValue();
53 MessageLoop::current()->QuitWhenIdle();
56 void DidCreateTemporary(PlatformFileError error
,
57 PassPlatformFile file
,
58 const FilePath
& path
) {
60 file_
= file
.ReleaseValue();
62 MessageLoop::current()->QuitWhenIdle();
65 void DidGetFileInfo(PlatformFileError error
,
66 const PlatformFileInfo
& file_info
) {
68 file_info_
= file_info
;
69 MessageLoop::current()->QuitWhenIdle();
72 void DidRead(PlatformFileError error
,
76 buffer_
.resize(bytes_read
);
77 memcpy(&buffer_
[0], data
, bytes_read
);
78 MessageLoop::current()->QuitWhenIdle();
81 void DidWrite(PlatformFileError error
,
84 bytes_written_
= bytes_written
;
85 MessageLoop::current()->QuitWhenIdle();
89 PlatformFile
GetTestPlatformFile(int flags
) {
90 if (file_
!= kInvalidPlatformFileValue
)
93 PlatformFileError error
;
94 file_
= CreatePlatformFile(test_path(), flags
, &created
, &error
);
95 EXPECT_EQ(PLATFORM_FILE_OK
, error
);
96 EXPECT_NE(kInvalidPlatformFileValue
, file_
);
100 TaskRunner
* file_task_runner() const {
101 return file_thread_
.message_loop_proxy().get();
103 const FilePath
& test_dir_path() const { return dir_
.path(); }
104 const FilePath
test_path() const { return dir_
.path().AppendASCII("test"); }
106 MessageLoop message_loop_
;
110 PlatformFileError error_
;
114 PlatformFileInfo file_info_
;
115 std::vector
<char> buffer_
;
117 WeakPtrFactory
<FileUtilProxyTest
> weak_factory_
;
120 TEST_F(FileUtilProxyTest
, CreateOrOpen_Create
) {
121 FileUtilProxy::CreateOrOpen(
124 PLATFORM_FILE_CREATE
| PLATFORM_FILE_READ
,
125 Bind(&FileUtilProxyTest::DidCreateOrOpen
, weak_factory_
.GetWeakPtr()));
126 MessageLoop::current()->Run();
128 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
129 EXPECT_TRUE(created_
);
130 EXPECT_NE(kInvalidPlatformFileValue
, file_
);
131 EXPECT_TRUE(file_util::PathExists(test_path()));
134 TEST_F(FileUtilProxyTest
, CreateOrOpen_Open
) {
136 file_util::WriteFile(test_path(), NULL
, 0);
137 ASSERT_TRUE(file_util::PathExists(test_path()));
139 // Opens the created file.
140 FileUtilProxy::CreateOrOpen(
143 PLATFORM_FILE_OPEN
| PLATFORM_FILE_READ
,
144 Bind(&FileUtilProxyTest::DidCreateOrOpen
, weak_factory_
.GetWeakPtr()));
145 MessageLoop::current()->Run();
147 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
148 EXPECT_FALSE(created_
);
149 EXPECT_NE(kInvalidPlatformFileValue
, file_
);
152 TEST_F(FileUtilProxyTest
, CreateOrOpen_OpenNonExistent
) {
153 FileUtilProxy::CreateOrOpen(
156 PLATFORM_FILE_OPEN
| PLATFORM_FILE_READ
,
157 Bind(&FileUtilProxyTest::DidCreateOrOpen
, weak_factory_
.GetWeakPtr()));
158 MessageLoop::current()->Run();
159 EXPECT_EQ(PLATFORM_FILE_ERROR_NOT_FOUND
, error_
);
160 EXPECT_FALSE(created_
);
161 EXPECT_EQ(kInvalidPlatformFileValue
, file_
);
162 EXPECT_FALSE(file_util::PathExists(test_path()));
165 TEST_F(FileUtilProxyTest
, Close
) {
167 PlatformFile file
= GetTestPlatformFile(
168 PLATFORM_FILE_CREATE
| PLATFORM_FILE_WRITE
);
171 // This fails on Windows if the file is not closed.
172 EXPECT_FALSE(file_util::Move(test_path(),
173 test_dir_path().AppendASCII("new")));
176 FileUtilProxy::Close(
179 Bind(&FileUtilProxyTest::DidFinish
, weak_factory_
.GetWeakPtr()));
180 MessageLoop::current()->Run();
181 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
183 // Now it should pass on all platforms.
184 EXPECT_TRUE(file_util::Move(test_path(), test_dir_path().AppendASCII("new")));
187 TEST_F(FileUtilProxyTest
, CreateTemporary
) {
188 FileUtilProxy::CreateTemporary(
189 file_task_runner(), 0 /* additional_file_flags */,
190 Bind(&FileUtilProxyTest::DidCreateTemporary
, weak_factory_
.GetWeakPtr()));
191 MessageLoop::current()->Run();
192 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
193 EXPECT_TRUE(file_util::PathExists(path_
));
194 EXPECT_NE(kInvalidPlatformFileValue
, file_
);
196 // The file should be writable.
198 HANDLE hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
199 OVERLAPPED overlapped
= {0};
200 overlapped
.hEvent
= hEvent
;
202 if (!::WriteFile(file_
, "test", 4, &bytes_written
, &overlapped
)) {
203 // Temporary file is created with ASYNC flag, so WriteFile may return 0
204 // with ERROR_IO_PENDING.
205 EXPECT_EQ(ERROR_IO_PENDING
, GetLastError());
206 GetOverlappedResult(file_
, &overlapped
, &bytes_written
, TRUE
);
208 EXPECT_EQ(4, bytes_written
);
210 // On POSIX ASYNC flag does not affect synchronous read/write behavior.
211 EXPECT_EQ(4, WritePlatformFile(file_
, 0, "test", 4));
213 EXPECT_TRUE(ClosePlatformFile(file_
));
214 file_
= kInvalidPlatformFileValue
;
216 // Make sure the written data can be read from the returned path.
218 EXPECT_TRUE(file_util::ReadFileToString(path_
, &data
));
219 EXPECT_EQ("test", data
);
221 // Make sure we can & do delete the created file to prevent leaks on the bots.
222 EXPECT_TRUE(file_util::Delete(path_
, false));
225 TEST_F(FileUtilProxyTest
, GetFileInfo_File
) {
227 ASSERT_EQ(4, file_util::WriteFile(test_path(), "test", 4));
228 PlatformFileInfo expected_info
;
229 file_util::GetFileInfo(test_path(), &expected_info
);
232 FileUtilProxy::GetFileInfo(
235 Bind(&FileUtilProxyTest::DidGetFileInfo
, weak_factory_
.GetWeakPtr()));
236 MessageLoop::current()->Run();
239 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
240 EXPECT_EQ(expected_info
.size
, file_info_
.size
);
241 EXPECT_EQ(expected_info
.is_directory
, file_info_
.is_directory
);
242 EXPECT_EQ(expected_info
.is_symbolic_link
, file_info_
.is_symbolic_link
);
243 EXPECT_EQ(expected_info
.last_modified
, file_info_
.last_modified
);
244 EXPECT_EQ(expected_info
.last_accessed
, file_info_
.last_accessed
);
245 EXPECT_EQ(expected_info
.creation_time
, file_info_
.creation_time
);
248 TEST_F(FileUtilProxyTest
, GetFileInfo_Directory
) {
250 ASSERT_TRUE(file_util::CreateDirectory(test_path()));
251 PlatformFileInfo expected_info
;
252 file_util::GetFileInfo(test_path(), &expected_info
);
255 FileUtilProxy::GetFileInfo(
258 Bind(&FileUtilProxyTest::DidGetFileInfo
, weak_factory_
.GetWeakPtr()));
259 MessageLoop::current()->Run();
262 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
263 EXPECT_EQ(expected_info
.size
, file_info_
.size
);
264 EXPECT_EQ(expected_info
.is_directory
, file_info_
.is_directory
);
265 EXPECT_EQ(expected_info
.is_symbolic_link
, file_info_
.is_symbolic_link
);
266 EXPECT_EQ(expected_info
.last_modified
, file_info_
.last_modified
);
267 EXPECT_EQ(expected_info
.last_accessed
, file_info_
.last_accessed
);
268 EXPECT_EQ(expected_info
.creation_time
, file_info_
.creation_time
);
271 TEST_F(FileUtilProxyTest
, Read
) {
273 const char expected_data
[] = "bleh";
274 int expected_bytes
= arraysize(expected_data
);
275 ASSERT_EQ(expected_bytes
,
276 file_util::WriteFile(test_path(), expected_data
, expected_bytes
));
281 GetTestPlatformFile(PLATFORM_FILE_OPEN
| PLATFORM_FILE_READ
),
284 Bind(&FileUtilProxyTest::DidRead
, weak_factory_
.GetWeakPtr()));
285 MessageLoop::current()->Run();
288 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
289 EXPECT_EQ(expected_bytes
, static_cast<int>(buffer_
.size()));
290 for (size_t i
= 0; i
< buffer_
.size(); ++i
) {
291 EXPECT_EQ(expected_data
[i
], buffer_
[i
]);
295 TEST_F(FileUtilProxyTest
, WriteAndFlush
) {
296 const char data
[] = "foo!";
297 int data_bytes
= ARRAYSIZE_UNSAFE(data
);
298 PlatformFile file
= GetTestPlatformFile(
299 PLATFORM_FILE_CREATE
| PLATFORM_FILE_WRITE
);
301 FileUtilProxy::Write(
307 Bind(&FileUtilProxyTest::DidWrite
, weak_factory_
.GetWeakPtr()));
308 MessageLoop::current()->Run();
309 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
310 EXPECT_EQ(data_bytes
, bytes_written_
);
312 // Flush the written data. (So that the following read should always
313 // succeed. On some platforms it may work with or without this flush.)
314 FileUtilProxy::Flush(
317 Bind(&FileUtilProxyTest::DidFinish
, weak_factory_
.GetWeakPtr()));
318 MessageLoop::current()->Run();
319 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
321 // Verify the written data.
323 EXPECT_EQ(data_bytes
, file_util::ReadFile(test_path(), buffer
, data_bytes
));
324 for (int i
= 0; i
< data_bytes
; ++i
) {
325 EXPECT_EQ(data
[i
], buffer
[i
]);
329 TEST_F(FileUtilProxyTest
, Touch
) {
330 Time last_accessed_time
= Time::Now() - TimeDelta::FromDays(12345);
331 Time last_modified_time
= Time::Now() - TimeDelta::FromHours(98765);
333 FileUtilProxy::Touch(
335 GetTestPlatformFile(PLATFORM_FILE_CREATE
|
336 PLATFORM_FILE_WRITE
|
337 PLATFORM_FILE_WRITE_ATTRIBUTES
),
340 Bind(&FileUtilProxyTest::DidFinish
, weak_factory_
.GetWeakPtr()));
341 MessageLoop::current()->Run();
342 EXPECT_EQ(PLATFORM_FILE_OK
, error_
);
344 PlatformFileInfo info
;
345 file_util::GetFileInfo(test_path(), &info
);
347 // The returned values may only have the seconds precision, so we cast
348 // the double values to int here.
349 EXPECT_EQ(static_cast<int>(last_modified_time
.ToDoubleT()),
350 static_cast<int>(info
.last_modified
.ToDoubleT()));
351 EXPECT_EQ(static_cast<int>(last_accessed_time
.ToDoubleT()),
352 static_cast<int>(info
.last_accessed
.ToDoubleT()));
355 TEST_F(FileUtilProxyTest
, Truncate_Shrink
) {
357 const char kTestData
[] = "0123456789";
358 ASSERT_EQ(10, file_util::WriteFile(test_path(), kTestData
, 10));
359 PlatformFileInfo info
;
360 file_util::GetFileInfo(test_path(), &info
);
361 ASSERT_EQ(10, info
.size
);
364 FileUtilProxy::Truncate(
366 GetTestPlatformFile(PLATFORM_FILE_OPEN
| PLATFORM_FILE_WRITE
),
368 Bind(&FileUtilProxyTest::DidFinish
, weak_factory_
.GetWeakPtr()));
369 MessageLoop::current()->Run();
372 file_util::GetFileInfo(test_path(), &info
);
373 ASSERT_EQ(7, info
.size
);
376 EXPECT_EQ(7, file_util::ReadFile(test_path(), buffer
, 7));
379 EXPECT_EQ(kTestData
[i
], buffer
[i
]);
382 TEST_F(FileUtilProxyTest
, Truncate_Expand
) {
384 const char kTestData
[] = "9876543210";
385 ASSERT_EQ(10, file_util::WriteFile(test_path(), kTestData
, 10));
386 PlatformFileInfo info
;
387 file_util::GetFileInfo(test_path(), &info
);
388 ASSERT_EQ(10, info
.size
);
391 FileUtilProxy::Truncate(
393 GetTestPlatformFile(PLATFORM_FILE_OPEN
| PLATFORM_FILE_WRITE
),
395 Bind(&FileUtilProxyTest::DidFinish
, weak_factory_
.GetWeakPtr()));
396 MessageLoop::current()->Run();
399 file_util::GetFileInfo(test_path(), &info
);
400 ASSERT_EQ(53, info
.size
);
403 EXPECT_EQ(53, file_util::ReadFile(test_path(), buffer
, 53));
406 EXPECT_EQ(kTestData
[i
], buffer
[i
]);
408 EXPECT_EQ(0, buffer
[i
]);