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/scoped_temp_dir.h"
7 #include "base/platform_file.h"
8 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
15 // Reads from a file the given number of bytes, or until EOF is reached.
16 // Returns the number of bytes read.
17 int ReadFully(PlatformFile file
, int64 offset
, char* data
, int size
) {
18 return ReadPlatformFile(file
, offset
, data
, size
);
21 // Writes the given number of bytes to a file.
22 // Returns the number of bytes written.
23 int WriteFully(PlatformFile file
, int64 offset
,
24 const char* data
, int size
) {
25 return WritePlatformFile(file
, offset
, data
, size
);
28 PlatformFile
CreatePlatformFile(const FilePath
& path
,
31 PlatformFileError
* error
) {
32 File
file(path
, flags
);
33 if (!file
.IsValid()) {
35 *error
= static_cast<PlatformFileError
>(file
.error_details());
36 return kInvalidPlatformFileValue
;
40 *created
= file
.created();
43 *error
= PLATFORM_FILE_OK
;
45 return file
.TakePlatformFile();
50 TEST(PlatformFile
, CreatePlatformFile
) {
51 ScopedTempDir temp_dir
;
52 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
53 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
55 // Open a file that doesn't exist.
56 PlatformFileError error_code
= PLATFORM_FILE_OK
;
57 PlatformFile file
= CreatePlatformFile(
59 PLATFORM_FILE_OPEN
| PLATFORM_FILE_READ
,
62 EXPECT_EQ(kInvalidPlatformFileValue
, file
);
63 EXPECT_EQ(PLATFORM_FILE_ERROR_NOT_FOUND
, error_code
);
65 // Open or create a file.
67 error_code
= PLATFORM_FILE_OK
;
68 file
= CreatePlatformFile(
70 PLATFORM_FILE_OPEN_ALWAYS
| PLATFORM_FILE_READ
,
73 EXPECT_NE(kInvalidPlatformFileValue
, file
);
75 EXPECT_EQ(PLATFORM_FILE_OK
, error_code
);
76 ClosePlatformFile(file
);
78 // Open an existing file.
80 file
= CreatePlatformFile(
82 PLATFORM_FILE_OPEN
| PLATFORM_FILE_READ
,
85 EXPECT_NE(kInvalidPlatformFileValue
, file
);
86 EXPECT_FALSE(created
);
87 EXPECT_EQ(PLATFORM_FILE_OK
, error_code
);
88 ClosePlatformFile(file
);
90 // Create a file that exists.
91 file
= CreatePlatformFile(
93 PLATFORM_FILE_CREATE
| PLATFORM_FILE_READ
,
96 EXPECT_EQ(kInvalidPlatformFileValue
, file
);
97 EXPECT_FALSE(created
);
98 EXPECT_EQ(PLATFORM_FILE_ERROR_EXISTS
, error_code
);
100 // Create or overwrite a file.
101 error_code
= PLATFORM_FILE_OK
;
102 file
= CreatePlatformFile(
104 PLATFORM_FILE_CREATE_ALWAYS
| PLATFORM_FILE_READ
,
107 EXPECT_NE(kInvalidPlatformFileValue
, file
);
108 EXPECT_TRUE(created
);
109 EXPECT_EQ(PLATFORM_FILE_OK
, error_code
);
110 ClosePlatformFile(file
);
112 // Create a delete-on-close file.
114 file_path
= temp_dir
.path().AppendASCII("create_file_2");
115 file
= CreatePlatformFile(
117 PLATFORM_FILE_OPEN_ALWAYS
| PLATFORM_FILE_DELETE_ON_CLOSE
|
121 EXPECT_NE(kInvalidPlatformFileValue
, file
);
122 EXPECT_TRUE(created
);
123 EXPECT_EQ(PLATFORM_FILE_OK
, error_code
);
125 EXPECT_TRUE(ClosePlatformFile(file
));
126 EXPECT_FALSE(PathExists(file_path
));
129 TEST(PlatformFile
, DeleteOpenFile
) {
130 ScopedTempDir temp_dir
;
131 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
132 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
135 bool created
= false;
136 PlatformFileError error_code
= PLATFORM_FILE_OK
;
137 PlatformFile file
= CreatePlatformFile(
139 PLATFORM_FILE_OPEN_ALWAYS
| PLATFORM_FILE_READ
|
140 PLATFORM_FILE_SHARE_DELETE
,
143 EXPECT_NE(kInvalidPlatformFileValue
, file
);
144 EXPECT_TRUE(created
);
145 EXPECT_EQ(PLATFORM_FILE_OK
, error_code
);
147 // Open an existing file and mark it as delete on close.
149 PlatformFile same_file
= CreatePlatformFile(
151 PLATFORM_FILE_OPEN
| PLATFORM_FILE_DELETE_ON_CLOSE
|
155 EXPECT_NE(kInvalidPlatformFileValue
, file
);
156 EXPECT_FALSE(created
);
157 EXPECT_EQ(PLATFORM_FILE_OK
, error_code
);
159 // Close both handles and check that the file is gone.
160 ClosePlatformFile(file
);
161 ClosePlatformFile(same_file
);
162 EXPECT_FALSE(PathExists(file_path
));
165 TEST(PlatformFile
, ReadWritePlatformFile
) {
166 ScopedTempDir temp_dir
;
167 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
168 FilePath file_path
= temp_dir
.path().AppendASCII("read_write_file");
169 PlatformFile file
= CreatePlatformFile(
171 PLATFORM_FILE_CREATE
| PLATFORM_FILE_READ
|
175 EXPECT_NE(kInvalidPlatformFileValue
, file
);
177 char data_to_write
[] = "test";
178 const int kTestDataSize
= 4;
180 // Write 0 bytes to the file.
181 int bytes_written
= WriteFully(file
, 0, data_to_write
, 0);
182 EXPECT_EQ(0, bytes_written
);
184 // Write "test" to the file.
185 bytes_written
= WriteFully(file
, 0, data_to_write
, kTestDataSize
);
186 EXPECT_EQ(kTestDataSize
, bytes_written
);
189 char data_read_1
[32];
190 int bytes_read
= ReadFully(file
, kTestDataSize
, data_read_1
, kTestDataSize
);
191 EXPECT_EQ(0, bytes_read
);
193 // Read from somewhere in the middle of the file.
194 const int kPartialReadOffset
= 1;
195 bytes_read
= ReadFully(file
, kPartialReadOffset
, data_read_1
, kTestDataSize
);
196 EXPECT_EQ(kTestDataSize
- kPartialReadOffset
, bytes_read
);
197 for (int i
= 0; i
< bytes_read
; i
++)
198 EXPECT_EQ(data_to_write
[i
+ kPartialReadOffset
], data_read_1
[i
]);
201 bytes_read
= ReadFully(file
, 0, data_read_1
, 0);
202 EXPECT_EQ(0, bytes_read
);
204 // Read the entire file.
205 bytes_read
= ReadFully(file
, 0, data_read_1
, kTestDataSize
);
206 EXPECT_EQ(kTestDataSize
, bytes_read
);
207 for (int i
= 0; i
< bytes_read
; i
++)
208 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
210 // Read again, but using the trivial native wrapper.
211 bytes_read
= ReadPlatformFileNoBestEffort(file
, 0, data_read_1
,
213 EXPECT_LE(bytes_read
, kTestDataSize
);
214 for (int i
= 0; i
< bytes_read
; i
++)
215 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
217 // Write past the end of the file.
218 const int kOffsetBeyondEndOfFile
= 10;
219 const int kPartialWriteLength
= 2;
220 bytes_written
= WriteFully(file
, kOffsetBeyondEndOfFile
,
221 data_to_write
, kPartialWriteLength
);
222 EXPECT_EQ(kPartialWriteLength
, bytes_written
);
224 // Make sure the file was extended.
226 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
227 EXPECT_EQ(kOffsetBeyondEndOfFile
+ kPartialWriteLength
, file_size
);
229 // Make sure the file was zero-padded.
230 char data_read_2
[32];
231 bytes_read
= ReadFully(file
, 0, data_read_2
, static_cast<int>(file_size
));
232 EXPECT_EQ(file_size
, bytes_read
);
233 for (int i
= 0; i
< kTestDataSize
; i
++)
234 EXPECT_EQ(data_to_write
[i
], data_read_2
[i
]);
235 for (int i
= kTestDataSize
; i
< kOffsetBeyondEndOfFile
; i
++)
236 EXPECT_EQ(0, data_read_2
[i
]);
237 for (int i
= kOffsetBeyondEndOfFile
; i
< file_size
; i
++)
238 EXPECT_EQ(data_to_write
[i
- kOffsetBeyondEndOfFile
], data_read_2
[i
]);
240 // Close the file handle to allow the temp directory to be deleted.
241 ClosePlatformFile(file
);
244 TEST(PlatformFile
, AppendPlatformFile
) {
245 ScopedTempDir temp_dir
;
246 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
247 FilePath file_path
= temp_dir
.path().AppendASCII("append_file");
248 PlatformFile file
= CreatePlatformFile(
250 PLATFORM_FILE_CREATE
| PLATFORM_FILE_APPEND
,
253 EXPECT_NE(kInvalidPlatformFileValue
, file
);
255 char data_to_write
[] = "test";
256 const int kTestDataSize
= 4;
258 // Write 0 bytes to the file.
259 int bytes_written
= WriteFully(file
, 0, data_to_write
, 0);
260 EXPECT_EQ(0, bytes_written
);
262 // Write "test" to the file.
263 bytes_written
= WriteFully(file
, 0, data_to_write
, kTestDataSize
);
264 EXPECT_EQ(kTestDataSize
, bytes_written
);
266 ClosePlatformFile(file
);
267 file
= CreatePlatformFile(
269 PLATFORM_FILE_OPEN
| PLATFORM_FILE_READ
|
270 PLATFORM_FILE_APPEND
,
273 EXPECT_NE(kInvalidPlatformFileValue
, file
);
275 char append_data_to_write
[] = "78";
276 const int kAppendDataSize
= 2;
278 // Append "78" to the file.
279 bytes_written
= WriteFully(file
, 0, append_data_to_write
, kAppendDataSize
);
280 EXPECT_EQ(kAppendDataSize
, bytes_written
);
282 // Read the entire file.
283 char data_read_1
[32];
284 int bytes_read
= ReadFully(file
, 0, data_read_1
,
285 kTestDataSize
+ kAppendDataSize
);
286 EXPECT_EQ(kTestDataSize
+ kAppendDataSize
, bytes_read
);
287 for (int i
= 0; i
< kTestDataSize
; i
++)
288 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
289 for (int i
= 0; i
< kAppendDataSize
; i
++)
290 EXPECT_EQ(append_data_to_write
[i
], data_read_1
[kTestDataSize
+ i
]);
292 // Close the file handle to allow the temp directory to be deleted.
293 ClosePlatformFile(file
);
297 TEST(PlatformFile
, TruncatePlatformFile
) {
298 ScopedTempDir temp_dir
;
299 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
300 FilePath file_path
= temp_dir
.path().AppendASCII("truncate_file");
301 PlatformFile file
= CreatePlatformFile(
303 PLATFORM_FILE_CREATE
| PLATFORM_FILE_READ
|
307 EXPECT_NE(kInvalidPlatformFileValue
, file
);
309 // Write "test" to the file.
310 char data_to_write
[] = "test";
311 int kTestDataSize
= 4;
312 int bytes_written
= WriteFully(file
, 0, data_to_write
, kTestDataSize
);
313 EXPECT_EQ(kTestDataSize
, bytes_written
);
316 const int kExtendedFileLength
= 10;
318 EXPECT_TRUE(TruncatePlatformFile(file
, kExtendedFileLength
));
319 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
320 EXPECT_EQ(kExtendedFileLength
, file_size
);
322 // Make sure the file was zero-padded.
324 int bytes_read
= ReadFully(file
, 0, data_read
, static_cast<int>(file_size
));
325 EXPECT_EQ(file_size
, bytes_read
);
326 for (int i
= 0; i
< kTestDataSize
; i
++)
327 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
328 for (int i
= kTestDataSize
; i
< file_size
; i
++)
329 EXPECT_EQ(0, data_read
[i
]);
331 // Truncate the file.
332 const int kTruncatedFileLength
= 2;
333 EXPECT_TRUE(TruncatePlatformFile(file
, kTruncatedFileLength
));
334 EXPECT_TRUE(GetFileSize(file_path
, &file_size
));
335 EXPECT_EQ(kTruncatedFileLength
, file_size
);
337 // Make sure the file was truncated.
338 bytes_read
= ReadFully(file
, 0, data_read
, kTestDataSize
);
339 EXPECT_EQ(file_size
, bytes_read
);
340 for (int i
= 0; i
< file_size
; i
++)
341 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
343 // Close the file handle to allow the temp directory to be deleted.
344 ClosePlatformFile(file
);
347 // Flakily fails: http://crbug.com/86494
348 #if defined(OS_ANDROID)
349 TEST(PlatformFile
, TouchGetInfoPlatformFile
) {
351 TEST(PlatformFile
, DISABLED_TouchGetInfoPlatformFile
) {
353 ScopedTempDir temp_dir
;
354 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
355 PlatformFile file
= CreatePlatformFile(
356 temp_dir
.path().AppendASCII("touch_get_info_file"),
357 PLATFORM_FILE_CREATE
| PLATFORM_FILE_WRITE
|
358 PLATFORM_FILE_WRITE_ATTRIBUTES
,
361 EXPECT_NE(kInvalidPlatformFileValue
, file
);
363 // Get info for a newly created file.
364 PlatformFileInfo info
;
365 EXPECT_TRUE(GetPlatformFileInfo(file
, &info
));
367 // Add 2 seconds to account for possible rounding errors on
368 // filesystems that use a 1s or 2s timestamp granularity.
369 Time now
= Time::Now() + TimeDelta::FromSeconds(2);
370 EXPECT_EQ(0, info
.size
);
371 EXPECT_FALSE(info
.is_directory
);
372 EXPECT_FALSE(info
.is_symbolic_link
);
373 EXPECT_LE(info
.last_accessed
.ToInternalValue(), now
.ToInternalValue());
374 EXPECT_LE(info
.last_modified
.ToInternalValue(), now
.ToInternalValue());
375 EXPECT_LE(info
.creation_time
.ToInternalValue(), now
.ToInternalValue());
376 Time creation_time
= info
.creation_time
;
378 // Write "test" to the file.
379 char data
[] = "test";
380 const int kTestDataSize
= 4;
381 int bytes_written
= WriteFully(file
, 0, data
, kTestDataSize
);
382 EXPECT_EQ(kTestDataSize
, bytes_written
);
384 // Change the last_accessed and last_modified dates.
385 // It's best to add values that are multiples of 2 (in seconds)
386 // to the current last_accessed and last_modified times, because
387 // FATxx uses a 2s timestamp granularity.
388 Time new_last_accessed
=
389 info
.last_accessed
+ TimeDelta::FromSeconds(234);
390 Time new_last_modified
=
391 info
.last_modified
+ TimeDelta::FromMinutes(567);
393 EXPECT_TRUE(TouchPlatformFile(file
, new_last_accessed
, new_last_modified
));
395 // Make sure the file info was updated accordingly.
396 EXPECT_TRUE(GetPlatformFileInfo(file
, &info
));
397 EXPECT_EQ(info
.size
, kTestDataSize
);
398 EXPECT_FALSE(info
.is_directory
);
399 EXPECT_FALSE(info
.is_symbolic_link
);
401 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
402 #if defined(OS_POSIX)
403 EXPECT_EQ(info
.last_accessed
.ToTimeVal().tv_sec
,
404 new_last_accessed
.ToTimeVal().tv_sec
);
405 EXPECT_EQ(info
.last_modified
.ToTimeVal().tv_sec
,
406 new_last_modified
.ToTimeVal().tv_sec
);
408 EXPECT_EQ(info
.last_accessed
.ToInternalValue(),
409 new_last_accessed
.ToInternalValue());
410 EXPECT_EQ(info
.last_modified
.ToInternalValue(),
411 new_last_modified
.ToInternalValue());
414 EXPECT_EQ(info
.creation_time
.ToInternalValue(),
415 creation_time
.ToInternalValue());
417 // Close the file handle to allow the temp directory to be deleted.
418 ClosePlatformFile(file
);
421 TEST(PlatformFile
, ReadFileAtCurrentPosition
) {
422 ScopedTempDir temp_dir
;
423 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
425 temp_dir
.path().AppendASCII("read_file_at_current_position");
426 PlatformFile file
= CreatePlatformFile(
428 PLATFORM_FILE_CREATE
| PLATFORM_FILE_READ
|
431 EXPECT_NE(kInvalidPlatformFileValue
, file
);
433 const char kData
[] = "test";
434 const int kDataSize
= arraysize(kData
) - 1;
435 EXPECT_EQ(kDataSize
, WriteFully(file
, 0, kData
, kDataSize
));
437 EXPECT_EQ(0, SeekPlatformFile(file
, PLATFORM_FILE_FROM_BEGIN
, 0));
439 char buffer
[kDataSize
];
440 int first_chunk_size
= kDataSize
/ 2;
441 EXPECT_EQ(first_chunk_size
,
442 ReadPlatformFileAtCurrentPos(
443 file
, buffer
, first_chunk_size
));
444 EXPECT_EQ(kDataSize
- first_chunk_size
,
445 ReadPlatformFileAtCurrentPos(
446 file
, buffer
+ first_chunk_size
,
447 kDataSize
- first_chunk_size
));
448 EXPECT_EQ(std::string(buffer
, buffer
+ kDataSize
),
451 ClosePlatformFile(file
);