Upstream version 8.37.180.0
[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 namespace base {
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(PlatformFile file, int64 offset, char* data, int size) {
18   return 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(PlatformFile file, int64 offset,
24                const char* data, int size) {
25   return WritePlatformFile(file, offset, data, size);
26 }
27
28 PlatformFile CreatePlatformFile(const FilePath& path,
29                                 int flags,
30                                 bool* created,
31                                 PlatformFileError* error) {
32   File file(path, flags);
33   if (!file.IsValid()) {
34     if (error)
35       *error = static_cast<PlatformFileError>(file.error_details());
36     return kInvalidPlatformFileValue;
37   }
38
39   if (created)
40     *created = file.created();
41
42   if (error)
43     *error = PLATFORM_FILE_OK;
44
45   return file.TakePlatformFile();
46 }
47
48 } // namespace
49
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");
54
55   // Open a file that doesn't exist.
56   PlatformFileError error_code = PLATFORM_FILE_OK;
57   PlatformFile file = CreatePlatformFile(
58       file_path,
59       PLATFORM_FILE_OPEN | PLATFORM_FILE_READ,
60       NULL,
61       &error_code);
62   EXPECT_EQ(kInvalidPlatformFileValue, file);
63   EXPECT_EQ(PLATFORM_FILE_ERROR_NOT_FOUND, error_code);
64
65   // Open or create a file.
66   bool created = false;
67   error_code = PLATFORM_FILE_OK;
68   file = CreatePlatformFile(
69       file_path,
70       PLATFORM_FILE_OPEN_ALWAYS | PLATFORM_FILE_READ,
71       &created,
72       &error_code);
73   EXPECT_NE(kInvalidPlatformFileValue, file);
74   EXPECT_TRUE(created);
75   EXPECT_EQ(PLATFORM_FILE_OK, error_code);
76   ClosePlatformFile(file);
77
78   // Open an existing file.
79   created = false;
80   file = CreatePlatformFile(
81       file_path,
82       PLATFORM_FILE_OPEN | PLATFORM_FILE_READ,
83       &created,
84       &error_code);
85   EXPECT_NE(kInvalidPlatformFileValue, file);
86   EXPECT_FALSE(created);
87   EXPECT_EQ(PLATFORM_FILE_OK, error_code);
88   ClosePlatformFile(file);
89
90   // Create a file that exists.
91   file = CreatePlatformFile(
92       file_path,
93       PLATFORM_FILE_CREATE | PLATFORM_FILE_READ,
94       &created,
95       &error_code);
96   EXPECT_EQ(kInvalidPlatformFileValue, file);
97   EXPECT_FALSE(created);
98   EXPECT_EQ(PLATFORM_FILE_ERROR_EXISTS, error_code);
99
100   // Create or overwrite a file.
101   error_code = PLATFORM_FILE_OK;
102   file = CreatePlatformFile(
103       file_path,
104       PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_WRITE,
105       &created,
106       &error_code);
107   EXPECT_NE(kInvalidPlatformFileValue, file);
108   EXPECT_TRUE(created);
109   EXPECT_EQ(PLATFORM_FILE_OK, error_code);
110   ClosePlatformFile(file);
111
112   // Create a delete-on-close file.
113   created = false;
114   file_path = temp_dir.path().AppendASCII("create_file_2");
115   file = CreatePlatformFile(
116       file_path,
117       PLATFORM_FILE_OPEN_ALWAYS | PLATFORM_FILE_DELETE_ON_CLOSE |
118           PLATFORM_FILE_READ,
119       &created,
120       &error_code);
121   EXPECT_NE(kInvalidPlatformFileValue, file);
122   EXPECT_TRUE(created);
123   EXPECT_EQ(PLATFORM_FILE_OK, error_code);
124
125   EXPECT_TRUE(ClosePlatformFile(file));
126   EXPECT_FALSE(PathExists(file_path));
127 }
128
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");
133
134   // Create a file.
135   bool created = false;
136   PlatformFileError error_code = PLATFORM_FILE_OK;
137   PlatformFile file = CreatePlatformFile(
138       file_path,
139       PLATFORM_FILE_OPEN_ALWAYS | PLATFORM_FILE_READ |
140           PLATFORM_FILE_SHARE_DELETE,
141       &created,
142       &error_code);
143   EXPECT_NE(kInvalidPlatformFileValue, file);
144   EXPECT_TRUE(created);
145   EXPECT_EQ(PLATFORM_FILE_OK, error_code);
146
147   // Open an existing file and mark it as delete on close.
148   created = false;
149   PlatformFile same_file = CreatePlatformFile(
150       file_path,
151       PLATFORM_FILE_OPEN | PLATFORM_FILE_DELETE_ON_CLOSE |
152           PLATFORM_FILE_READ,
153       &created,
154       &error_code);
155   EXPECT_NE(kInvalidPlatformFileValue, file);
156   EXPECT_FALSE(created);
157   EXPECT_EQ(PLATFORM_FILE_OK, error_code);
158
159   // Close both handles and check that the file is gone.
160   ClosePlatformFile(file);
161   ClosePlatformFile(same_file);
162   EXPECT_FALSE(PathExists(file_path));
163 }
164
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(
170       file_path,
171       PLATFORM_FILE_CREATE | PLATFORM_FILE_READ |
172           PLATFORM_FILE_WRITE,
173       NULL,
174       NULL);
175   EXPECT_NE(kInvalidPlatformFileValue, file);
176
177   char data_to_write[] = "test";
178   const int kTestDataSize = 4;
179
180   // Write 0 bytes to the file.
181   int bytes_written = WriteFully(file, 0, data_to_write, 0);
182   EXPECT_EQ(0, bytes_written);
183
184   // Write "test" to the file.
185   bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
186   EXPECT_EQ(kTestDataSize, bytes_written);
187
188   // Read from EOF.
189   char data_read_1[32];
190   int bytes_read = ReadFully(file, kTestDataSize, data_read_1, kTestDataSize);
191   EXPECT_EQ(0, bytes_read);
192
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]);
199
200   // Read 0 bytes.
201   bytes_read = ReadFully(file, 0, data_read_1, 0);
202   EXPECT_EQ(0, bytes_read);
203
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]);
209
210   // Read again, but using the trivial native wrapper.
211   bytes_read = ReadPlatformFileNoBestEffort(file, 0, data_read_1,
212                                                   kTestDataSize);
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]);
216
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);
223
224   // Make sure the file was extended.
225   int64 file_size = 0;
226   EXPECT_TRUE(GetFileSize(file_path, &file_size));
227   EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
228
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]);
239
240   // Close the file handle to allow the temp directory to be deleted.
241   ClosePlatformFile(file);
242 }
243
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(
249       file_path,
250       PLATFORM_FILE_CREATE | PLATFORM_FILE_APPEND,
251       NULL,
252       NULL);
253   EXPECT_NE(kInvalidPlatformFileValue, file);
254
255   char data_to_write[] = "test";
256   const int kTestDataSize = 4;
257
258   // Write 0 bytes to the file.
259   int bytes_written = WriteFully(file, 0, data_to_write, 0);
260   EXPECT_EQ(0, bytes_written);
261
262   // Write "test" to the file.
263   bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
264   EXPECT_EQ(kTestDataSize, bytes_written);
265
266   ClosePlatformFile(file);
267   file = CreatePlatformFile(
268       file_path,
269       PLATFORM_FILE_OPEN | PLATFORM_FILE_READ |
270           PLATFORM_FILE_APPEND,
271       NULL,
272       NULL);
273   EXPECT_NE(kInvalidPlatformFileValue, file);
274
275   char append_data_to_write[] = "78";
276   const int kAppendDataSize = 2;
277
278   // Append "78" to the file.
279   bytes_written = WriteFully(file, 0, append_data_to_write, kAppendDataSize);
280   EXPECT_EQ(kAppendDataSize, bytes_written);
281
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]);
291
292   // Close the file handle to allow the temp directory to be deleted.
293   ClosePlatformFile(file);
294 }
295
296
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(
302       file_path,
303       PLATFORM_FILE_CREATE | PLATFORM_FILE_READ |
304           PLATFORM_FILE_WRITE,
305       NULL,
306       NULL);
307   EXPECT_NE(kInvalidPlatformFileValue, file);
308
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);
314
315   // Extend the file.
316   const int kExtendedFileLength = 10;
317   int64 file_size = 0;
318   EXPECT_TRUE(TruncatePlatformFile(file, kExtendedFileLength));
319   EXPECT_TRUE(GetFileSize(file_path, &file_size));
320   EXPECT_EQ(kExtendedFileLength, file_size);
321
322   // Make sure the file was zero-padded.
323   char data_read[32];
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]);
330
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);
336
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]);
342
343   // Close the file handle to allow the temp directory to be deleted.
344   ClosePlatformFile(file);
345 }
346
347 // Flakily fails: http://crbug.com/86494
348 #if defined(OS_ANDROID)
349 TEST(PlatformFile, TouchGetInfoPlatformFile) {
350 #else
351 TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) {
352 #endif
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,
359       NULL,
360       NULL);
361   EXPECT_NE(kInvalidPlatformFileValue, file);
362
363   // Get info for a newly created file.
364   PlatformFileInfo info;
365   EXPECT_TRUE(GetPlatformFileInfo(file, &info));
366
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;
377
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);
383
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);
392
393   EXPECT_TRUE(TouchPlatformFile(file, new_last_accessed, new_last_modified));
394
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);
400
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);
407 #else
408   EXPECT_EQ(info.last_accessed.ToInternalValue(),
409             new_last_accessed.ToInternalValue());
410   EXPECT_EQ(info.last_modified.ToInternalValue(),
411             new_last_modified.ToInternalValue());
412 #endif
413
414   EXPECT_EQ(info.creation_time.ToInternalValue(),
415             creation_time.ToInternalValue());
416
417   // Close the file handle to allow the temp directory to be deleted.
418   ClosePlatformFile(file);
419 }
420
421 TEST(PlatformFile, ReadFileAtCurrentPosition) {
422   ScopedTempDir temp_dir;
423   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
424   FilePath file_path =
425       temp_dir.path().AppendASCII("read_file_at_current_position");
426   PlatformFile file = CreatePlatformFile(
427       file_path,
428       PLATFORM_FILE_CREATE | PLATFORM_FILE_READ |
429           PLATFORM_FILE_WRITE,
430       NULL, NULL);
431   EXPECT_NE(kInvalidPlatformFileValue, file);
432
433   const char kData[] = "test";
434   const int kDataSize = arraysize(kData) - 1;
435   EXPECT_EQ(kDataSize, WriteFully(file, 0, kData, kDataSize));
436
437   EXPECT_EQ(0, SeekPlatformFile(file, PLATFORM_FILE_FROM_BEGIN, 0));
438
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),
449             std::string(kData));
450
451   ClosePlatformFile(file);
452 }
453
454 }  // namespace base