Roll skia to r1241.
[chromium-blink-merge.git] / base / platform_file_unittest.cc
blobdac29566d911cdd2f8396090f67750e948adf7de
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"
8 #include "base/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 namespace {
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;
17 int bytes_read;
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.
24 if (bytes_read == 0)
25 return total_bytes_read;
27 if ((bytes_read < 0) || (bytes_read > size - total_bytes_read))
28 return -1;
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;
41 int bytes_written;
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))
48 return 0;
50 if ((bytes_written <= 0) || (bytes_written > size - total_bytes_written))
51 return -1;
53 total_bytes_written += bytes_written;
56 return total_bytes_written;
59 } // namespace
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,
70 NULL, &error_code);
71 EXPECT_EQ(base::kInvalidPlatformFileValue, file);
72 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, error_code);
74 // Open or create a file.
75 bool created = false;
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);
81 EXPECT_TRUE(created);
82 EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
83 base::ClosePlatformFile(file);
85 // Open an existing file.
86 created = false;
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.
114 created = false;
115 file_path = temp_dir.path().AppendASCII("create_file_2");
116 file = base::CreatePlatformFile(
117 file_path,
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(
135 file_path,
136 base::PLATFORM_FILE_CREATE |
137 base::PLATFORM_FILE_READ |
138 base::PLATFORM_FILE_WRITE,
139 NULL, NULL);
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);
153 // Read from EOF.
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]);
165 // Read 0 bytes.
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.
183 int64 file_size = 0;
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(
207 file_path,
208 base::PLATFORM_FILE_CREATE |
209 base::PLATFORM_FILE_READ |
210 base::PLATFORM_FILE_WRITE,
211 NULL, NULL);
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);
220 // Extend the file.
221 const int kExtendedFileLength = 10;
222 int64 file_size = 0;
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.
228 char data_read[32];
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,
260 NULL, NULL);
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,
294 new_last_modified));
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);
308 #else
309 EXPECT_EQ(info.last_accessed.ToInternalValue(),
310 new_last_accessed.ToInternalValue());
311 EXPECT_EQ(info.last_modified.ToInternalValue(),
312 new_last_modified.ToInternalValue());
313 #endif
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);