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
7 #include <stdint.h>
8
9 #include <utility>
10
11 #include "base/files/file_util.h"
12 #include "base/files/memory_mapped_file.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/time/time.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using base::File;
19 using base::FilePath;
20
TEST(FileTest,Create)21 TEST(FileTest, Create) {
22 base::ScopedTempDir temp_dir;
23 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
24 FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
25
26 {
27 // Don't create a File at all.
28 File file;
29 EXPECT_FALSE(file.IsValid());
30 EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
31
32 File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
33 EXPECT_FALSE(file2.IsValid());
34 EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
35 }
36
37 {
38 // Open a file that doesn't exist.
39 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
40 EXPECT_FALSE(file.IsValid());
41 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
42 }
43
44 {
45 // Open or create a file.
46 File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
47 EXPECT_TRUE(file.IsValid());
48 EXPECT_TRUE(file.created());
49 EXPECT_EQ(base::File::FILE_OK, file.error_details());
50 }
51
52 {
53 // Open an existing file.
54 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
55 EXPECT_TRUE(file.IsValid());
56 EXPECT_FALSE(file.created());
57 EXPECT_EQ(base::File::FILE_OK, file.error_details());
58
59 // This time verify closing the file.
60 file.Close();
61 EXPECT_FALSE(file.IsValid());
62 }
63
64 {
65 // Open an existing file through Initialize
66 File file;
67 file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
68 EXPECT_TRUE(file.IsValid());
69 EXPECT_FALSE(file.created());
70 EXPECT_EQ(base::File::FILE_OK, file.error_details());
71
72 // This time verify closing the file.
73 file.Close();
74 EXPECT_FALSE(file.IsValid());
75 }
76
77 {
78 // Create a file that exists.
79 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
80 EXPECT_FALSE(file.IsValid());
81 EXPECT_FALSE(file.created());
82 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
83 }
84
85 {
86 // Create or overwrite a file.
87 File file(file_path,
88 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
89 EXPECT_TRUE(file.IsValid());
90 EXPECT_TRUE(file.created());
91 EXPECT_EQ(base::File::FILE_OK, file.error_details());
92 }
93
94 {
95 // Create a delete-on-close file.
96 file_path = temp_dir.GetPath().AppendASCII("create_file_2");
97 File file(file_path,
98 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
99 base::File::FLAG_DELETE_ON_CLOSE);
100 EXPECT_TRUE(file.IsValid());
101 EXPECT_TRUE(file.created());
102 EXPECT_EQ(base::File::FILE_OK, file.error_details());
103 }
104
105 EXPECT_FALSE(base::PathExists(file_path));
106 }
107
TEST(FileTest,Async)108 TEST(FileTest, Async) {
109 base::ScopedTempDir temp_dir;
110 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
111 FilePath file_path = temp_dir.GetPath().AppendASCII("create_file");
112
113 {
114 File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC);
115 EXPECT_TRUE(file.IsValid());
116 EXPECT_TRUE(file.async());
117 }
118
119 {
120 File file(file_path, base::File::FLAG_OPEN_ALWAYS);
121 EXPECT_TRUE(file.IsValid());
122 EXPECT_FALSE(file.async());
123 }
124 }
125
TEST(FileTest,DeleteOpenFile)126 TEST(FileTest, DeleteOpenFile) {
127 base::ScopedTempDir temp_dir;
128 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
129 FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
130
131 // Create a file.
132 File file(file_path,
133 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
134 base::File::FLAG_SHARE_DELETE);
135 EXPECT_TRUE(file.IsValid());
136 EXPECT_TRUE(file.created());
137 EXPECT_EQ(base::File::FILE_OK, file.error_details());
138
139 // Open an existing file and mark it as delete on close.
140 File same_file(file_path,
141 base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
142 base::File::FLAG_READ);
143 EXPECT_TRUE(file.IsValid());
144 EXPECT_FALSE(same_file.created());
145 EXPECT_EQ(base::File::FILE_OK, same_file.error_details());
146
147 // Close both handles and check that the file is gone.
148 file.Close();
149 same_file.Close();
150 EXPECT_FALSE(base::PathExists(file_path));
151 }
152
TEST(FileTest,ReadWrite)153 TEST(FileTest, ReadWrite) {
154 base::ScopedTempDir temp_dir;
155 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
156 FilePath file_path = temp_dir.GetPath().AppendASCII("read_write_file");
157 File file(file_path,
158 base::File::FLAG_CREATE | base::File::FLAG_READ |
159 base::File::FLAG_WRITE);
160 ASSERT_TRUE(file.IsValid());
161
162 char data_to_write[] = "test";
163 const int kTestDataSize = 4;
164
165 // Write 0 bytes to the file.
166 int bytes_written = file.Write(0, data_to_write, 0);
167 EXPECT_EQ(0, bytes_written);
168
169 // Write "test" to the file.
170 bytes_written = file.Write(0, data_to_write, kTestDataSize);
171 EXPECT_EQ(kTestDataSize, bytes_written);
172
173 // Read from EOF.
174 char data_read_1[32];
175 int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
176 EXPECT_EQ(0, bytes_read);
177
178 // Read from somewhere in the middle of the file.
179 const int kPartialReadOffset = 1;
180 bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
181 EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
182 for (int i = 0; i < bytes_read; i++)
183 EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
184
185 // Read 0 bytes.
186 bytes_read = file.Read(0, data_read_1, 0);
187 EXPECT_EQ(0, bytes_read);
188
189 // Read the entire file.
190 bytes_read = file.Read(0, data_read_1, kTestDataSize);
191 EXPECT_EQ(kTestDataSize, bytes_read);
192 for (int i = 0; i < bytes_read; i++)
193 EXPECT_EQ(data_to_write[i], data_read_1[i]);
194
195 // Read again, but using the trivial native wrapper.
196 bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
197 EXPECT_LE(bytes_read, kTestDataSize);
198 for (int i = 0; i < bytes_read; i++)
199 EXPECT_EQ(data_to_write[i], data_read_1[i]);
200
201 // Write past the end of the file.
202 const int kOffsetBeyondEndOfFile = 10;
203 const int kPartialWriteLength = 2;
204 bytes_written = file.Write(kOffsetBeyondEndOfFile,
205 data_to_write, kPartialWriteLength);
206 EXPECT_EQ(kPartialWriteLength, bytes_written);
207
208 // Make sure the file was extended.
209 int64_t file_size = 0;
210 EXPECT_TRUE(GetFileSize(file_path, &file_size));
211 EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
212
213 // Make sure the file was zero-padded.
214 char data_read_2[32];
215 bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
216 EXPECT_EQ(file_size, bytes_read);
217 for (int i = 0; i < kTestDataSize; i++)
218 EXPECT_EQ(data_to_write[i], data_read_2[i]);
219 for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
220 EXPECT_EQ(0, data_read_2[i]);
221 for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
222 EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
223 }
224
TEST(FileTest,Append)225 TEST(FileTest, Append) {
226 base::ScopedTempDir temp_dir;
227 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
228 FilePath file_path = temp_dir.GetPath().AppendASCII("append_file");
229 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
230 ASSERT_TRUE(file.IsValid());
231
232 char data_to_write[] = "test";
233 const int kTestDataSize = 4;
234
235 // Write 0 bytes to the file.
236 int bytes_written = file.Write(0, data_to_write, 0);
237 EXPECT_EQ(0, bytes_written);
238
239 // Write "test" to the file.
240 bytes_written = file.Write(0, data_to_write, kTestDataSize);
241 EXPECT_EQ(kTestDataSize, bytes_written);
242
243 file.Close();
244 File file2(file_path,
245 base::File::FLAG_OPEN | base::File::FLAG_READ |
246 base::File::FLAG_APPEND);
247 ASSERT_TRUE(file2.IsValid());
248
249 // Test passing the file around.
250 file = std::move(file2);
251 EXPECT_FALSE(file2.IsValid());
252 ASSERT_TRUE(file.IsValid());
253
254 char append_data_to_write[] = "78";
255 const int kAppendDataSize = 2;
256
257 // Append "78" to the file.
258 bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
259 EXPECT_EQ(kAppendDataSize, bytes_written);
260
261 // Read the entire file.
262 char data_read_1[32];
263 int bytes_read = file.Read(0, data_read_1,
264 kTestDataSize + kAppendDataSize);
265 EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
266 for (int i = 0; i < kTestDataSize; i++)
267 EXPECT_EQ(data_to_write[i], data_read_1[i]);
268 for (int i = 0; i < kAppendDataSize; i++)
269 EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
270 }
271
272
TEST(FileTest,Length)273 TEST(FileTest, Length) {
274 base::ScopedTempDir temp_dir;
275 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
276 FilePath file_path = temp_dir.GetPath().AppendASCII("truncate_file");
277 File file(file_path,
278 base::File::FLAG_CREATE | base::File::FLAG_READ |
279 base::File::FLAG_WRITE);
280 ASSERT_TRUE(file.IsValid());
281 EXPECT_EQ(0, file.GetLength());
282
283 // Write "test" to the file.
284 char data_to_write[] = "test";
285 int kTestDataSize = 4;
286 int bytes_written = file.Write(0, data_to_write, kTestDataSize);
287 EXPECT_EQ(kTestDataSize, bytes_written);
288
289 // Extend the file.
290 const int kExtendedFileLength = 10;
291 int64_t file_size = 0;
292 EXPECT_TRUE(file.SetLength(kExtendedFileLength));
293 EXPECT_EQ(kExtendedFileLength, file.GetLength());
294 EXPECT_TRUE(GetFileSize(file_path, &file_size));
295 EXPECT_EQ(kExtendedFileLength, file_size);
296
297 // Make sure the file was zero-padded.
298 char data_read[32];
299 int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
300 EXPECT_EQ(file_size, bytes_read);
301 for (int i = 0; i < kTestDataSize; i++)
302 EXPECT_EQ(data_to_write[i], data_read[i]);
303 for (int i = kTestDataSize; i < file_size; i++)
304 EXPECT_EQ(0, data_read[i]);
305
306 // Truncate the file.
307 const int kTruncatedFileLength = 2;
308 EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
309 EXPECT_EQ(kTruncatedFileLength, file.GetLength());
310 EXPECT_TRUE(GetFileSize(file_path, &file_size));
311 EXPECT_EQ(kTruncatedFileLength, file_size);
312
313 // Make sure the file was truncated.
314 bytes_read = file.Read(0, data_read, kTestDataSize);
315 EXPECT_EQ(file_size, bytes_read);
316 for (int i = 0; i < file_size; i++)
317 EXPECT_EQ(data_to_write[i], data_read[i]);
318 }
319
320 // Flakily fails: http://crbug.com/86494
321 #if defined(OS_ANDROID)
TEST(FileTest,TouchGetInfo)322 TEST(FileTest, TouchGetInfo) {
323 #else
324 TEST(FileTest, DISABLED_TouchGetInfo) {
325 #endif
326 base::ScopedTempDir temp_dir;
327 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
328 File file(temp_dir.GetPath().AppendASCII("touch_get_info_file"),
329 base::File::FLAG_CREATE | base::File::FLAG_WRITE |
330 base::File::FLAG_WRITE_ATTRIBUTES);
331 ASSERT_TRUE(file.IsValid());
332
333 // Get info for a newly created file.
334 base::File::Info info;
335 EXPECT_TRUE(file.GetInfo(&info));
336
337 // Add 2 seconds to account for possible rounding errors on
338 // filesystems that use a 1s or 2s timestamp granularity.
339 base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
340 EXPECT_EQ(0, info.size);
341 EXPECT_FALSE(info.is_directory);
342 EXPECT_FALSE(info.is_symbolic_link);
343 EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
344 EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
345 EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
346 base::Time creation_time = info.creation_time;
347
348 // Write "test" to the file.
349 char data[] = "test";
350 const int kTestDataSize = 4;
351 int bytes_written = file.Write(0, data, kTestDataSize);
352 EXPECT_EQ(kTestDataSize, bytes_written);
353
354 // Change the last_accessed and last_modified dates.
355 // It's best to add values that are multiples of 2 (in seconds)
356 // to the current last_accessed and last_modified times, because
357 // FATxx uses a 2s timestamp granularity.
358 base::Time new_last_accessed =
359 info.last_accessed + base::TimeDelta::FromSeconds(234);
360 base::Time new_last_modified =
361 info.last_modified + base::TimeDelta::FromMinutes(567);
362
363 EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
364
365 // Make sure the file info was updated accordingly.
366 EXPECT_TRUE(file.GetInfo(&info));
367 EXPECT_EQ(info.size, kTestDataSize);
368 EXPECT_FALSE(info.is_directory);
369 EXPECT_FALSE(info.is_symbolic_link);
370
371 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
372 #if defined(OS_POSIX)
373 EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
374 new_last_accessed.ToTimeVal().tv_sec);
375 EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
376 new_last_modified.ToTimeVal().tv_sec);
377 #else
378 EXPECT_EQ(info.last_accessed.ToInternalValue(),
379 new_last_accessed.ToInternalValue());
380 EXPECT_EQ(info.last_modified.ToInternalValue(),
381 new_last_modified.ToInternalValue());
382 #endif
383
384 EXPECT_EQ(info.creation_time.ToInternalValue(),
385 creation_time.ToInternalValue());
386 }
387
388 TEST(FileTest, ReadAtCurrentPosition) {
389 base::ScopedTempDir temp_dir;
390 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
391 FilePath file_path =
392 temp_dir.GetPath().AppendASCII("read_at_current_position");
393 File file(file_path,
394 base::File::FLAG_CREATE | base::File::FLAG_READ |
395 base::File::FLAG_WRITE);
396 EXPECT_TRUE(file.IsValid());
397
398 const char kData[] = "test";
399 const int kDataSize = sizeof(kData) - 1;
400 EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
401
402 EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
403
404 char buffer[kDataSize];
405 int first_chunk_size = kDataSize / 2;
406 EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
407 EXPECT_EQ(kDataSize - first_chunk_size,
408 file.ReadAtCurrentPos(buffer + first_chunk_size,
409 kDataSize - first_chunk_size));
410 EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
411 }
412
413 TEST(FileTest, WriteAtCurrentPosition) {
414 base::ScopedTempDir temp_dir;
415 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
416 FilePath file_path =
417 temp_dir.GetPath().AppendASCII("write_at_current_position");
418 File file(file_path,
419 base::File::FLAG_CREATE | base::File::FLAG_READ |
420 base::File::FLAG_WRITE);
421 EXPECT_TRUE(file.IsValid());
422
423 const char kData[] = "test";
424 const int kDataSize = sizeof(kData) - 1;
425
426 int first_chunk_size = kDataSize / 2;
427 EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
428 EXPECT_EQ(kDataSize - first_chunk_size,
429 file.WriteAtCurrentPos(kData + first_chunk_size,
430 kDataSize - first_chunk_size));
431
432 char buffer[kDataSize];
433 EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
434 EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
435 }
436
437 TEST(FileTest, Seek) {
438 base::ScopedTempDir temp_dir;
439 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
440 FilePath file_path = temp_dir.GetPath().AppendASCII("seek_file");
441 File file(file_path,
442 base::File::FLAG_CREATE | base::File::FLAG_READ |
443 base::File::FLAG_WRITE);
444 ASSERT_TRUE(file.IsValid());
445
446 const int64_t kOffset = 10;
447 EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset));
448 EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset));
449 EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset));
450 EXPECT_TRUE(file.SetLength(kOffset * 2));
451 EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset));
452 }
453
454 TEST(FileTest, Duplicate) {
455 base::ScopedTempDir temp_dir;
456 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
457 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
458 File file(file_path,(base::File::FLAG_CREATE |
459 base::File::FLAG_READ |
460 base::File::FLAG_WRITE));
461 ASSERT_TRUE(file.IsValid());
462
463 File file2(file.Duplicate());
464 ASSERT_TRUE(file2.IsValid());
465
466 // Write through one handle, close it, read through the other.
467 static const char kData[] = "now is a good time.";
468 static const int kDataLen = sizeof(kData) - 1;
469
470 ASSERT_EQ(0, file.Seek(base::File::FROM_CURRENT, 0));
471 ASSERT_EQ(0, file2.Seek(base::File::FROM_CURRENT, 0));
472 ASSERT_EQ(kDataLen, file.WriteAtCurrentPos(kData, kDataLen));
473 ASSERT_EQ(kDataLen, file.Seek(base::File::FROM_CURRENT, 0));
474 ASSERT_EQ(kDataLen, file2.Seek(base::File::FROM_CURRENT, 0));
475 file.Close();
476 char buf[kDataLen];
477 ASSERT_EQ(kDataLen, file2.Read(0, &buf[0], kDataLen));
478 ASSERT_EQ(std::string(kData, kDataLen), std::string(&buf[0], kDataLen));
479 }
480
481 TEST(FileTest, DuplicateDeleteOnClose) {
482 base::ScopedTempDir temp_dir;
483 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
484 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
485 File file(file_path,(base::File::FLAG_CREATE |
486 base::File::FLAG_READ |
487 base::File::FLAG_WRITE |
488 base::File::FLAG_DELETE_ON_CLOSE));
489 ASSERT_TRUE(file.IsValid());
490 File file2(file.Duplicate());
491 ASSERT_TRUE(file2.IsValid());
492 file.Close();
493 file2.Close();
494 ASSERT_FALSE(base::PathExists(file_path));
495 }
496
497 #if defined(OS_WIN)
498 TEST(FileTest, GetInfoForDirectory) {
499 base::ScopedTempDir temp_dir;
500 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
501 FilePath empty_dir =
502 temp_dir.GetPath().Append(FILE_PATH_LITERAL("gpfi_test"));
503 ASSERT_TRUE(CreateDirectory(empty_dir));
504
505 base::File dir(
506 ::CreateFile(empty_dir.value().c_str(),
507 GENERIC_READ | GENERIC_WRITE,
508 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
509 NULL,
510 OPEN_EXISTING,
511 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
512 NULL));
513 ASSERT_TRUE(dir.IsValid());
514
515 base::File::Info info;
516 EXPECT_TRUE(dir.GetInfo(&info));
517 EXPECT_TRUE(info.is_directory);
518 EXPECT_FALSE(info.is_symbolic_link);
519 EXPECT_EQ(0, info.size);
520 }
521
522 TEST(FileTest, DeleteNoop) {
523 base::ScopedTempDir temp_dir;
524 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
525 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
526
527 // Creating and closing a file with DELETE perms should do nothing special.
528 File file(file_path,
529 (base::File::FLAG_CREATE | base::File::FLAG_READ |
530 base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
531 ASSERT_TRUE(file.IsValid());
532 file.Close();
533 ASSERT_TRUE(base::PathExists(file_path));
534 }
535
536 TEST(FileTest, Delete) {
537 base::ScopedTempDir temp_dir;
538 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
539 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
540
541 // Creating a file with DELETE and then marking for delete on close should
542 // delete it.
543 File file(file_path,
544 (base::File::FLAG_CREATE | base::File::FLAG_READ |
545 base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
546 ASSERT_TRUE(file.IsValid());
547 ASSERT_TRUE(file.DeleteOnClose(true));
548 file.Close();
549 ASSERT_FALSE(base::PathExists(file_path));
550 }
551
552 TEST(FileTest, DeleteThenRevoke) {
553 base::ScopedTempDir temp_dir;
554 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
555 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
556
557 // Creating a file with DELETE, marking it for delete, then clearing delete on
558 // close should not delete it.
559 File file(file_path,
560 (base::File::FLAG_CREATE | base::File::FLAG_READ |
561 base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
562 ASSERT_TRUE(file.IsValid());
563 ASSERT_TRUE(file.DeleteOnClose(true));
564 ASSERT_TRUE(file.DeleteOnClose(false));
565 file.Close();
566 ASSERT_TRUE(base::PathExists(file_path));
567 }
568
569 TEST(FileTest, IrrevokableDeleteOnClose) {
570 base::ScopedTempDir temp_dir;
571 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
572 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
573
574 // DELETE_ON_CLOSE cannot be revoked by this opener.
575 File file(
576 file_path,
577 (base::File::FLAG_CREATE | base::File::FLAG_READ |
578 base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
579 base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
580 ASSERT_TRUE(file.IsValid());
581 // https://msdn.microsoft.com/library/windows/desktop/aa364221.aspx says that
582 // setting the dispositon has no effect if the handle was opened with
583 // FLAG_DELETE_ON_CLOSE. Do not make the test's success dependent on whether
584 // or not SetFileInformationByHandle indicates success or failure. (It happens
585 // to indicate success on Windows 10.)
586 file.DeleteOnClose(false);
587 file.Close();
588 ASSERT_FALSE(base::PathExists(file_path));
589 }
590
591 TEST(FileTest, IrrevokableDeleteOnCloseOther) {
592 base::ScopedTempDir temp_dir;
593 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
594 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
595
596 // DELETE_ON_CLOSE cannot be revoked by another opener.
597 File file(
598 file_path,
599 (base::File::FLAG_CREATE | base::File::FLAG_READ |
600 base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
601 base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
602 ASSERT_TRUE(file.IsValid());
603
604 File file2(
605 file_path,
606 (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
607 base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
608 ASSERT_TRUE(file2.IsValid());
609
610 file2.DeleteOnClose(false);
611 file2.Close();
612 ASSERT_TRUE(base::PathExists(file_path));
613 file.Close();
614 ASSERT_FALSE(base::PathExists(file_path));
615 }
616
617 TEST(FileTest, DeleteWithoutPermission) {
618 base::ScopedTempDir temp_dir;
619 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
620 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
621
622 // It should not be possible to mark a file for deletion when it was not
623 // created/opened with DELETE.
624 File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
625 base::File::FLAG_WRITE));
626 ASSERT_TRUE(file.IsValid());
627 ASSERT_FALSE(file.DeleteOnClose(true));
628 file.Close();
629 ASSERT_TRUE(base::PathExists(file_path));
630 }
631
632 TEST(FileTest, UnsharedDeleteOnClose) {
633 base::ScopedTempDir temp_dir;
634 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
635 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
636
637 // Opening with DELETE_ON_CLOSE when a previous opener hasn't enabled sharing
638 // will fail.
639 File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
640 base::File::FLAG_WRITE));
641 ASSERT_TRUE(file.IsValid());
642 File file2(
643 file_path,
644 (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
645 base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_SHARE_DELETE));
646 ASSERT_FALSE(file2.IsValid());
647
648 file.Close();
649 ASSERT_TRUE(base::PathExists(file_path));
650 }
651
652 TEST(FileTest, NoDeleteOnCloseWithMappedFile) {
653 base::ScopedTempDir temp_dir;
654 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
655 FilePath file_path = temp_dir.GetPath().AppendASCII("file");
656
657 // Mapping a file into memory blocks DeleteOnClose.
658 File file(file_path,
659 (base::File::FLAG_CREATE | base::File::FLAG_READ |
660 base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
661 ASSERT_TRUE(file.IsValid());
662 ASSERT_EQ(5, file.WriteAtCurrentPos("12345", 5));
663
664 {
665 base::MemoryMappedFile mapping;
666 ASSERT_TRUE(mapping.Initialize(file.Duplicate()));
667 ASSERT_EQ(5U, mapping.length());
668
669 EXPECT_FALSE(file.DeleteOnClose(true));
670 }
671
672 file.Close();
673 ASSERT_TRUE(base::PathExists(file_path));
674 }
675 #endif // defined(OS_WIN)
676