- add sources.
[platform/framework/web/crosswalk.git] / src / base / platform_file_unittest.cc
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.
4
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"
10
11 using base::FilePath;
12
13 namespace {
14
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(base::PlatformFile file, int64 offset, char* data, int size) {
18   return base::ReadPlatformFile(file, offset, data, size);
19 }
20
21 // Writes the given number of bytes to a file.
22 // Returns the number of bytes written.
23 int WriteFully(base::PlatformFile file, int64 offset,
24                const char* data, int size) {
25   return base::WritePlatformFile(file, offset, data, size);
26 }
27
28 } // namespace
29
30 TEST(PlatformFile, CreatePlatformFile) {
31   base::ScopedTempDir temp_dir;
32   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
33   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
34
35   // Open a file that doesn't exist.
36   base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
37   base::PlatformFile file = base::CreatePlatformFile(
38       file_path,
39       base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
40       NULL,
41       &error_code);
42   EXPECT_EQ(base::kInvalidPlatformFileValue, file);
43   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, error_code);
44
45   // Open or create a file.
46   bool created = false;
47   error_code = base::PLATFORM_FILE_OK;
48   file = base::CreatePlatformFile(
49       file_path,
50       base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ,
51       &created,
52       &error_code);
53   EXPECT_NE(base::kInvalidPlatformFileValue, file);
54   EXPECT_TRUE(created);
55   EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
56   base::ClosePlatformFile(file);
57
58   // Open an existing file.
59   created = false;
60   file = base::CreatePlatformFile(
61       file_path,
62       base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
63       &created,
64       &error_code);
65   EXPECT_NE(base::kInvalidPlatformFileValue, file);
66   EXPECT_FALSE(created);
67   EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
68   base::ClosePlatformFile(file);
69
70   // Create a file that exists.
71   file = base::CreatePlatformFile(
72       file_path,
73       base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ,
74       &created,
75       &error_code);
76   EXPECT_EQ(base::kInvalidPlatformFileValue, file);
77   EXPECT_FALSE(created);
78   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, error_code);
79
80   // Create or overwrite a file.
81   error_code = base::PLATFORM_FILE_OK;
82   file = base::CreatePlatformFile(
83       file_path,
84       base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ,
85       &created,
86       &error_code);
87   EXPECT_NE(base::kInvalidPlatformFileValue, file);
88   EXPECT_TRUE(created);
89   EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
90   base::ClosePlatformFile(file);
91
92   // Create a delete-on-close file.
93   created = false;
94   file_path = temp_dir.path().AppendASCII("create_file_2");
95   file = base::CreatePlatformFile(
96       file_path,
97       base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_DELETE_ON_CLOSE |
98           base::PLATFORM_FILE_READ,
99       &created,
100       &error_code);
101   EXPECT_NE(base::kInvalidPlatformFileValue, file);
102   EXPECT_TRUE(created);
103   EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
104
105   EXPECT_TRUE(base::ClosePlatformFile(file));
106   EXPECT_FALSE(base::PathExists(file_path));
107 }
108
109 TEST(PlatformFile, DeleteOpenFile) {
110   base::ScopedTempDir temp_dir;
111   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
112   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
113
114   // Create a file.
115   bool created = false;
116   base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
117   base::PlatformFile file = base::CreatePlatformFile(
118       file_path,
119       base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ |
120           base::PLATFORM_FILE_SHARE_DELETE,
121       &created,
122       &error_code);
123   EXPECT_NE(base::kInvalidPlatformFileValue, file);
124   EXPECT_TRUE(created);
125   EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
126
127   // Open an existing file and mark it as delete on close.
128   created = false;
129   base::PlatformFile same_file = base::CreatePlatformFile(
130       file_path,
131       base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_DELETE_ON_CLOSE |
132           base::PLATFORM_FILE_READ,
133       &created,
134       &error_code);
135   EXPECT_NE(base::kInvalidPlatformFileValue, file);
136   EXPECT_FALSE(created);
137   EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
138
139   // Close both handles and check that the file is gone.
140   base::ClosePlatformFile(file);
141   base::ClosePlatformFile(same_file);
142   EXPECT_FALSE(base::PathExists(file_path));
143 }
144
145 TEST(PlatformFile, ReadWritePlatformFile) {
146   base::ScopedTempDir temp_dir;
147   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
148   FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
149   base::PlatformFile file = base::CreatePlatformFile(
150       file_path,
151       base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ |
152           base::PLATFORM_FILE_WRITE,
153       NULL,
154       NULL);
155   EXPECT_NE(base::kInvalidPlatformFileValue, file);
156
157   char data_to_write[] = "test";
158   const int kTestDataSize = 4;
159
160   // Write 0 bytes to the file.
161   int bytes_written = WriteFully(file, 0, data_to_write, 0);
162   EXPECT_EQ(0, bytes_written);
163
164   // Write "test" to the file.
165   bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
166   EXPECT_EQ(kTestDataSize, bytes_written);
167
168   // Read from EOF.
169   char data_read_1[32];
170   int bytes_read = ReadFully(file, kTestDataSize, data_read_1, kTestDataSize);
171   EXPECT_EQ(0, bytes_read);
172
173   // Read from somewhere in the middle of the file.
174   const int kPartialReadOffset = 1;
175   bytes_read = ReadFully(file, kPartialReadOffset, data_read_1, kTestDataSize);
176   EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
177   for (int i = 0; i < bytes_read; i++)
178     EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
179
180   // Read 0 bytes.
181   bytes_read = ReadFully(file, 0, data_read_1, 0);
182   EXPECT_EQ(0, bytes_read);
183
184   // Read the entire file.
185   bytes_read = ReadFully(file, 0, data_read_1, kTestDataSize);
186   EXPECT_EQ(kTestDataSize, bytes_read);
187   for (int i = 0; i < bytes_read; i++)
188     EXPECT_EQ(data_to_write[i], data_read_1[i]);
189
190   // Read again, but using the trivial native wrapper.
191   bytes_read = base::ReadPlatformFileNoBestEffort(file, 0, data_read_1,
192                                                   kTestDataSize);
193   EXPECT_LE(bytes_read, kTestDataSize);
194   for (int i = 0; i < bytes_read; i++)
195     EXPECT_EQ(data_to_write[i], data_read_1[i]);
196
197   // Write past the end of the file.
198   const int kOffsetBeyondEndOfFile = 10;
199   const int kPartialWriteLength = 2;
200   bytes_written = WriteFully(file, kOffsetBeyondEndOfFile,
201                              data_to_write, kPartialWriteLength);
202   EXPECT_EQ(kPartialWriteLength, bytes_written);
203
204   // Make sure the file was extended.
205   int64 file_size = 0;
206   EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
207   EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
208
209   // Make sure the file was zero-padded.
210   char data_read_2[32];
211   bytes_read = ReadFully(file, 0, data_read_2, static_cast<int>(file_size));
212   EXPECT_EQ(file_size, bytes_read);
213   for (int i = 0; i < kTestDataSize; i++)
214     EXPECT_EQ(data_to_write[i], data_read_2[i]);
215   for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
216     EXPECT_EQ(0, data_read_2[i]);
217   for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
218     EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
219
220   // Close the file handle to allow the temp directory to be deleted.
221   base::ClosePlatformFile(file);
222 }
223
224 TEST(PlatformFile, AppendPlatformFile) {
225   base::ScopedTempDir temp_dir;
226   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
227   FilePath file_path = temp_dir.path().AppendASCII("append_file");
228   base::PlatformFile file = base::CreatePlatformFile(
229       file_path,
230       base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_APPEND,
231       NULL,
232       NULL);
233   EXPECT_NE(base::kInvalidPlatformFileValue, file);
234
235   char data_to_write[] = "test";
236   const int kTestDataSize = 4;
237
238   // Write 0 bytes to the file.
239   int bytes_written = WriteFully(file, 0, data_to_write, 0);
240   EXPECT_EQ(0, bytes_written);
241
242   // Write "test" to the file.
243   bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
244   EXPECT_EQ(kTestDataSize, bytes_written);
245
246   base::ClosePlatformFile(file);
247   file = base::CreatePlatformFile(
248       file_path,
249       base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ |
250           base::PLATFORM_FILE_APPEND,
251       NULL,
252       NULL);
253   EXPECT_NE(base::kInvalidPlatformFileValue, file);
254
255   char append_data_to_write[] = "78";
256   const int kAppendDataSize = 2;
257
258   // Append "78" to the file.
259   bytes_written = WriteFully(file, 0, append_data_to_write, kAppendDataSize);
260   EXPECT_EQ(kAppendDataSize, bytes_written);
261
262   // Read the entire file.
263   char data_read_1[32];
264   int bytes_read = ReadFully(file, 0, data_read_1,
265                              kTestDataSize + kAppendDataSize);
266   EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
267   for (int i = 0; i < kTestDataSize; i++)
268     EXPECT_EQ(data_to_write[i], data_read_1[i]);
269   for (int i = 0; i < kAppendDataSize; i++)
270     EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
271
272   // Close the file handle to allow the temp directory to be deleted.
273   base::ClosePlatformFile(file);
274 }
275
276
277 TEST(PlatformFile, TruncatePlatformFile) {
278   base::ScopedTempDir temp_dir;
279   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
280   FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
281   base::PlatformFile file = base::CreatePlatformFile(
282       file_path,
283       base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ |
284           base::PLATFORM_FILE_WRITE,
285       NULL,
286       NULL);
287   EXPECT_NE(base::kInvalidPlatformFileValue, file);
288
289   // Write "test" to the file.
290   char data_to_write[] = "test";
291   int kTestDataSize = 4;
292   int bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
293   EXPECT_EQ(kTestDataSize, bytes_written);
294
295   // Extend the file.
296   const int kExtendedFileLength = 10;
297   int64 file_size = 0;
298   EXPECT_TRUE(base::TruncatePlatformFile(file, kExtendedFileLength));
299   EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
300   EXPECT_EQ(kExtendedFileLength, file_size);
301
302   // Make sure the file was zero-padded.
303   char data_read[32];
304   int bytes_read = ReadFully(file, 0, data_read, static_cast<int>(file_size));
305   EXPECT_EQ(file_size, bytes_read);
306   for (int i = 0; i < kTestDataSize; i++)
307     EXPECT_EQ(data_to_write[i], data_read[i]);
308   for (int i = kTestDataSize; i < file_size; i++)
309     EXPECT_EQ(0, data_read[i]);
310
311   // Truncate the file.
312   const int kTruncatedFileLength = 2;
313   EXPECT_TRUE(base::TruncatePlatformFile(file, kTruncatedFileLength));
314   EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
315   EXPECT_EQ(kTruncatedFileLength, file_size);
316
317   // Make sure the file was truncated.
318   bytes_read = ReadFully(file, 0, data_read, kTestDataSize);
319   EXPECT_EQ(file_size, bytes_read);
320   for (int i = 0; i < file_size; i++)
321     EXPECT_EQ(data_to_write[i], data_read[i]);
322
323   // Close the file handle to allow the temp directory to be deleted.
324   base::ClosePlatformFile(file);
325 }
326
327 // Flakily fails: http://crbug.com/86494
328 #if defined(OS_ANDROID)
329 TEST(PlatformFile, TouchGetInfoPlatformFile) {
330 #else
331 TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) {
332 #endif
333   base::ScopedTempDir temp_dir;
334   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
335   base::PlatformFile file = base::CreatePlatformFile(
336       temp_dir.path().AppendASCII("touch_get_info_file"),
337       base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE |
338           base::PLATFORM_FILE_WRITE_ATTRIBUTES,
339       NULL,
340       NULL);
341   EXPECT_NE(base::kInvalidPlatformFileValue, file);
342
343   // Get info for a newly created file.
344   base::PlatformFileInfo info;
345   EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
346
347   // Add 2 seconds to account for possible rounding errors on
348   // filesystems that use a 1s or 2s timestamp granularity.
349   base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
350   EXPECT_EQ(0, info.size);
351   EXPECT_FALSE(info.is_directory);
352   EXPECT_FALSE(info.is_symbolic_link);
353   EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
354   EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
355   EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
356   base::Time creation_time = info.creation_time;
357
358   // Write "test" to the file.
359   char data[] = "test";
360   const int kTestDataSize = 4;
361   int bytes_written = WriteFully(file, 0, data, kTestDataSize);
362   EXPECT_EQ(kTestDataSize, bytes_written);
363
364   // Change the last_accessed and last_modified dates.
365   // It's best to add values that are multiples of 2 (in seconds)
366   // to the current last_accessed and last_modified times, because
367   // FATxx uses a 2s timestamp granularity.
368   base::Time new_last_accessed =
369       info.last_accessed + base::TimeDelta::FromSeconds(234);
370   base::Time new_last_modified =
371       info.last_modified + base::TimeDelta::FromMinutes(567);
372
373   EXPECT_TRUE(base::TouchPlatformFile(file, new_last_accessed,
374                                       new_last_modified));
375
376   // Make sure the file info was updated accordingly.
377   EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
378   EXPECT_EQ(info.size, kTestDataSize);
379   EXPECT_FALSE(info.is_directory);
380   EXPECT_FALSE(info.is_symbolic_link);
381
382   // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
383 #if defined(OS_POSIX)
384   EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
385             new_last_accessed.ToTimeVal().tv_sec);
386   EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
387             new_last_modified.ToTimeVal().tv_sec);
388 #else
389   EXPECT_EQ(info.last_accessed.ToInternalValue(),
390             new_last_accessed.ToInternalValue());
391   EXPECT_EQ(info.last_modified.ToInternalValue(),
392             new_last_modified.ToInternalValue());
393 #endif
394
395   EXPECT_EQ(info.creation_time.ToInternalValue(),
396             creation_time.ToInternalValue());
397
398   // Close the file handle to allow the temp directory to be deleted.
399   base::ClosePlatformFile(file);
400 }