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