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 "webkit/browser/fileapi/sandbox_directory_database.h" 6 7 #include <math.h> 8 #include <limits> 9 10 #include "base/file_util.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/platform_file.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_util.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "third_party/leveldatabase/src/include/leveldb/db.h" 18 #include "webkit/browser/fileapi/sandbox_database_test_helper.h" 19 #include "webkit/common/fileapi/file_system_util.h" 20 21 #define FPL(x) FILE_PATH_LITERAL(x) 22 23 namespace fileapi { 24 25 namespace { 26 const base::FilePath::CharType kDirectoryDatabaseName[] = FPL("Paths"); 27 } 28 29 class SandboxDirectoryDatabaseTest : public testing::Test { 30 public: 31 typedef SandboxDirectoryDatabase::FileId FileId; 32 typedef SandboxDirectoryDatabase::FileInfo FileInfo; 33 34 SandboxDirectoryDatabaseTest() { 35 EXPECT_TRUE(base_.CreateUniqueTempDir()); 36 InitDatabase(); 37 } 38 39 SandboxDirectoryDatabase* db() { 40 return db_.get(); 41 } 42 43 void InitDatabase() { 44 // Call CloseDatabase() to avoid having multiple database instances for 45 // single directory at once. 46 CloseDatabase(); 47 db_.reset(new SandboxDirectoryDatabase(path())); 48 } 49 50 void CloseDatabase() { 51 db_.reset(); 52 } 53 54 bool AddFileInfo(FileId parent_id, const base::FilePath::StringType& name) { 55 FileId file_id; 56 FileInfo info; 57 info.parent_id = parent_id; 58 info.name = name; 59 return db_->AddFileInfo(info, &file_id); 60 } 61 62 void CreateDirectory(FileId parent_id, 63 const base::FilePath::StringType& name, 64 FileId* file_id_out) { 65 FileInfo info; 66 info.parent_id = parent_id; 67 info.name = name; 68 ASSERT_TRUE(db_->AddFileInfo(info, file_id_out)); 69 } 70 71 void CreateFile(FileId parent_id, 72 const base::FilePath::StringType& name, 73 const base::FilePath::StringType& data_path, 74 FileId* file_id_out) { 75 FileId file_id; 76 77 FileInfo info; 78 info.parent_id = parent_id; 79 info.name = name; 80 info.data_path = base::FilePath(data_path).NormalizePathSeparators(); 81 ASSERT_TRUE(db_->AddFileInfo(info, &file_id)); 82 83 base::FilePath local_path = path().Append(data_path); 84 if (!base::DirectoryExists(local_path.DirName())) 85 ASSERT_TRUE(file_util::CreateDirectory(local_path.DirName())); 86 87 bool created = false; 88 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; 89 base::PlatformFile file = base::CreatePlatformFile( 90 local_path, 91 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, 92 &created, &error); 93 ASSERT_EQ(base::PLATFORM_FILE_OK, error); 94 ASSERT_TRUE(created); 95 ASSERT_TRUE(base::ClosePlatformFile(file)); 96 97 if (file_id_out) 98 *file_id_out = file_id; 99 } 100 101 void ClearDatabaseAndDirectory() { 102 db_.reset(); 103 ASSERT_TRUE(base::DeleteFile(path(), true /* recursive */)); 104 ASSERT_TRUE(file_util::CreateDirectory(path())); 105 db_.reset(new SandboxDirectoryDatabase(path())); 106 } 107 108 bool RepairDatabase() { 109 return db()->RepairDatabase( 110 FilePathToString(path().Append(kDirectoryDatabaseName))); 111 } 112 113 const base::FilePath& path() { 114 return base_.path(); 115 } 116 117 // Makes link from |parent_id| to |child_id| with |name|. 118 void MakeHierarchyLink(FileId parent_id, 119 FileId child_id, 120 const base::FilePath::StringType& name) { 121 ASSERT_TRUE(db()->db_->Put( 122 leveldb::WriteOptions(), 123 "CHILD_OF:" + base::Int64ToString(parent_id) + ":" + 124 FilePathToString(base::FilePath(name)), 125 base::Int64ToString(child_id)).ok()); 126 } 127 128 // Deletes link from parent of |file_id| to |file_id|. 129 void DeleteHierarchyLink(FileId file_id) { 130 FileInfo file_info; 131 ASSERT_TRUE(db()->GetFileInfo(file_id, &file_info)); 132 ASSERT_TRUE(db()->db_->Delete( 133 leveldb::WriteOptions(), 134 "CHILD_OF:" + base::Int64ToString(file_info.parent_id) + ":" + 135 FilePathToString(base::FilePath(file_info.name))).ok()); 136 } 137 138 protected: 139 // Common temp base for nondestructive uses. 140 base::ScopedTempDir base_; 141 scoped_ptr<SandboxDirectoryDatabase> db_; 142 143 DISALLOW_COPY_AND_ASSIGN(SandboxDirectoryDatabaseTest); 144 }; 145 146 TEST_F(SandboxDirectoryDatabaseTest, TestMissingFileGetInfo) { 147 FileId file_id = 888; 148 FileInfo info; 149 EXPECT_FALSE(db()->GetFileInfo(file_id, &info)); 150 } 151 152 TEST_F(SandboxDirectoryDatabaseTest, TestGetRootFileInfoBeforeCreate) { 153 FileId file_id = 0; 154 FileInfo info; 155 EXPECT_TRUE(db()->GetFileInfo(file_id, &info)); 156 EXPECT_EQ(0, info.parent_id); 157 EXPECT_TRUE(info.name.empty()); 158 EXPECT_TRUE(info.data_path.empty()); 159 } 160 161 TEST_F(SandboxDirectoryDatabaseTest, TestMissingParentAddFileInfo) { 162 FileId parent_id = 7; 163 EXPECT_FALSE(AddFileInfo(parent_id, FILE_PATH_LITERAL("foo"))); 164 } 165 166 TEST_F(SandboxDirectoryDatabaseTest, TestAddNameClash) { 167 FileInfo info; 168 FileId file_id; 169 info.parent_id = 0; 170 info.name = FILE_PATH_LITERAL("dir 0"); 171 EXPECT_TRUE(db()->AddFileInfo(info, &file_id)); 172 173 // Check for name clash in the root directory. 174 base::FilePath::StringType name = info.name; 175 EXPECT_FALSE(AddFileInfo(0, name)); 176 name = FILE_PATH_LITERAL("dir 1"); 177 EXPECT_TRUE(AddFileInfo(0, name)); 178 179 name = FILE_PATH_LITERAL("subdir 0"); 180 EXPECT_TRUE(AddFileInfo(file_id, name)); 181 182 // Check for name clash in a subdirectory. 183 EXPECT_FALSE(AddFileInfo(file_id, name)); 184 name = FILE_PATH_LITERAL("subdir 1"); 185 EXPECT_TRUE(AddFileInfo(file_id, name)); 186 } 187 188 TEST_F(SandboxDirectoryDatabaseTest, TestRenameNoMoveNameClash) { 189 FileInfo info; 190 FileId file_id0; 191 base::FilePath::StringType name0 = FILE_PATH_LITERAL("foo"); 192 base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); 193 base::FilePath::StringType name2 = FILE_PATH_LITERAL("bas"); 194 info.parent_id = 0; 195 info.name = name0; 196 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 197 EXPECT_TRUE(AddFileInfo(0, name1)); 198 info.name = name1; 199 EXPECT_FALSE(db()->UpdateFileInfo(file_id0, info)); 200 info.name = name2; 201 EXPECT_TRUE(db()->UpdateFileInfo(file_id0, info)); 202 } 203 204 TEST_F(SandboxDirectoryDatabaseTest, TestMoveSameNameNameClash) { 205 FileInfo info; 206 FileId file_id0; 207 FileId file_id1; 208 base::FilePath::StringType name0 = FILE_PATH_LITERAL("foo"); 209 base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); 210 info.parent_id = 0; 211 info.name = name0; 212 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 213 info.parent_id = file_id0; 214 EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); 215 info.parent_id = 0; 216 EXPECT_FALSE(db()->UpdateFileInfo(file_id1, info)); 217 info.name = name1; 218 EXPECT_TRUE(db()->UpdateFileInfo(file_id1, info)); 219 } 220 221 TEST_F(SandboxDirectoryDatabaseTest, TestMoveRenameNameClash) { 222 FileInfo info; 223 FileId file_id0; 224 FileId file_id1; 225 base::FilePath::StringType name0 = FILE_PATH_LITERAL("foo"); 226 base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); 227 base::FilePath::StringType name2 = FILE_PATH_LITERAL("bas"); 228 info.parent_id = 0; 229 info.name = name0; 230 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 231 info.parent_id = file_id0; 232 info.name = name1; 233 EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); 234 info.parent_id = 0; 235 info.name = name0; 236 EXPECT_FALSE(db()->UpdateFileInfo(file_id1, info)); 237 info.name = name1; 238 EXPECT_TRUE(db()->UpdateFileInfo(file_id1, info)); 239 // Also test a successful move+rename. 240 info.parent_id = file_id0; 241 info.name = name2; 242 EXPECT_TRUE(db()->UpdateFileInfo(file_id1, info)); 243 } 244 245 TEST_F(SandboxDirectoryDatabaseTest, TestRemoveWithChildren) { 246 FileInfo info; 247 FileId file_id0; 248 FileId file_id1; 249 info.parent_id = 0; 250 info.name = FILE_PATH_LITERAL("foo"); 251 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 252 info.parent_id = file_id0; 253 EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); 254 EXPECT_FALSE(db()->RemoveFileInfo(file_id0)); 255 EXPECT_TRUE(db()->RemoveFileInfo(file_id1)); 256 EXPECT_TRUE(db()->RemoveFileInfo(file_id0)); 257 } 258 259 TEST_F(SandboxDirectoryDatabaseTest, TestGetChildWithName) { 260 FileInfo info; 261 FileId file_id0; 262 FileId file_id1; 263 base::FilePath::StringType name0 = FILE_PATH_LITERAL("foo"); 264 base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); 265 info.parent_id = 0; 266 info.name = name0; 267 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 268 info.parent_id = file_id0; 269 info.name = name1; 270 EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); 271 EXPECT_NE(file_id0, file_id1); 272 273 FileId check_file_id; 274 EXPECT_FALSE(db()->GetChildWithName(0, name1, &check_file_id)); 275 EXPECT_TRUE(db()->GetChildWithName(0, name0, &check_file_id)); 276 EXPECT_EQ(file_id0, check_file_id); 277 EXPECT_FALSE(db()->GetChildWithName(file_id0, name0, &check_file_id)); 278 EXPECT_TRUE(db()->GetChildWithName(file_id0, name1, &check_file_id)); 279 EXPECT_EQ(file_id1, check_file_id); 280 } 281 282 TEST_F(SandboxDirectoryDatabaseTest, TestGetFileWithPath) { 283 FileInfo info; 284 FileId file_id0; 285 FileId file_id1; 286 FileId file_id2; 287 base::FilePath::StringType name0 = FILE_PATH_LITERAL("foo"); 288 base::FilePath::StringType name1 = FILE_PATH_LITERAL("bar"); 289 base::FilePath::StringType name2 = FILE_PATH_LITERAL("dog"); 290 291 info.parent_id = 0; 292 info.name = name0; 293 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 294 info.parent_id = file_id0; 295 info.name = name1; 296 EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); 297 EXPECT_NE(file_id0, file_id1); 298 info.parent_id = file_id1; 299 info.name = name2; 300 EXPECT_TRUE(db()->AddFileInfo(info, &file_id2)); 301 EXPECT_NE(file_id0, file_id2); 302 EXPECT_NE(file_id1, file_id2); 303 304 FileId check_file_id; 305 base::FilePath path = base::FilePath(name0); 306 EXPECT_TRUE(db()->GetFileWithPath(path, &check_file_id)); 307 EXPECT_EQ(file_id0, check_file_id); 308 309 path = path.Append(name1); 310 EXPECT_TRUE(db()->GetFileWithPath(path, &check_file_id)); 311 EXPECT_EQ(file_id1, check_file_id); 312 313 path = path.Append(name2); 314 EXPECT_TRUE(db()->GetFileWithPath(path, &check_file_id)); 315 EXPECT_EQ(file_id2, check_file_id); 316 } 317 318 TEST_F(SandboxDirectoryDatabaseTest, TestListChildren) { 319 // No children in the root. 320 std::vector<FileId> children; 321 EXPECT_TRUE(db()->ListChildren(0, &children)); 322 EXPECT_TRUE(children.empty()); 323 324 // One child in the root. 325 FileId file_id0; 326 FileInfo info; 327 info.parent_id = 0; 328 info.name = FILE_PATH_LITERAL("foo"); 329 EXPECT_TRUE(db()->AddFileInfo(info, &file_id0)); 330 EXPECT_TRUE(db()->ListChildren(0, &children)); 331 EXPECT_EQ(children.size(), 1UL); 332 EXPECT_EQ(children[0], file_id0); 333 334 // Two children in the root. 335 FileId file_id1; 336 info.name = FILE_PATH_LITERAL("bar"); 337 EXPECT_TRUE(db()->AddFileInfo(info, &file_id1)); 338 EXPECT_TRUE(db()->ListChildren(0, &children)); 339 EXPECT_EQ(2UL, children.size()); 340 if (children[0] == file_id0) { 341 EXPECT_EQ(children[1], file_id1); 342 } else { 343 EXPECT_EQ(children[1], file_id0); 344 EXPECT_EQ(children[0], file_id1); 345 } 346 347 // No children in a subdirectory. 348 EXPECT_TRUE(db()->ListChildren(file_id0, &children)); 349 EXPECT_TRUE(children.empty()); 350 351 // One child in a subdirectory. 352 info.parent_id = file_id0; 353 info.name = FILE_PATH_LITERAL("foo"); 354 FileId file_id2; 355 FileId file_id3; 356 EXPECT_TRUE(db()->AddFileInfo(info, &file_id2)); 357 EXPECT_TRUE(db()->ListChildren(file_id0, &children)); 358 EXPECT_EQ(1UL, children.size()); 359 EXPECT_EQ(children[0], file_id2); 360 361 // Two children in a subdirectory. 362 info.name = FILE_PATH_LITERAL("bar"); 363 EXPECT_TRUE(db()->AddFileInfo(info, &file_id3)); 364 EXPECT_TRUE(db()->ListChildren(file_id0, &children)); 365 EXPECT_EQ(2UL, children.size()); 366 if (children[0] == file_id2) { 367 EXPECT_EQ(children[1], file_id3); 368 } else { 369 EXPECT_EQ(children[1], file_id2); 370 EXPECT_EQ(children[0], file_id3); 371 } 372 } 373 374 TEST_F(SandboxDirectoryDatabaseTest, TestUpdateModificationTime) { 375 FileInfo info0; 376 FileId file_id; 377 info0.parent_id = 0; 378 info0.name = FILE_PATH_LITERAL("name"); 379 info0.data_path = base::FilePath(FILE_PATH_LITERAL("fake path")); 380 info0.modification_time = base::Time::Now(); 381 EXPECT_TRUE(db()->AddFileInfo(info0, &file_id)); 382 FileInfo info1; 383 EXPECT_TRUE(db()->GetFileInfo(file_id, &info1)); 384 EXPECT_EQ(info0.name, info1.name); 385 EXPECT_EQ(info0.parent_id, info1.parent_id); 386 EXPECT_EQ(info0.data_path, info1.data_path); 387 EXPECT_EQ( 388 floor(info0.modification_time.ToDoubleT()), 389 info1.modification_time.ToDoubleT()); 390 391 EXPECT_TRUE(db()->UpdateModificationTime(file_id, base::Time::UnixEpoch())); 392 EXPECT_TRUE(db()->GetFileInfo(file_id, &info1)); 393 EXPECT_EQ(info0.name, info1.name); 394 EXPECT_EQ(info0.parent_id, info1.parent_id); 395 EXPECT_EQ(info0.data_path, info1.data_path); 396 EXPECT_NE(info0.modification_time, info1.modification_time); 397 EXPECT_EQ( 398 info1.modification_time.ToDoubleT(), 399 floor(base::Time::UnixEpoch().ToDoubleT())); 400 401 EXPECT_FALSE(db()->UpdateModificationTime(999, base::Time::UnixEpoch())); 402 } 403 404 TEST_F(SandboxDirectoryDatabaseTest, TestSimpleFileOperations) { 405 FileId file_id = 888; 406 FileInfo info0; 407 EXPECT_FALSE(db()->GetFileInfo(file_id, &info0)); 408 info0.parent_id = 0; 409 info0.data_path = base::FilePath(FILE_PATH_LITERAL("foo")); 410 info0.name = FILE_PATH_LITERAL("file name"); 411 info0.modification_time = base::Time::Now(); 412 EXPECT_TRUE(db()->AddFileInfo(info0, &file_id)); 413 FileInfo info1; 414 EXPECT_TRUE(db()->GetFileInfo(file_id, &info1)); 415 EXPECT_EQ(info0.parent_id, info1.parent_id); 416 EXPECT_EQ(info0.data_path, info1.data_path); 417 EXPECT_EQ(info0.name, info1.name); 418 EXPECT_EQ( 419 floor(info0.modification_time.ToDoubleT()), 420 info1.modification_time.ToDoubleT()); 421 } 422 423 TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileSrcDirectory) { 424 FileId directory_id; 425 FileInfo info0; 426 info0.parent_id = 0; 427 info0.name = FILE_PATH_LITERAL("directory"); 428 info0.modification_time = base::Time::Now(); 429 EXPECT_TRUE(db()->AddFileInfo(info0, &directory_id)); 430 431 FileId file_id; 432 FileInfo info1; 433 info1.parent_id = 0; 434 info1.data_path = base::FilePath(FILE_PATH_LITERAL("bar")); 435 info1.name = FILE_PATH_LITERAL("file"); 436 info1.modification_time = base::Time::UnixEpoch(); 437 EXPECT_TRUE(db()->AddFileInfo(info1, &file_id)); 438 439 EXPECT_FALSE(db()->OverwritingMoveFile(directory_id, file_id)); 440 } 441 442 TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileDestDirectory) { 443 FileId file_id; 444 FileInfo info0; 445 info0.parent_id = 0; 446 info0.name = FILE_PATH_LITERAL("file"); 447 info0.data_path = base::FilePath(FILE_PATH_LITERAL("bar")); 448 info0.modification_time = base::Time::Now(); 449 EXPECT_TRUE(db()->AddFileInfo(info0, &file_id)); 450 451 FileId directory_id; 452 FileInfo info1; 453 info1.parent_id = 0; 454 info1.name = FILE_PATH_LITERAL("directory"); 455 info1.modification_time = base::Time::UnixEpoch(); 456 EXPECT_TRUE(db()->AddFileInfo(info1, &directory_id)); 457 458 EXPECT_FALSE(db()->OverwritingMoveFile(file_id, directory_id)); 459 } 460 461 TEST_F(SandboxDirectoryDatabaseTest, TestOverwritingMoveFileSuccess) { 462 FileId file_id0; 463 FileInfo info0; 464 info0.parent_id = 0; 465 info0.data_path = base::FilePath(FILE_PATH_LITERAL("foo")); 466 info0.name = FILE_PATH_LITERAL("file name 0"); 467 info0.modification_time = base::Time::Now(); 468 EXPECT_TRUE(db()->AddFileInfo(info0, &file_id0)); 469 470 FileInfo dir_info; 471 FileId dir_id; 472 dir_info.parent_id = 0; 473 dir_info.name = FILE_PATH_LITERAL("directory name"); 474 EXPECT_TRUE(db()->AddFileInfo(dir_info, &dir_id)); 475 476 FileId file_id1; 477 FileInfo info1; 478 info1.parent_id = dir_id; 479 info1.data_path = base::FilePath(FILE_PATH_LITERAL("bar")); 480 info1.name = FILE_PATH_LITERAL("file name 1"); 481 info1.modification_time = base::Time::UnixEpoch(); 482 EXPECT_TRUE(db()->AddFileInfo(info1, &file_id1)); 483 484 EXPECT_TRUE(db()->OverwritingMoveFile(file_id0, file_id1)); 485 486 FileInfo check_info; 487 FileId check_id; 488 489 EXPECT_FALSE(db()->GetFileWithPath(base::FilePath(info0.name), &check_id)); 490 EXPECT_TRUE(db()->GetFileWithPath( 491 base::FilePath(dir_info.name).Append(info1.name), &check_id)); 492 EXPECT_TRUE(db()->GetFileInfo(check_id, &check_info)); 493 494 EXPECT_EQ(info0.data_path, check_info.data_path); 495 } 496 497 TEST_F(SandboxDirectoryDatabaseTest, TestGetNextInteger) { 498 int64 next = -1; 499 EXPECT_TRUE(db()->GetNextInteger(&next)); 500 EXPECT_EQ(0, next); 501 EXPECT_TRUE(db()->GetNextInteger(&next)); 502 EXPECT_EQ(1, next); 503 InitDatabase(); 504 EXPECT_TRUE(db()->GetNextInteger(&next)); 505 EXPECT_EQ(2, next); 506 EXPECT_TRUE(db()->GetNextInteger(&next)); 507 EXPECT_EQ(3, next); 508 InitDatabase(); 509 EXPECT_TRUE(db()->GetNextInteger(&next)); 510 EXPECT_EQ(4, next); 511 } 512 513 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_Empty) { 514 EXPECT_TRUE(db()->IsFileSystemConsistent()); 515 516 int64 next = -1; 517 EXPECT_TRUE(db()->GetNextInteger(&next)); 518 EXPECT_EQ(0, next); 519 EXPECT_TRUE(db()->IsFileSystemConsistent()); 520 } 521 522 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_Consistent) { 523 FileId dir_id; 524 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); 525 CreateDirectory(0, FPL("bar"), &dir_id); 526 CreateFile(dir_id, FPL("baz"), FPL("fuga"), NULL); 527 CreateFile(dir_id, FPL("fizz"), FPL("buzz"), NULL); 528 529 EXPECT_TRUE(db()->IsFileSystemConsistent()); 530 } 531 532 TEST_F(SandboxDirectoryDatabaseTest, 533 TestConsistencyCheck_BackingMultiEntry) { 534 const base::FilePath::CharType kBackingFileName[] = FPL("the celeb"); 535 CreateFile(0, FPL("foo"), kBackingFileName, NULL); 536 537 EXPECT_TRUE(db()->IsFileSystemConsistent()); 538 ASSERT_TRUE(base::DeleteFile(path().Append(kBackingFileName), false)); 539 CreateFile(0, FPL("bar"), kBackingFileName, NULL); 540 EXPECT_FALSE(db()->IsFileSystemConsistent()); 541 } 542 543 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_FileLost) { 544 const base::FilePath::CharType kBackingFileName[] = FPL("hoge"); 545 CreateFile(0, FPL("foo"), kBackingFileName, NULL); 546 547 EXPECT_TRUE(db()->IsFileSystemConsistent()); 548 ASSERT_TRUE(base::DeleteFile(path().Append(kBackingFileName), false)); 549 EXPECT_TRUE(db()->IsFileSystemConsistent()); 550 } 551 552 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_OrphanFile) { 553 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); 554 555 EXPECT_TRUE(db()->IsFileSystemConsistent()); 556 557 bool created = false; 558 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; 559 base::PlatformFile file = base::CreatePlatformFile( 560 path().Append(FPL("Orphan File")), 561 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, 562 &created, &error); 563 ASSERT_EQ(base::PLATFORM_FILE_OK, error); 564 ASSERT_TRUE(created); 565 ASSERT_TRUE(base::ClosePlatformFile(file)); 566 567 EXPECT_TRUE(db()->IsFileSystemConsistent()); 568 } 569 570 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_RootLoop) { 571 EXPECT_TRUE(db()->IsFileSystemConsistent()); 572 MakeHierarchyLink(0, 0, base::FilePath::StringType()); 573 EXPECT_FALSE(db()->IsFileSystemConsistent()); 574 } 575 576 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_DirectoryLoop) { 577 FileId dir1_id; 578 FileId dir2_id; 579 base::FilePath::StringType dir1_name = FPL("foo"); 580 CreateDirectory(0, dir1_name, &dir1_id); 581 CreateDirectory(dir1_id, FPL("bar"), &dir2_id); 582 583 EXPECT_TRUE(db()->IsFileSystemConsistent()); 584 MakeHierarchyLink(dir2_id, dir1_id, dir1_name); 585 EXPECT_FALSE(db()->IsFileSystemConsistent()); 586 } 587 588 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_NameMismatch) { 589 FileId dir_id; 590 FileId file_id; 591 CreateDirectory(0, FPL("foo"), &dir_id); 592 CreateFile(dir_id, FPL("bar"), FPL("hoge/fuga/piyo"), &file_id); 593 594 EXPECT_TRUE(db()->IsFileSystemConsistent()); 595 DeleteHierarchyLink(file_id); 596 MakeHierarchyLink(dir_id, file_id, FPL("baz")); 597 EXPECT_FALSE(db()->IsFileSystemConsistent()); 598 } 599 600 TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_WreckedEntries) { 601 FileId dir1_id; 602 FileId dir2_id; 603 CreateDirectory(0, FPL("foo"), &dir1_id); 604 CreateDirectory(dir1_id, FPL("bar"), &dir2_id); 605 CreateFile(dir2_id, FPL("baz"), FPL("fizz/buzz"), NULL); 606 607 EXPECT_TRUE(db()->IsFileSystemConsistent()); 608 DeleteHierarchyLink(dir2_id); // Delete link from |dir1_id| to |dir2_id|. 609 EXPECT_FALSE(db()->IsFileSystemConsistent()); 610 } 611 612 TEST_F(SandboxDirectoryDatabaseTest, TestRepairDatabase_Success) { 613 base::FilePath::StringType kFileName = FPL("bar"); 614 615 FileId file_id_prev; 616 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); 617 CreateFile(0, kFileName, FPL("fuga"), &file_id_prev); 618 619 const base::FilePath kDatabaseDirectory = 620 path().Append(kDirectoryDatabaseName); 621 CloseDatabase(); 622 CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile, 623 0, std::numeric_limits<size_t>::max()); 624 InitDatabase(); 625 EXPECT_FALSE(db()->IsFileSystemConsistent()); 626 627 FileId file_id; 628 EXPECT_TRUE(db()->GetChildWithName(0, kFileName, &file_id)); 629 EXPECT_EQ(file_id_prev, file_id); 630 631 EXPECT_TRUE(db()->IsFileSystemConsistent()); 632 } 633 634 TEST_F(SandboxDirectoryDatabaseTest, TestRepairDatabase_Failure) { 635 base::FilePath::StringType kFileName = FPL("bar"); 636 637 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); 638 CreateFile(0, kFileName, FPL("fuga"), NULL); 639 640 const base::FilePath kDatabaseDirectory = 641 path().Append(kDirectoryDatabaseName); 642 CloseDatabase(); 643 CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile, 644 0, std::numeric_limits<size_t>::max()); 645 CorruptDatabase(kDatabaseDirectory, leveldb::kLogFile, 646 -1, 1); 647 InitDatabase(); 648 EXPECT_FALSE(db()->IsFileSystemConsistent()); 649 650 FileId file_id; 651 EXPECT_FALSE(db()->GetChildWithName(0, kFileName, &file_id)); 652 EXPECT_TRUE(db()->IsFileSystemConsistent()); 653 } 654 655 TEST_F(SandboxDirectoryDatabaseTest, TestRepairDatabase_MissingManifest) { 656 base::FilePath::StringType kFileName = FPL("bar"); 657 658 FileId file_id_prev; 659 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); 660 CreateFile(0, kFileName, FPL("fuga"), &file_id_prev); 661 662 const base::FilePath kDatabaseDirectory = 663 path().Append(kDirectoryDatabaseName); 664 CloseDatabase(); 665 666 DeleteDatabaseFile(kDatabaseDirectory, leveldb::kDescriptorFile); 667 668 InitDatabase(); 669 EXPECT_FALSE(db()->IsFileSystemConsistent()); 670 671 FileId file_id; 672 EXPECT_TRUE(db()->GetChildWithName(0, kFileName, &file_id)); 673 EXPECT_EQ(file_id_prev, file_id); 674 675 EXPECT_TRUE(db()->IsFileSystemConsistent()); 676 } 677 678 } // namespace fileapi 679