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