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.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
14 TEST(FileTest
, Create
) {
15 base::ScopedTempDir temp_dir
;
16 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
17 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
20 // Don't create a File at all.
22 EXPECT_FALSE(file
.IsValid());
23 EXPECT_EQ(base::File::FILE_ERROR_FAILED
, file
.error_details());
25 File
file2(base::File::FILE_ERROR_TOO_MANY_OPENED
);
26 EXPECT_FALSE(file2
.IsValid());
27 EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED
, file2
.error_details());
31 // Open a file that doesn't exist.
32 File
file(file_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
33 EXPECT_FALSE(file
.IsValid());
34 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
, file
.error_details());
38 // Open or create a file.
39 File
file(file_path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
);
40 EXPECT_TRUE(file
.IsValid());
41 EXPECT_TRUE(file
.created());
42 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
46 // Open an existing file.
47 File
file(file_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
48 EXPECT_TRUE(file
.IsValid());
49 EXPECT_FALSE(file
.created());
50 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
52 // This time verify closing the file.
54 EXPECT_FALSE(file
.IsValid());
58 // Open an existing file through Initialize
60 file
.Initialize(file_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
61 EXPECT_TRUE(file
.IsValid());
62 EXPECT_FALSE(file
.created());
63 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
65 // This time verify closing the file.
67 EXPECT_FALSE(file
.IsValid());
71 // Create a file that exists.
72 File
file(file_path
, base::File::FLAG_CREATE
| base::File::FLAG_READ
);
73 EXPECT_FALSE(file
.IsValid());
74 EXPECT_FALSE(file
.created());
75 EXPECT_EQ(base::File::FILE_ERROR_EXISTS
, file
.error_details());
79 // Create or overwrite a file.
81 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
);
82 EXPECT_TRUE(file
.IsValid());
83 EXPECT_TRUE(file
.created());
84 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
88 // Create a delete-on-close file.
89 file_path
= temp_dir
.path().AppendASCII("create_file_2");
91 base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
|
92 base::File::FLAG_DELETE_ON_CLOSE
);
93 EXPECT_TRUE(file
.IsValid());
94 EXPECT_TRUE(file
.created());
95 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
98 EXPECT_FALSE(base::PathExists(file_path
));
101 TEST(FileTest
, Async
) {
102 base::ScopedTempDir temp_dir
;
103 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
104 FilePath file_path
= temp_dir
.path().AppendASCII("create_file");
107 File
file(file_path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_ASYNC
);
108 EXPECT_TRUE(file
.IsValid());
109 EXPECT_TRUE(file
.async());
113 File
file(file_path
, base::File::FLAG_OPEN_ALWAYS
);
114 EXPECT_TRUE(file
.IsValid());
115 EXPECT_FALSE(file
.async());
119 TEST(FileTest
, DeleteOpenFile
) {
120 base::ScopedTempDir temp_dir
;
121 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
122 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
126 base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
|
127 base::File::FLAG_SHARE_DELETE
);
128 EXPECT_TRUE(file
.IsValid());
129 EXPECT_TRUE(file
.created());
130 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
132 // Open an existing file and mark it as delete on close.
133 File
same_file(file_path
,
134 base::File::FLAG_OPEN
| base::File::FLAG_DELETE_ON_CLOSE
|
135 base::File::FLAG_READ
);
136 EXPECT_TRUE(file
.IsValid());
137 EXPECT_FALSE(same_file
.created());
138 EXPECT_EQ(base::File::FILE_OK
, same_file
.error_details());
140 // Close both handles and check that the file is gone.
143 EXPECT_FALSE(base::PathExists(file_path
));
146 TEST(FileTest
, ReadWrite
) {
147 base::ScopedTempDir temp_dir
;
148 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
149 FilePath file_path
= temp_dir
.path().AppendASCII("read_write_file");
151 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
152 base::File::FLAG_WRITE
);
153 ASSERT_TRUE(file
.IsValid());
155 char data_to_write
[] = "test";
156 const int kTestDataSize
= 4;
158 // Write 0 bytes to the file.
159 int bytes_written
= file
.Write(0, data_to_write
, 0);
160 EXPECT_EQ(0, bytes_written
);
162 // Write "test" to the file.
163 bytes_written
= file
.Write(0, data_to_write
, kTestDataSize
);
164 EXPECT_EQ(kTestDataSize
, bytes_written
);
167 char data_read_1
[32];
168 int bytes_read
= file
.Read(kTestDataSize
, data_read_1
, kTestDataSize
);
169 EXPECT_EQ(0, bytes_read
);
171 // Read from somewhere in the middle of the file.
172 const int kPartialReadOffset
= 1;
173 bytes_read
= file
.Read(kPartialReadOffset
, data_read_1
, kTestDataSize
);
174 EXPECT_EQ(kTestDataSize
- kPartialReadOffset
, bytes_read
);
175 for (int i
= 0; i
< bytes_read
; i
++)
176 EXPECT_EQ(data_to_write
[i
+ kPartialReadOffset
], data_read_1
[i
]);
179 bytes_read
= file
.Read(0, data_read_1
, 0);
180 EXPECT_EQ(0, bytes_read
);
182 // Read the entire file.
183 bytes_read
= file
.Read(0, data_read_1
, kTestDataSize
);
184 EXPECT_EQ(kTestDataSize
, bytes_read
);
185 for (int i
= 0; i
< bytes_read
; i
++)
186 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
188 // Read again, but using the trivial native wrapper.
189 bytes_read
= file
.ReadNoBestEffort(0, data_read_1
, kTestDataSize
);
190 EXPECT_LE(bytes_read
, kTestDataSize
);
191 for (int i
= 0; i
< bytes_read
; i
++)
192 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
194 // Write past the end of the file.
195 const int kOffsetBeyondEndOfFile
= 10;
196 const int kPartialWriteLength
= 2;
197 bytes_written
= file
.Write(kOffsetBeyondEndOfFile
,
198 data_to_write
, kPartialWriteLength
);
199 EXPECT_EQ(kPartialWriteLength
, bytes_written
);
201 // Make sure the file was extended.
203 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
204 EXPECT_EQ(kOffsetBeyondEndOfFile
+ kPartialWriteLength
, file_size
);
206 // Make sure the file was zero-padded.
207 char data_read_2
[32];
208 bytes_read
= file
.Read(0, data_read_2
, static_cast<int>(file_size
));
209 EXPECT_EQ(file_size
, bytes_read
);
210 for (int i
= 0; i
< kTestDataSize
; i
++)
211 EXPECT_EQ(data_to_write
[i
], data_read_2
[i
]);
212 for (int i
= kTestDataSize
; i
< kOffsetBeyondEndOfFile
; i
++)
213 EXPECT_EQ(0, data_read_2
[i
]);
214 for (int i
= kOffsetBeyondEndOfFile
; i
< file_size
; i
++)
215 EXPECT_EQ(data_to_write
[i
- kOffsetBeyondEndOfFile
], data_read_2
[i
]);
218 TEST(FileTest
, Append
) {
219 base::ScopedTempDir temp_dir
;
220 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
221 FilePath file_path
= temp_dir
.path().AppendASCII("append_file");
222 File
file(file_path
, base::File::FLAG_CREATE
| base::File::FLAG_APPEND
);
223 ASSERT_TRUE(file
.IsValid());
225 char data_to_write
[] = "test";
226 const int kTestDataSize
= 4;
228 // Write 0 bytes to the file.
229 int bytes_written
= file
.Write(0, data_to_write
, 0);
230 EXPECT_EQ(0, bytes_written
);
232 // Write "test" to the file.
233 bytes_written
= file
.Write(0, data_to_write
, kTestDataSize
);
234 EXPECT_EQ(kTestDataSize
, bytes_written
);
237 File
file2(file_path
,
238 base::File::FLAG_OPEN
| base::File::FLAG_READ
|
239 base::File::FLAG_APPEND
);
240 ASSERT_TRUE(file2
.IsValid());
242 // Test passing the file around.
244 EXPECT_FALSE(file2
.IsValid());
245 ASSERT_TRUE(file
.IsValid());
247 char append_data_to_write
[] = "78";
248 const int kAppendDataSize
= 2;
250 // Append "78" to the file.
251 bytes_written
= file
.Write(0, append_data_to_write
, kAppendDataSize
);
252 EXPECT_EQ(kAppendDataSize
, bytes_written
);
254 // Read the entire file.
255 char data_read_1
[32];
256 int bytes_read
= file
.Read(0, data_read_1
,
257 kTestDataSize
+ kAppendDataSize
);
258 EXPECT_EQ(kTestDataSize
+ kAppendDataSize
, bytes_read
);
259 for (int i
= 0; i
< kTestDataSize
; i
++)
260 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
261 for (int i
= 0; i
< kAppendDataSize
; i
++)
262 EXPECT_EQ(append_data_to_write
[i
], data_read_1
[kTestDataSize
+ i
]);
266 TEST(FileTest
, Length
) {
267 base::ScopedTempDir temp_dir
;
268 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
269 FilePath file_path
= temp_dir
.path().AppendASCII("truncate_file");
271 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
272 base::File::FLAG_WRITE
);
273 ASSERT_TRUE(file
.IsValid());
274 EXPECT_EQ(0, file
.GetLength());
276 // Write "test" to the file.
277 char data_to_write
[] = "test";
278 int kTestDataSize
= 4;
279 int bytes_written
= file
.Write(0, data_to_write
, kTestDataSize
);
280 EXPECT_EQ(kTestDataSize
, bytes_written
);
283 const int kExtendedFileLength
= 10;
285 EXPECT_TRUE(file
.SetLength(kExtendedFileLength
));
286 EXPECT_EQ(kExtendedFileLength
, file
.GetLength());
287 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
288 EXPECT_EQ(kExtendedFileLength
, file_size
);
290 // Make sure the file was zero-padded.
292 int bytes_read
= file
.Read(0, data_read
, static_cast<int>(file_size
));
293 EXPECT_EQ(file_size
, bytes_read
);
294 for (int i
= 0; i
< kTestDataSize
; i
++)
295 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
296 for (int i
= kTestDataSize
; i
< file_size
; i
++)
297 EXPECT_EQ(0, data_read
[i
]);
299 // Truncate the file.
300 const int kTruncatedFileLength
= 2;
301 EXPECT_TRUE(file
.SetLength(kTruncatedFileLength
));
302 EXPECT_EQ(kTruncatedFileLength
, file
.GetLength());
303 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
304 EXPECT_EQ(kTruncatedFileLength
, file_size
);
306 // Make sure the file was truncated.
307 bytes_read
= file
.Read(0, data_read
, kTestDataSize
);
308 EXPECT_EQ(file_size
, bytes_read
);
309 for (int i
= 0; i
< file_size
; i
++)
310 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
313 // Flakily fails: http://crbug.com/86494
314 #if defined(OS_ANDROID)
315 TEST(FileTest
, TouchGetInfo
) {
317 TEST(FileTest
, DISABLED_TouchGetInfo
) {
319 base::ScopedTempDir temp_dir
;
320 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
321 File
file(temp_dir
.path().AppendASCII("touch_get_info_file"),
322 base::File::FLAG_CREATE
| base::File::FLAG_WRITE
|
323 base::File::FLAG_WRITE_ATTRIBUTES
);
324 ASSERT_TRUE(file
.IsValid());
326 // Get info for a newly created file.
327 base::File::Info info
;
328 EXPECT_TRUE(file
.GetInfo(&info
));
330 // Add 2 seconds to account for possible rounding errors on
331 // filesystems that use a 1s or 2s timestamp granularity.
332 base::Time now
= base::Time::Now() + base::TimeDelta::FromSeconds(2);
333 EXPECT_EQ(0, info
.size
);
334 EXPECT_FALSE(info
.is_directory
);
335 EXPECT_FALSE(info
.is_symbolic_link
);
336 EXPECT_LE(info
.last_accessed
.ToInternalValue(), now
.ToInternalValue());
337 EXPECT_LE(info
.last_modified
.ToInternalValue(), now
.ToInternalValue());
338 EXPECT_LE(info
.creation_time
.ToInternalValue(), now
.ToInternalValue());
339 base::Time creation_time
= info
.creation_time
;
341 // Write "test" to the file.
342 char data
[] = "test";
343 const int kTestDataSize
= 4;
344 int bytes_written
= file
.Write(0, data
, kTestDataSize
);
345 EXPECT_EQ(kTestDataSize
, bytes_written
);
347 // Change the last_accessed and last_modified dates.
348 // It's best to add values that are multiples of 2 (in seconds)
349 // to the current last_accessed and last_modified times, because
350 // FATxx uses a 2s timestamp granularity.
351 base::Time new_last_accessed
=
352 info
.last_accessed
+ base::TimeDelta::FromSeconds(234);
353 base::Time new_last_modified
=
354 info
.last_modified
+ base::TimeDelta::FromMinutes(567);
356 EXPECT_TRUE(file
.SetTimes(new_last_accessed
, new_last_modified
));
358 // Make sure the file info was updated accordingly.
359 EXPECT_TRUE(file
.GetInfo(&info
));
360 EXPECT_EQ(info
.size
, kTestDataSize
);
361 EXPECT_FALSE(info
.is_directory
);
362 EXPECT_FALSE(info
.is_symbolic_link
);
364 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
365 #if defined(OS_POSIX)
366 EXPECT_EQ(info
.last_accessed
.ToTimeVal().tv_sec
,
367 new_last_accessed
.ToTimeVal().tv_sec
);
368 EXPECT_EQ(info
.last_modified
.ToTimeVal().tv_sec
,
369 new_last_modified
.ToTimeVal().tv_sec
);
371 EXPECT_EQ(info
.last_accessed
.ToInternalValue(),
372 new_last_accessed
.ToInternalValue());
373 EXPECT_EQ(info
.last_modified
.ToInternalValue(),
374 new_last_modified
.ToInternalValue());
377 EXPECT_EQ(info
.creation_time
.ToInternalValue(),
378 creation_time
.ToInternalValue());
381 TEST(FileTest
, ReadAtCurrentPosition
) {
382 base::ScopedTempDir temp_dir
;
383 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
384 FilePath file_path
= temp_dir
.path().AppendASCII("read_at_current_position");
386 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
387 base::File::FLAG_WRITE
);
388 EXPECT_TRUE(file
.IsValid());
390 const char kData
[] = "test";
391 const int kDataSize
= sizeof(kData
) - 1;
392 EXPECT_EQ(kDataSize
, file
.Write(0, kData
, kDataSize
));
394 EXPECT_EQ(0, file
.Seek(base::File::FROM_BEGIN
, 0));
396 char buffer
[kDataSize
];
397 int first_chunk_size
= kDataSize
/ 2;
398 EXPECT_EQ(first_chunk_size
, file
.ReadAtCurrentPos(buffer
, first_chunk_size
));
399 EXPECT_EQ(kDataSize
- first_chunk_size
,
400 file
.ReadAtCurrentPos(buffer
+ first_chunk_size
,
401 kDataSize
- first_chunk_size
));
402 EXPECT_EQ(std::string(buffer
, buffer
+ kDataSize
), std::string(kData
));
405 TEST(FileTest
, WriteAtCurrentPosition
) {
406 base::ScopedTempDir temp_dir
;
407 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
408 FilePath file_path
= temp_dir
.path().AppendASCII("write_at_current_position");
410 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
411 base::File::FLAG_WRITE
);
412 EXPECT_TRUE(file
.IsValid());
414 const char kData
[] = "test";
415 const int kDataSize
= sizeof(kData
) - 1;
417 int first_chunk_size
= kDataSize
/ 2;
418 EXPECT_EQ(first_chunk_size
, file
.WriteAtCurrentPos(kData
, first_chunk_size
));
419 EXPECT_EQ(kDataSize
- first_chunk_size
,
420 file
.WriteAtCurrentPos(kData
+ first_chunk_size
,
421 kDataSize
- first_chunk_size
));
423 char buffer
[kDataSize
];
424 EXPECT_EQ(kDataSize
, file
.Read(0, buffer
, kDataSize
));
425 EXPECT_EQ(std::string(buffer
, buffer
+ kDataSize
), std::string(kData
));
428 TEST(FileTest
, Seek
) {
429 base::ScopedTempDir temp_dir
;
430 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
431 FilePath file_path
= temp_dir
.path().AppendASCII("seek_file");
433 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
434 base::File::FLAG_WRITE
);
435 ASSERT_TRUE(file
.IsValid());
437 const int64 kOffset
= 10;
438 EXPECT_EQ(kOffset
, file
.Seek(base::File::FROM_BEGIN
, kOffset
));
439 EXPECT_EQ(2 * kOffset
, file
.Seek(base::File::FROM_CURRENT
, kOffset
));
440 EXPECT_EQ(kOffset
, file
.Seek(base::File::FROM_CURRENT
, -kOffset
));
441 EXPECT_TRUE(file
.SetLength(kOffset
* 2));
442 EXPECT_EQ(kOffset
, file
.Seek(base::File::FROM_END
, -kOffset
));
446 TEST(FileTest
, GetInfoForDirectory
) {
447 base::ScopedTempDir temp_dir
;
448 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
449 FilePath empty_dir
= temp_dir
.path().Append(FILE_PATH_LITERAL("gpfi_test"));
450 ASSERT_TRUE(CreateDirectory(empty_dir
));
453 ::CreateFile(empty_dir
.value().c_str(),
455 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
458 FILE_FLAG_BACKUP_SEMANTICS
, // Needed to open a directory.
460 ASSERT_TRUE(dir
.IsValid());
462 base::File::Info info
;
463 EXPECT_TRUE(dir
.GetInfo(&info
));
464 EXPECT_TRUE(info
.is_directory
);
465 EXPECT_FALSE(info
.is_symbolic_link
);
466 EXPECT_EQ(0, info
.size
);
468 #endif // defined(OS_WIN)