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/file_util.h"
6 #include "base/files/file.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
15 base::ScopedTempDir temp_dir
;
16 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
17 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
20 // Open a file that doesn't exist.
21 File
file(file_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
22 EXPECT_FALSE(file
.IsValid());
23 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
, file
.error_details());
27 // Open or create a file.
28 File
file(file_path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
);
29 EXPECT_TRUE(file
.IsValid());
30 EXPECT_TRUE(file
.created());
31 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
35 // Open an existing file.
36 File
file(file_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
37 EXPECT_TRUE(file
.IsValid());
38 EXPECT_FALSE(file
.created());
39 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
41 // This time verify closing the file.
43 EXPECT_FALSE(file
.IsValid());
47 // Open an existing file through Initialize
49 file
.Initialize(file_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
50 EXPECT_TRUE(file
.IsValid());
51 EXPECT_FALSE(file
.created());
52 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
54 // This time verify closing the file.
56 EXPECT_FALSE(file
.IsValid());
60 // Create a file that exists.
61 File
file(file_path
, base::File::FLAG_CREATE
| base::File::FLAG_READ
);
62 EXPECT_FALSE(file
.IsValid());
63 EXPECT_FALSE(file
.created());
64 EXPECT_EQ(base::File::FILE_ERROR_EXISTS
, file
.error_details());
68 // Create or overwrite a file.
70 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_READ
);
71 EXPECT_TRUE(file
.IsValid());
72 EXPECT_TRUE(file
.created());
73 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
77 // Create a delete-on-close file.
78 file_path
= temp_dir
.path().AppendASCII("create_file_2");
80 base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
|
81 base::File::FLAG_DELETE_ON_CLOSE
);
82 EXPECT_TRUE(file
.IsValid());
83 EXPECT_TRUE(file
.created());
84 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
87 EXPECT_FALSE(base::PathExists(file_path
));
90 TEST(File
, DeleteOpenFile
) {
91 base::ScopedTempDir temp_dir
;
92 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
93 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
97 base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
|
98 base::File::FLAG_SHARE_DELETE
);
99 EXPECT_TRUE(file
.IsValid());
100 EXPECT_TRUE(file
.created());
101 EXPECT_EQ(base::File::FILE_OK
, file
.error_details());
103 // Open an existing file and mark it as delete on close.
104 File
same_file(file_path
,
105 base::File::FLAG_OPEN
| base::File::FLAG_DELETE_ON_CLOSE
|
106 base::File::FLAG_READ
);
107 EXPECT_TRUE(file
.IsValid());
108 EXPECT_FALSE(same_file
.created());
109 EXPECT_EQ(base::File::FILE_OK
, same_file
.error_details());
111 // Close both handles and check that the file is gone.
114 EXPECT_FALSE(base::PathExists(file_path
));
117 TEST(File
, ReadWrite
) {
118 base::ScopedTempDir temp_dir
;
119 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
120 FilePath file_path
= temp_dir
.path().AppendASCII("read_write_file");
122 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
123 base::File::FLAG_WRITE
);
124 ASSERT_TRUE(file
.IsValid());
126 char data_to_write
[] = "test";
127 const int kTestDataSize
= 4;
129 // Write 0 bytes to the file.
130 int bytes_written
= file
.Write(0, data_to_write
, 0);
131 EXPECT_EQ(0, bytes_written
);
133 // Write "test" to the file.
134 bytes_written
= file
.Write(0, data_to_write
, kTestDataSize
);
135 EXPECT_EQ(kTestDataSize
, bytes_written
);
138 char data_read_1
[32];
139 int bytes_read
= file
.Read(kTestDataSize
, data_read_1
, kTestDataSize
);
140 EXPECT_EQ(0, bytes_read
);
142 // Read from somewhere in the middle of the file.
143 const int kPartialReadOffset
= 1;
144 bytes_read
= file
.Read(kPartialReadOffset
, data_read_1
, kTestDataSize
);
145 EXPECT_EQ(kTestDataSize
- kPartialReadOffset
, bytes_read
);
146 for (int i
= 0; i
< bytes_read
; i
++)
147 EXPECT_EQ(data_to_write
[i
+ kPartialReadOffset
], data_read_1
[i
]);
150 bytes_read
= file
.Read(0, data_read_1
, 0);
151 EXPECT_EQ(0, bytes_read
);
153 // Read the entire file.
154 bytes_read
= file
.Read(0, data_read_1
, kTestDataSize
);
155 EXPECT_EQ(kTestDataSize
, bytes_read
);
156 for (int i
= 0; i
< bytes_read
; i
++)
157 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
159 // Read again, but using the trivial native wrapper.
160 bytes_read
= file
.ReadNoBestEffort(0, data_read_1
, kTestDataSize
);
161 EXPECT_LE(bytes_read
, kTestDataSize
);
162 for (int i
= 0; i
< bytes_read
; i
++)
163 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
165 // Write past the end of the file.
166 const int kOffsetBeyondEndOfFile
= 10;
167 const int kPartialWriteLength
= 2;
168 bytes_written
= file
.Write(kOffsetBeyondEndOfFile
,
169 data_to_write
, kPartialWriteLength
);
170 EXPECT_EQ(kPartialWriteLength
, bytes_written
);
172 // Make sure the file was extended.
174 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
175 EXPECT_EQ(kOffsetBeyondEndOfFile
+ kPartialWriteLength
, file_size
);
177 // Make sure the file was zero-padded.
178 char data_read_2
[32];
179 bytes_read
= file
.Read(0, data_read_2
, static_cast<int>(file_size
));
180 EXPECT_EQ(file_size
, bytes_read
);
181 for (int i
= 0; i
< kTestDataSize
; i
++)
182 EXPECT_EQ(data_to_write
[i
], data_read_2
[i
]);
183 for (int i
= kTestDataSize
; i
< kOffsetBeyondEndOfFile
; i
++)
184 EXPECT_EQ(0, data_read_2
[i
]);
185 for (int i
= kOffsetBeyondEndOfFile
; i
< file_size
; i
++)
186 EXPECT_EQ(data_to_write
[i
- kOffsetBeyondEndOfFile
], data_read_2
[i
]);
190 base::ScopedTempDir temp_dir
;
191 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
192 FilePath file_path
= temp_dir
.path().AppendASCII("append_file");
193 File
file(file_path
, base::File::FLAG_CREATE
| base::File::FLAG_APPEND
);
194 ASSERT_TRUE(file
.IsValid());
196 char data_to_write
[] = "test";
197 const int kTestDataSize
= 4;
199 // Write 0 bytes to the file.
200 int bytes_written
= file
.Write(0, data_to_write
, 0);
201 EXPECT_EQ(0, bytes_written
);
203 // Write "test" to the file.
204 bytes_written
= file
.Write(0, data_to_write
, kTestDataSize
);
205 EXPECT_EQ(kTestDataSize
, bytes_written
);
208 File
file2(file_path
,
209 base::File::FLAG_OPEN
| base::File::FLAG_READ
|
210 base::File::FLAG_APPEND
);
211 ASSERT_TRUE(file2
.IsValid());
213 // Test passing the file around.
215 EXPECT_FALSE(file2
.IsValid());
216 ASSERT_TRUE(file
.IsValid());
218 char append_data_to_write
[] = "78";
219 const int kAppendDataSize
= 2;
221 // Append "78" to the file.
222 bytes_written
= file
.Write(0, append_data_to_write
, kAppendDataSize
);
223 EXPECT_EQ(kAppendDataSize
, bytes_written
);
225 // Read the entire file.
226 char data_read_1
[32];
227 int bytes_read
= file
.Read(0, data_read_1
,
228 kTestDataSize
+ kAppendDataSize
);
229 EXPECT_EQ(kTestDataSize
+ kAppendDataSize
, bytes_read
);
230 for (int i
= 0; i
< kTestDataSize
; i
++)
231 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
232 for (int i
= 0; i
< kAppendDataSize
; i
++)
233 EXPECT_EQ(append_data_to_write
[i
], data_read_1
[kTestDataSize
+ i
]);
238 base::ScopedTempDir temp_dir
;
239 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
240 FilePath file_path
= temp_dir
.path().AppendASCII("truncate_file");
242 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
243 base::File::FLAG_WRITE
);
244 ASSERT_TRUE(file
.IsValid());
245 EXPECT_EQ(0, file
.GetLength());
247 // Write "test" to the file.
248 char data_to_write
[] = "test";
249 int kTestDataSize
= 4;
250 int bytes_written
= file
.Write(0, data_to_write
, kTestDataSize
);
251 EXPECT_EQ(kTestDataSize
, bytes_written
);
254 const int kExtendedFileLength
= 10;
256 EXPECT_TRUE(file
.SetLength(kExtendedFileLength
));
257 EXPECT_EQ(kExtendedFileLength
, file
.GetLength());
258 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
259 EXPECT_EQ(kExtendedFileLength
, file_size
);
261 // Make sure the file was zero-padded.
263 int bytes_read
= file
.Read(0, data_read
, static_cast<int>(file_size
));
264 EXPECT_EQ(file_size
, bytes_read
);
265 for (int i
= 0; i
< kTestDataSize
; i
++)
266 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
267 for (int i
= kTestDataSize
; i
< file_size
; i
++)
268 EXPECT_EQ(0, data_read
[i
]);
270 // Truncate the file.
271 const int kTruncatedFileLength
= 2;
272 EXPECT_TRUE(file
.SetLength(kTruncatedFileLength
));
273 EXPECT_EQ(kTruncatedFileLength
, file
.GetLength());
274 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
275 EXPECT_EQ(kTruncatedFileLength
, file_size
);
277 // Make sure the file was truncated.
278 bytes_read
= file
.Read(0, data_read
, kTestDataSize
);
279 EXPECT_EQ(file_size
, bytes_read
);
280 for (int i
= 0; i
< file_size
; i
++)
281 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
284 // Flakily fails: http://crbug.com/86494
285 #if defined(OS_ANDROID)
286 TEST(File
, TouchGetInfo
) {
288 TEST(File
, DISABLED_TouchGetInfo
) {
290 base::ScopedTempDir temp_dir
;
291 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
292 File
file(temp_dir
.path().AppendASCII("touch_get_info_file"),
293 base::File::FLAG_CREATE
| base::File::FLAG_WRITE
|
294 base::File::FLAG_WRITE_ATTRIBUTES
);
295 ASSERT_TRUE(file
.IsValid());
297 // Get info for a newly created file.
298 base::File::Info info
;
299 EXPECT_TRUE(file
.GetInfo(&info
));
301 // Add 2 seconds to account for possible rounding errors on
302 // filesystems that use a 1s or 2s timestamp granularity.
303 base::Time now
= base::Time::Now() + base::TimeDelta::FromSeconds(2);
304 EXPECT_EQ(0, info
.size
);
305 EXPECT_FALSE(info
.is_directory
);
306 EXPECT_FALSE(info
.is_symbolic_link
);
307 EXPECT_LE(info
.last_accessed
.ToInternalValue(), now
.ToInternalValue());
308 EXPECT_LE(info
.last_modified
.ToInternalValue(), now
.ToInternalValue());
309 EXPECT_LE(info
.creation_time
.ToInternalValue(), now
.ToInternalValue());
310 base::Time creation_time
= info
.creation_time
;
312 // Write "test" to the file.
313 char data
[] = "test";
314 const int kTestDataSize
= 4;
315 int bytes_written
= file
.Write(0, data
, kTestDataSize
);
316 EXPECT_EQ(kTestDataSize
, bytes_written
);
318 // Change the last_accessed and last_modified dates.
319 // It's best to add values that are multiples of 2 (in seconds)
320 // to the current last_accessed and last_modified times, because
321 // FATxx uses a 2s timestamp granularity.
322 base::Time new_last_accessed
=
323 info
.last_accessed
+ base::TimeDelta::FromSeconds(234);
324 base::Time new_last_modified
=
325 info
.last_modified
+ base::TimeDelta::FromMinutes(567);
327 EXPECT_TRUE(file
.SetTimes(new_last_accessed
, new_last_modified
));
329 // Make sure the file info was updated accordingly.
330 EXPECT_TRUE(file
.GetInfo(&info
));
331 EXPECT_EQ(info
.size
, kTestDataSize
);
332 EXPECT_FALSE(info
.is_directory
);
333 EXPECT_FALSE(info
.is_symbolic_link
);
335 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
336 #if defined(OS_POSIX)
337 EXPECT_EQ(info
.last_accessed
.ToTimeVal().tv_sec
,
338 new_last_accessed
.ToTimeVal().tv_sec
);
339 EXPECT_EQ(info
.last_modified
.ToTimeVal().tv_sec
,
340 new_last_modified
.ToTimeVal().tv_sec
);
342 EXPECT_EQ(info
.last_accessed
.ToInternalValue(),
343 new_last_accessed
.ToInternalValue());
344 EXPECT_EQ(info
.last_modified
.ToInternalValue(),
345 new_last_modified
.ToInternalValue());
348 EXPECT_EQ(info
.creation_time
.ToInternalValue(),
349 creation_time
.ToInternalValue());
352 TEST(File
, ReadFileAtCurrentPosition
) {
353 base::ScopedTempDir temp_dir
;
354 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
356 temp_dir
.path().AppendASCII("read_file_at_current_position");
358 base::File::FLAG_CREATE
| base::File::FLAG_READ
|
359 base::File::FLAG_WRITE
);
360 EXPECT_TRUE(file
.IsValid());
362 const char kData
[] = "test";
363 const int kDataSize
= arraysize(kData
) - 1;
364 EXPECT_EQ(kDataSize
, file
.Write(0, kData
, kDataSize
));
366 EXPECT_EQ(0, file
.Seek(base::File::FROM_BEGIN
, 0));
368 char buffer
[kDataSize
];
369 int first_chunk_size
= kDataSize
/ 2;
370 EXPECT_EQ(first_chunk_size
, file
.ReadAtCurrentPos(buffer
, first_chunk_size
));
371 EXPECT_EQ(kDataSize
- first_chunk_size
,
372 file
.ReadAtCurrentPos(buffer
+ first_chunk_size
,
373 kDataSize
- first_chunk_size
));
374 EXPECT_EQ(std::string(buffer
, buffer
+ kDataSize
),
379 TEST(File
, GetInfoForDirectory
) {
380 base::ScopedTempDir temp_dir
;
381 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
382 FilePath empty_dir
= temp_dir
.path().Append(FILE_PATH_LITERAL("gpfi_test"));
383 ASSERT_TRUE(CreateDirectory(empty_dir
));
386 ::CreateFile(empty_dir
.value().c_str(),
388 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
391 FILE_FLAG_BACKUP_SEMANTICS
, // Needed to open a directory.
393 ASSERT_TRUE(dir
.IsValid());
395 base::File::Info info
;
396 EXPECT_TRUE(dir
.GetInfo(&info
));
397 EXPECT_TRUE(info
.is_directory
);
398 EXPECT_FALSE(info
.is_symbolic_link
);
399 EXPECT_EQ(0, info
.size
);
401 #endif // defined(OS_WIN)