• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/files/file.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 
11 using base::File;
12 using base::FilePath;
13 
TEST(FileTest,Create)14 TEST(FileTest, Create) {
15   base::ScopedTempDir temp_dir;
16   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
17   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
18 
19   {
20     // Don't create a File at all.
21     File file;
22     EXPECT_FALSE(file.IsValid());
23     EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
24 
25     File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
26     EXPECT_FALSE(file2.IsValid());
27     EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
28   }
29 
30   {
31     // Open a file that doesn't exist.
32     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
33     EXPECT_FALSE(file.IsValid());
34     EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
35   }
36 
37   {
38     // Open or create a file.
39     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
40     EXPECT_TRUE(file.IsValid());
41     EXPECT_TRUE(file.created());
42     EXPECT_EQ(base::File::FILE_OK, file.error_details());
43   }
44 
45   {
46     // Open an existing file.
47     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
48     EXPECT_TRUE(file.IsValid());
49     EXPECT_FALSE(file.created());
50     EXPECT_EQ(base::File::FILE_OK, file.error_details());
51 
52     // This time verify closing the file.
53     file.Close();
54     EXPECT_FALSE(file.IsValid());
55   }
56 
57   {
58     // Open an existing file through Initialize
59     File file;
60     file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
61     EXPECT_TRUE(file.IsValid());
62     EXPECT_FALSE(file.created());
63     EXPECT_EQ(base::File::FILE_OK, file.error_details());
64 
65     // This time verify closing the file.
66     file.Close();
67     EXPECT_FALSE(file.IsValid());
68   }
69 
70   {
71     // Create a file that exists.
72     File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
73     EXPECT_FALSE(file.IsValid());
74     EXPECT_FALSE(file.created());
75     EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
76   }
77 
78   {
79     // Create or overwrite a file.
80     File file(file_path,
81               base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
82     EXPECT_TRUE(file.IsValid());
83     EXPECT_TRUE(file.created());
84     EXPECT_EQ(base::File::FILE_OK, file.error_details());
85   }
86 
87   {
88     // Create a delete-on-close file.
89     file_path = temp_dir.path().AppendASCII("create_file_2");
90     File file(file_path,
91               base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
92                   base::File::FLAG_DELETE_ON_CLOSE);
93     EXPECT_TRUE(file.IsValid());
94     EXPECT_TRUE(file.created());
95     EXPECT_EQ(base::File::FILE_OK, file.error_details());
96   }
97 
98   EXPECT_FALSE(base::PathExists(file_path));
99 }
100 
TEST(FileTest,Async)101 TEST(FileTest, Async) {
102   base::ScopedTempDir temp_dir;
103   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
104   FilePath file_path = temp_dir.path().AppendASCII("create_file");
105 
106   {
107     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC);
108     EXPECT_TRUE(file.IsValid());
109     EXPECT_TRUE(file.async());
110   }
111 
112   {
113     File file(file_path, base::File::FLAG_OPEN_ALWAYS);
114     EXPECT_TRUE(file.IsValid());
115     EXPECT_FALSE(file.async());
116   }
117 }
118 
TEST(FileTest,DeleteOpenFile)119 TEST(FileTest, DeleteOpenFile) {
120   base::ScopedTempDir temp_dir;
121   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
122   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
123 
124   // Create a file.
125   File file(file_path,
126             base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
127                 base::File::FLAG_SHARE_DELETE);
128   EXPECT_TRUE(file.IsValid());
129   EXPECT_TRUE(file.created());
130   EXPECT_EQ(base::File::FILE_OK, file.error_details());
131 
132   // Open an existing file and mark it as delete on close.
133   File same_file(file_path,
134                  base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
135                      base::File::FLAG_READ);
136   EXPECT_TRUE(file.IsValid());
137   EXPECT_FALSE(same_file.created());
138   EXPECT_EQ(base::File::FILE_OK, same_file.error_details());
139 
140   // Close both handles and check that the file is gone.
141   file.Close();
142   same_file.Close();
143   EXPECT_FALSE(base::PathExists(file_path));
144 }
145 
TEST(FileTest,ReadWrite)146 TEST(FileTest, ReadWrite) {
147   base::ScopedTempDir temp_dir;
148   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
149   FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
150   File file(file_path,
151             base::File::FLAG_CREATE | base::File::FLAG_READ |
152                 base::File::FLAG_WRITE);
153   ASSERT_TRUE(file.IsValid());
154 
155   char data_to_write[] = "test";
156   const int kTestDataSize = 4;
157 
158   // Write 0 bytes to the file.
159   int bytes_written = file.Write(0, data_to_write, 0);
160   EXPECT_EQ(0, bytes_written);
161 
162   // Write "test" to the file.
163   bytes_written = file.Write(0, data_to_write, kTestDataSize);
164   EXPECT_EQ(kTestDataSize, bytes_written);
165 
166   // Read from EOF.
167   char data_read_1[32];
168   int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
169   EXPECT_EQ(0, bytes_read);
170 
171   // Read from somewhere in the middle of the file.
172   const int kPartialReadOffset = 1;
173   bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
174   EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
175   for (int i = 0; i < bytes_read; i++)
176     EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
177 
178   // Read 0 bytes.
179   bytes_read = file.Read(0, data_read_1, 0);
180   EXPECT_EQ(0, bytes_read);
181 
182   // Read the entire file.
183   bytes_read = file.Read(0, data_read_1, kTestDataSize);
184   EXPECT_EQ(kTestDataSize, bytes_read);
185   for (int i = 0; i < bytes_read; i++)
186     EXPECT_EQ(data_to_write[i], data_read_1[i]);
187 
188   // Read again, but using the trivial native wrapper.
189   bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
190   EXPECT_LE(bytes_read, kTestDataSize);
191   for (int i = 0; i < bytes_read; i++)
192     EXPECT_EQ(data_to_write[i], data_read_1[i]);
193 
194   // Write past the end of the file.
195   const int kOffsetBeyondEndOfFile = 10;
196   const int kPartialWriteLength = 2;
197   bytes_written = file.Write(kOffsetBeyondEndOfFile,
198                              data_to_write, kPartialWriteLength);
199   EXPECT_EQ(kPartialWriteLength, bytes_written);
200 
201   // Make sure the file was extended.
202   int64 file_size = 0;
203   EXPECT_TRUE(GetFileSize(file_path, &file_size));
204   EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
205 
206   // Make sure the file was zero-padded.
207   char data_read_2[32];
208   bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
209   EXPECT_EQ(file_size, bytes_read);
210   for (int i = 0; i < kTestDataSize; i++)
211     EXPECT_EQ(data_to_write[i], data_read_2[i]);
212   for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
213     EXPECT_EQ(0, data_read_2[i]);
214   for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
215     EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
216 }
217 
TEST(FileTest,Append)218 TEST(FileTest, Append) {
219   base::ScopedTempDir temp_dir;
220   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
221   FilePath file_path = temp_dir.path().AppendASCII("append_file");
222   File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
223   ASSERT_TRUE(file.IsValid());
224 
225   char data_to_write[] = "test";
226   const int kTestDataSize = 4;
227 
228   // Write 0 bytes to the file.
229   int bytes_written = file.Write(0, data_to_write, 0);
230   EXPECT_EQ(0, bytes_written);
231 
232   // Write "test" to the file.
233   bytes_written = file.Write(0, data_to_write, kTestDataSize);
234   EXPECT_EQ(kTestDataSize, bytes_written);
235 
236   file.Close();
237   File file2(file_path,
238              base::File::FLAG_OPEN | base::File::FLAG_READ |
239                  base::File::FLAG_APPEND);
240   ASSERT_TRUE(file2.IsValid());
241 
242   // Test passing the file around.
243   file = file2.Pass();
244   EXPECT_FALSE(file2.IsValid());
245   ASSERT_TRUE(file.IsValid());
246 
247   char append_data_to_write[] = "78";
248   const int kAppendDataSize = 2;
249 
250   // Append "78" to the file.
251   bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
252   EXPECT_EQ(kAppendDataSize, bytes_written);
253 
254   // Read the entire file.
255   char data_read_1[32];
256   int bytes_read = file.Read(0, data_read_1,
257                              kTestDataSize + kAppendDataSize);
258   EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
259   for (int i = 0; i < kTestDataSize; i++)
260     EXPECT_EQ(data_to_write[i], data_read_1[i]);
261   for (int i = 0; i < kAppendDataSize; i++)
262     EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
263 }
264 
265 
TEST(FileTest,Length)266 TEST(FileTest, Length) {
267   base::ScopedTempDir temp_dir;
268   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
269   FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
270   File file(file_path,
271             base::File::FLAG_CREATE | base::File::FLAG_READ |
272                 base::File::FLAG_WRITE);
273   ASSERT_TRUE(file.IsValid());
274   EXPECT_EQ(0, file.GetLength());
275 
276   // Write "test" to the file.
277   char data_to_write[] = "test";
278   int kTestDataSize = 4;
279   int bytes_written = file.Write(0, data_to_write, kTestDataSize);
280   EXPECT_EQ(kTestDataSize, bytes_written);
281 
282   // Extend the file.
283   const int kExtendedFileLength = 10;
284   int64 file_size = 0;
285   EXPECT_TRUE(file.SetLength(kExtendedFileLength));
286   EXPECT_EQ(kExtendedFileLength, file.GetLength());
287   EXPECT_TRUE(GetFileSize(file_path, &file_size));
288   EXPECT_EQ(kExtendedFileLength, file_size);
289 
290   // Make sure the file was zero-padded.
291   char data_read[32];
292   int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
293   EXPECT_EQ(file_size, bytes_read);
294   for (int i = 0; i < kTestDataSize; i++)
295     EXPECT_EQ(data_to_write[i], data_read[i]);
296   for (int i = kTestDataSize; i < file_size; i++)
297     EXPECT_EQ(0, data_read[i]);
298 
299   // Truncate the file.
300   const int kTruncatedFileLength = 2;
301   EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
302   EXPECT_EQ(kTruncatedFileLength, file.GetLength());
303   EXPECT_TRUE(GetFileSize(file_path, &file_size));
304   EXPECT_EQ(kTruncatedFileLength, file_size);
305 
306   // Make sure the file was truncated.
307   bytes_read = file.Read(0, data_read, kTestDataSize);
308   EXPECT_EQ(file_size, bytes_read);
309   for (int i = 0; i < file_size; i++)
310     EXPECT_EQ(data_to_write[i], data_read[i]);
311 }
312 
313 // Flakily fails: http://crbug.com/86494
314 #if defined(OS_ANDROID)
TEST(FileTest,TouchGetInfo)315 TEST(FileTest, TouchGetInfo) {
316 #else
317 TEST(FileTest, DISABLED_TouchGetInfo) {
318 #endif
319   base::ScopedTempDir temp_dir;
320   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
321   File file(temp_dir.path().AppendASCII("touch_get_info_file"),
322             base::File::FLAG_CREATE | base::File::FLAG_WRITE |
323                 base::File::FLAG_WRITE_ATTRIBUTES);
324   ASSERT_TRUE(file.IsValid());
325 
326   // Get info for a newly created file.
327   base::File::Info info;
328   EXPECT_TRUE(file.GetInfo(&info));
329 
330   // Add 2 seconds to account for possible rounding errors on
331   // filesystems that use a 1s or 2s timestamp granularity.
332   base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
333   EXPECT_EQ(0, info.size);
334   EXPECT_FALSE(info.is_directory);
335   EXPECT_FALSE(info.is_symbolic_link);
336   EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
337   EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
338   EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
339   base::Time creation_time = info.creation_time;
340 
341   // Write "test" to the file.
342   char data[] = "test";
343   const int kTestDataSize = 4;
344   int bytes_written = file.Write(0, data, kTestDataSize);
345   EXPECT_EQ(kTestDataSize, bytes_written);
346 
347   // Change the last_accessed and last_modified dates.
348   // It's best to add values that are multiples of 2 (in seconds)
349   // to the current last_accessed and last_modified times, because
350   // FATxx uses a 2s timestamp granularity.
351   base::Time new_last_accessed =
352       info.last_accessed + base::TimeDelta::FromSeconds(234);
353   base::Time new_last_modified =
354       info.last_modified + base::TimeDelta::FromMinutes(567);
355 
356   EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
357 
358   // Make sure the file info was updated accordingly.
359   EXPECT_TRUE(file.GetInfo(&info));
360   EXPECT_EQ(info.size, kTestDataSize);
361   EXPECT_FALSE(info.is_directory);
362   EXPECT_FALSE(info.is_symbolic_link);
363 
364   // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
365 #if defined(OS_POSIX)
366   EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
367             new_last_accessed.ToTimeVal().tv_sec);
368   EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
369             new_last_modified.ToTimeVal().tv_sec);
370 #else
371   EXPECT_EQ(info.last_accessed.ToInternalValue(),
372             new_last_accessed.ToInternalValue());
373   EXPECT_EQ(info.last_modified.ToInternalValue(),
374             new_last_modified.ToInternalValue());
375 #endif
376 
377   EXPECT_EQ(info.creation_time.ToInternalValue(),
378             creation_time.ToInternalValue());
379 }
380 
381 TEST(FileTest, ReadAtCurrentPosition) {
382   base::ScopedTempDir temp_dir;
383   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
384   FilePath file_path = temp_dir.path().AppendASCII("read_at_current_position");
385   File file(file_path,
386             base::File::FLAG_CREATE | base::File::FLAG_READ |
387                 base::File::FLAG_WRITE);
388   EXPECT_TRUE(file.IsValid());
389 
390   const char kData[] = "test";
391   const int kDataSize = sizeof(kData) - 1;
392   EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
393 
394   EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
395 
396   char buffer[kDataSize];
397   int first_chunk_size = kDataSize / 2;
398   EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
399   EXPECT_EQ(kDataSize - first_chunk_size,
400             file.ReadAtCurrentPos(buffer + first_chunk_size,
401                                   kDataSize - first_chunk_size));
402   EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
403 }
404 
405 TEST(FileTest, WriteAtCurrentPosition) {
406   base::ScopedTempDir temp_dir;
407   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
408   FilePath file_path = temp_dir.path().AppendASCII("write_at_current_position");
409   File file(file_path,
410             base::File::FLAG_CREATE | base::File::FLAG_READ |
411                 base::File::FLAG_WRITE);
412   EXPECT_TRUE(file.IsValid());
413 
414   const char kData[] = "test";
415   const int kDataSize = sizeof(kData) - 1;
416 
417   int first_chunk_size = kDataSize / 2;
418   EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
419   EXPECT_EQ(kDataSize - first_chunk_size,
420             file.WriteAtCurrentPos(kData + first_chunk_size,
421                                    kDataSize - first_chunk_size));
422 
423   char buffer[kDataSize];
424   EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
425   EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
426 }
427 
428 TEST(FileTest, Seek) {
429   base::ScopedTempDir temp_dir;
430   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
431   FilePath file_path = temp_dir.path().AppendASCII("seek_file");
432   File file(file_path,
433             base::File::FLAG_CREATE | base::File::FLAG_READ |
434                 base::File::FLAG_WRITE);
435   ASSERT_TRUE(file.IsValid());
436 
437   const int64 kOffset = 10;
438   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset));
439   EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset));
440   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset));
441   EXPECT_TRUE(file.SetLength(kOffset * 2));
442   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset));
443 }
444 
445 #if defined(OS_WIN)
446 TEST(FileTest, GetInfoForDirectory) {
447   base::ScopedTempDir temp_dir;
448   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
449   FilePath empty_dir = temp_dir.path().Append(FILE_PATH_LITERAL("gpfi_test"));
450   ASSERT_TRUE(CreateDirectory(empty_dir));
451 
452   base::File dir(
453       ::CreateFile(empty_dir.value().c_str(),
454                    FILE_ALL_ACCESS,
455                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
456                    NULL,
457                    OPEN_EXISTING,
458                    FILE_FLAG_BACKUP_SEMANTICS,  // Needed to open a directory.
459                    NULL));
460   ASSERT_TRUE(dir.IsValid());
461 
462   base::File::Info info;
463   EXPECT_TRUE(dir.GetInfo(&info));
464   EXPECT_TRUE(info.is_directory);
465   EXPECT_FALSE(info.is_symbolic_link);
466   EXPECT_EQ(0, info.size);
467 }
468 #endif  // defined(OS_WIN)
469