1 // Copyright (c) 2011 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/memory/scoped_temp_dir.h"
7 #include "base/platform_file.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 // Reads from a file the given number of bytes, or until EOF is reached.
14 // Returns the number of bytes read.
15 int ReadFully(base::PlatformFile file
, int64 offset
, char* data
, int size
) {
16 int total_bytes_read
= 0;
18 while (total_bytes_read
< size
) {
19 bytes_read
= base::ReadPlatformFile(
20 file
, offset
+ total_bytes_read
, &data
[total_bytes_read
],
21 size
- total_bytes_read
);
23 // If we reached EOF, bytes_read will be 0.
25 return total_bytes_read
;
27 if ((bytes_read
< 0) || (bytes_read
> size
- total_bytes_read
))
30 total_bytes_read
+= bytes_read
;
33 return total_bytes_read
;
36 // Writes the given number of bytes to a file.
37 // Returns the number of bytes written.
38 int WriteFully(base::PlatformFile file
, int64 offset
,
39 const char* data
, int size
) {
40 int total_bytes_written
= 0;
42 while (total_bytes_written
< size
) {
43 bytes_written
= base::WritePlatformFile(
44 file
, offset
+ total_bytes_written
, &data
[total_bytes_written
],
45 size
- total_bytes_written
);
47 if ((bytes_written
== 0) && (size
== 0))
50 if ((bytes_written
<= 0) || (bytes_written
> size
- total_bytes_written
))
53 total_bytes_written
+= bytes_written
;
56 return total_bytes_written
;
61 TEST(PlatformFile
, CreatePlatformFile
) {
62 ScopedTempDir temp_dir
;
63 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
64 FilePath file_path
= temp_dir
.path().AppendASCII("create_file_1");
66 // Open a file that doesn't exist.
67 base::PlatformFileError error_code
= base::PLATFORM_FILE_OK
;
68 base::PlatformFile file
= base::CreatePlatformFile(
69 file_path
, base::PLATFORM_FILE_OPEN
| base::PLATFORM_FILE_READ
,
71 EXPECT_EQ(base::kInvalidPlatformFileValue
, file
);
72 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND
, error_code
);
74 // Open or create a file.
76 error_code
= base::PLATFORM_FILE_OK
;
77 file
= base::CreatePlatformFile(
78 file_path
, base::PLATFORM_FILE_OPEN_ALWAYS
| base::PLATFORM_FILE_READ
,
79 &created
, &error_code
);
80 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
82 EXPECT_EQ(base::PLATFORM_FILE_OK
, error_code
);
83 base::ClosePlatformFile(file
);
85 // Open an existing file.
87 file
= base::CreatePlatformFile(
88 file_path
, base::PLATFORM_FILE_OPEN
| base::PLATFORM_FILE_READ
,
89 &created
, &error_code
);
90 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
91 EXPECT_FALSE(created
);
92 EXPECT_EQ(base::PLATFORM_FILE_OK
, error_code
);
93 base::ClosePlatformFile(file
);
95 // Create a file that exists.
96 file
= base::CreatePlatformFile(
97 file_path
, base::PLATFORM_FILE_CREATE
| base::PLATFORM_FILE_READ
,
98 &created
, &error_code
);
99 EXPECT_EQ(base::kInvalidPlatformFileValue
, file
);
100 EXPECT_FALSE(created
);
101 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS
, error_code
);
103 // Create or overwrite a file.
104 error_code
= base::PLATFORM_FILE_OK
;
105 file
= base::CreatePlatformFile(
106 file_path
, base::PLATFORM_FILE_CREATE_ALWAYS
| base::PLATFORM_FILE_READ
,
107 &created
, &error_code
);
108 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
109 EXPECT_TRUE(created
);
110 EXPECT_EQ(base::PLATFORM_FILE_OK
, error_code
);
111 base::ClosePlatformFile(file
);
113 // Create a delete-on-close file.
115 file_path
= temp_dir
.path().AppendASCII("create_file_2");
116 file
= base::CreatePlatformFile(
118 base::PLATFORM_FILE_OPEN_ALWAYS
|
119 base::PLATFORM_FILE_DELETE_ON_CLOSE
|
120 base::PLATFORM_FILE_READ
,
121 &created
, &error_code
);
122 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
123 EXPECT_TRUE(created
);
124 EXPECT_EQ(base::PLATFORM_FILE_OK
, error_code
);
126 EXPECT_TRUE(base::ClosePlatformFile(file
));
127 EXPECT_FALSE(file_util::PathExists(file_path
));
130 TEST(PlatformFile
, ReadWritePlatformFile
) {
131 ScopedTempDir temp_dir
;
132 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
133 FilePath file_path
= temp_dir
.path().AppendASCII("read_write_file");
134 base::PlatformFile file
= base::CreatePlatformFile(
136 base::PLATFORM_FILE_CREATE
|
137 base::PLATFORM_FILE_READ
|
138 base::PLATFORM_FILE_WRITE
,
140 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
142 char data_to_write
[] = "test";
143 const int kTestDataSize
= 4;
145 // Write 0 bytes to the file.
146 int bytes_written
= WriteFully(file
, 0, data_to_write
, 0);
147 EXPECT_EQ(0, bytes_written
);
149 // Write "test" to the file.
150 bytes_written
= WriteFully(file
, 0, data_to_write
, kTestDataSize
);
151 EXPECT_EQ(kTestDataSize
, bytes_written
);
154 char data_read_1
[32];
155 int bytes_read
= ReadFully(file
, kTestDataSize
, data_read_1
, kTestDataSize
);
156 EXPECT_EQ(0, bytes_read
);
158 // Read from somewhere in the middle of the file.
159 const int kPartialReadOffset
= 1;
160 bytes_read
= ReadFully(file
, kPartialReadOffset
, data_read_1
, kTestDataSize
);
161 EXPECT_EQ(kTestDataSize
- kPartialReadOffset
, bytes_read
);
162 for (int i
= 0; i
< bytes_read
; i
++)
163 EXPECT_EQ(data_to_write
[i
+ kPartialReadOffset
], data_read_1
[i
]);
166 bytes_read
= ReadFully(file
, 0, data_read_1
, 0);
167 EXPECT_EQ(0, bytes_read
);
169 // Read the entire file.
170 bytes_read
= ReadFully(file
, 0, data_read_1
, kTestDataSize
);
171 EXPECT_EQ(kTestDataSize
, bytes_read
);
172 for (int i
= 0; i
< bytes_read
; i
++)
173 EXPECT_EQ(data_to_write
[i
], data_read_1
[i
]);
175 // Write past the end of the file.
176 const int kOffsetBeyondEndOfFile
= 10;
177 const int kPartialWriteLength
= 2;
178 bytes_written
= WriteFully(file
, kOffsetBeyondEndOfFile
,
179 data_to_write
, kPartialWriteLength
);
180 EXPECT_EQ(kPartialWriteLength
, bytes_written
);
182 // Make sure the file was extended.
184 EXPECT_TRUE(file_util::GetFileSize(file_path
, &file_size
));
185 EXPECT_EQ(kOffsetBeyondEndOfFile
+ kPartialWriteLength
, file_size
);
187 // Make sure the file was zero-padded.
188 char data_read_2
[32];
189 bytes_read
= ReadFully(file
, 0, data_read_2
, static_cast<int>(file_size
));
190 EXPECT_EQ(file_size
, bytes_read
);
191 for (int i
= 0; i
< kTestDataSize
; i
++)
192 EXPECT_EQ(data_to_write
[i
], data_read_2
[i
]);
193 for (int i
= kTestDataSize
; i
< kOffsetBeyondEndOfFile
; i
++)
194 EXPECT_EQ(0, data_read_2
[i
]);
195 for (int i
= kOffsetBeyondEndOfFile
; i
< file_size
; i
++)
196 EXPECT_EQ(data_to_write
[i
- kOffsetBeyondEndOfFile
], data_read_2
[i
]);
198 // Close the file handle to allow the temp directory to be deleted.
199 base::ClosePlatformFile(file
);
202 TEST(PlatformFile
, TruncatePlatformFile
) {
203 ScopedTempDir temp_dir
;
204 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
205 FilePath file_path
= temp_dir
.path().AppendASCII("truncate_file");
206 base::PlatformFile file
= base::CreatePlatformFile(
208 base::PLATFORM_FILE_CREATE
|
209 base::PLATFORM_FILE_READ
|
210 base::PLATFORM_FILE_WRITE
,
212 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
214 // Write "test" to the file.
215 char data_to_write
[] = "test";
216 int kTestDataSize
= 4;
217 int bytes_written
= WriteFully(file
, 0, data_to_write
, kTestDataSize
);
218 EXPECT_EQ(kTestDataSize
, bytes_written
);
221 const int kExtendedFileLength
= 10;
223 EXPECT_TRUE(base::TruncatePlatformFile(file
, kExtendedFileLength
));
224 EXPECT_TRUE(file_util::GetFileSize(file_path
, &file_size
));
225 EXPECT_EQ(kExtendedFileLength
, file_size
);
227 // Make sure the file was zero-padded.
229 int bytes_read
= ReadFully(file
, 0, data_read
, static_cast<int>(file_size
));
230 EXPECT_EQ(file_size
, bytes_read
);
231 for (int i
= 0; i
< kTestDataSize
; i
++)
232 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
233 for (int i
= kTestDataSize
; i
< file_size
; i
++)
234 EXPECT_EQ(0, data_read
[i
]);
236 // Truncate the file.
237 const int kTruncatedFileLength
= 2;
238 EXPECT_TRUE(base::TruncatePlatformFile(file
, kTruncatedFileLength
));
239 EXPECT_TRUE(file_util::GetFileSize(file_path
, &file_size
));
240 EXPECT_EQ(kTruncatedFileLength
, file_size
);
242 // Make sure the file was truncated.
243 bytes_read
= ReadFully(file
, 0, data_read
, kTestDataSize
);
244 EXPECT_EQ(file_size
, bytes_read
);
245 for (int i
= 0; i
< file_size
; i
++)
246 EXPECT_EQ(data_to_write
[i
], data_read
[i
]);
248 // Close the file handle to allow the temp directory to be deleted.
249 base::ClosePlatformFile(file
);
252 TEST(PlatformFile
, TouchGetInfoPlatformFile
) {
253 ScopedTempDir temp_dir
;
254 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
255 base::PlatformFile file
= base::CreatePlatformFile(
256 temp_dir
.path().AppendASCII("touch_get_info_file"),
257 base::PLATFORM_FILE_CREATE
|
258 base::PLATFORM_FILE_WRITE
|
259 base::PLATFORM_FILE_WRITE_ATTRIBUTES
,
261 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
263 // Get info for a newly created file.
264 base::PlatformFileInfo info
;
265 EXPECT_TRUE(base::GetPlatformFileInfo(file
, &info
));
267 // Add 2 seconds to account for possible rounding errors on
268 // filesystems that use a 1s or 2s timestamp granularity.
269 base::Time now
= base::Time::Now() + base::TimeDelta::FromSeconds(2);
270 EXPECT_EQ(0, info
.size
);
271 EXPECT_FALSE(info
.is_directory
);
272 EXPECT_FALSE(info
.is_symbolic_link
);
273 EXPECT_LE(info
.last_accessed
.ToInternalValue(), now
.ToInternalValue());
274 EXPECT_LE(info
.last_modified
.ToInternalValue(), now
.ToInternalValue());
275 EXPECT_LE(info
.creation_time
.ToInternalValue(), now
.ToInternalValue());
276 base::Time creation_time
= info
.creation_time
;
278 // Write "test" to the file.
279 char data
[] = "test";
280 const int kTestDataSize
= 4;
281 int bytes_written
= WriteFully(file
, 0, data
, kTestDataSize
);
282 EXPECT_EQ(kTestDataSize
, bytes_written
);
284 // Change the last_accessed and last_modified dates.
285 // It's best to add values that are multiples of 2 (in seconds)
286 // to the current last_accessed and last_modified times, because
287 // FATxx uses a 2s timestamp granularity.
288 base::Time new_last_accessed
=
289 info
.last_accessed
+ base::TimeDelta::FromSeconds(234);
290 base::Time new_last_modified
=
291 info
.last_modified
+ base::TimeDelta::FromMinutes(567);
293 EXPECT_TRUE(base::TouchPlatformFile(file
, new_last_accessed
,
296 // Make sure the file info was updated accordingly.
297 EXPECT_TRUE(base::GetPlatformFileInfo(file
, &info
));
298 EXPECT_EQ(info
.size
, kTestDataSize
);
299 EXPECT_FALSE(info
.is_directory
);
300 EXPECT_FALSE(info
.is_symbolic_link
);
302 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
303 #if defined(OS_POSIX)
304 EXPECT_EQ(info
.last_accessed
.ToTimeVal().tv_sec
,
305 new_last_accessed
.ToTimeVal().tv_sec
);
306 EXPECT_EQ(info
.last_modified
.ToTimeVal().tv_sec
,
307 new_last_modified
.ToTimeVal().tv_sec
);
309 EXPECT_EQ(info
.last_accessed
.ToInternalValue(),
310 new_last_accessed
.ToInternalValue());
311 EXPECT_EQ(info
.last_modified
.ToInternalValue(),
312 new_last_modified
.ToInternalValue());
315 EXPECT_EQ(info
.creation_time
.ToInternalValue(),
316 creation_time
.ToInternalValue());
318 // Close the file handle to allow the temp directory to be deleted.
319 base::ClosePlatformFile(file
);