OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/fileapi/file_system_directory_database.h" | 5 #include "webkit/fileapi/file_system_directory_database.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/file_util.h" | |
10 #include "base/platform_file.h" | |
9 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
10 #include "base/scoped_temp_dir.h" | 12 #include "base/scoped_temp_dir.h" |
11 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
12 #include "base/string_util.h" | 14 #include "base/string_util.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
16 #include "third_party/leveldatabase/src/include/leveldb/db.h" | |
17 #include "webkit/fileapi/file_system_database_test_helper.h" | |
18 #include "webkit/fileapi/file_system_util.h" | |
19 | |
20 #define FPL(x) FILE_PATH_LITERAL(x) | |
14 | 21 |
15 namespace fileapi { | 22 namespace fileapi { |
16 | 23 |
24 namespace { | |
25 const FilePath::CharType kDirectoryDatabaseName[] = FPL("Paths"); | |
26 } | |
27 | |
17 class FileSystemDirectoryDatabaseTest : public testing::Test { | 28 class FileSystemDirectoryDatabaseTest : public testing::Test { |
18 public: | 29 public: |
19 typedef FileSystemDirectoryDatabase::FileId FileId; | 30 typedef FileSystemDirectoryDatabase::FileId FileId; |
20 typedef FileSystemDirectoryDatabase::FileInfo FileInfo; | 31 typedef FileSystemDirectoryDatabase::FileInfo FileInfo; |
21 | 32 |
22 FileSystemDirectoryDatabaseTest() { | 33 FileSystemDirectoryDatabaseTest() { |
23 EXPECT_TRUE(base_.CreateUniqueTempDir()); | 34 EXPECT_TRUE(base_.CreateUniqueTempDir()); |
24 InitDatabase(); | 35 InitDatabase(); |
25 } | 36 } |
26 | 37 |
27 FileSystemDirectoryDatabase* db() { | 38 FileSystemDirectoryDatabase* db() { |
28 return db_.get(); | 39 return db_.get(); |
29 } | 40 } |
30 | 41 |
31 void InitDatabase() { | 42 void InitDatabase() { |
32 // First reset() is to avoid multiple database instance for single | 43 // Call CloseDatabase() to avoid multiple database instance for single |
kinuko
2012/04/11 10:58:49
nit: 'avoid multiple database instance' -> 'avoid
tzik
2012/04/11 13:39:06
Done.
| |
33 // directory at once. | 44 // directory at once. |
45 CloseDatabase(); | |
46 db_.reset(new FileSystemDirectoryDatabase(path())); | |
47 } | |
48 | |
49 void CloseDatabase() { | |
34 db_.reset(); | 50 db_.reset(); |
35 db_.reset(new FileSystemDirectoryDatabase(base_.path())); | |
36 } | 51 } |
37 | 52 |
38 bool AddFileInfo(FileId parent_id, const FilePath::StringType& name) { | 53 bool AddFileInfo(FileId parent_id, const FilePath::StringType& name) { |
39 FileId file_id; | 54 FileId file_id; |
40 FileInfo info; | 55 FileInfo info; |
41 info.parent_id = parent_id; | 56 info.parent_id = parent_id; |
42 info.name = name; | 57 info.name = name; |
43 return db_->AddFileInfo(info, &file_id); | 58 return db_->AddFileInfo(info, &file_id); |
44 } | 59 } |
45 | 60 |
61 void CreateDirectory(FileId parent_id, | |
62 const FilePath::StringType& name, | |
63 FileId* file_id_out) { | |
64 FileId file_id; | |
65 | |
66 FileInfo info; | |
67 info.parent_id = parent_id; | |
68 info.name = name; | |
69 ASSERT_TRUE(db_->AddFileInfo(info, &file_id)); | |
70 | |
71 if (file_id_out) | |
72 *file_id_out = file_id; | |
73 } | |
74 | |
75 void CreateFile(FileId parent_id, | |
76 const FilePath::StringType& name, | |
77 const 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 = FilePath(data_path).NormalizePathSeparators(); | |
85 ASSERT_TRUE(db_->AddFileInfo(info, &file_id)); | |
86 | |
87 FilePath local_path = path().Append(data_path); | |
88 if (!file_util::DirectoryExists(local_path.DirName())) | |
89 ASSERT_TRUE(file_util::CreateDirectory(local_path.DirName())); | |
90 | |
91 bool created; | |
92 base::PlatformFileError error; | |
kinuko
2012/04/11 10:58:49
nit: let's initialize created and error before cal
tzik
2012/04/11 13:39:06
Done.
| |
93 base::PlatformFile file = base::CreatePlatformFile( | |
94 local_path, | |
95 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, | |
96 &created, &error); | |
97 ASSERT_EQ(base::PLATFORM_FILE_OK, error); | |
98 ASSERT_TRUE(created); | |
99 ASSERT_TRUE(base::ClosePlatformFile(file)); | |
100 | |
101 if (file_id_out) | |
102 *file_id_out = file_id; | |
103 } | |
104 | |
105 void ClearDatabaseAndDirectory() { | |
106 db_.reset(); | |
107 ASSERT_TRUE(file_util::Delete(path(), true /* recursive */)); | |
108 ASSERT_TRUE(file_util::CreateDirectory(path())); | |
109 db_.reset(new FileSystemDirectoryDatabase(path())); | |
110 } | |
111 | |
112 bool RepairDatabase() { | |
113 return db()->RepairDatabase( | |
114 FilePathToString(path().Append(kDirectoryDatabaseName))); | |
115 } | |
116 | |
117 const FilePath& path() { | |
118 return base_.path(); | |
119 } | |
120 | |
121 // Makes link from |parent_id| to |child_id| with |name|. | |
122 void MakeHierarchyLink(FileId parent_id, | |
123 FileId child_id, | |
124 const FilePath::StringType& name) { | |
125 ASSERT_TRUE(db()->db_->Put( | |
126 leveldb::WriteOptions(), | |
127 "CHILD_OF:" + base::Int64ToString(parent_id) + ":" + | |
128 FilePathToString(FilePath(name)), | |
129 base::Int64ToString(child_id)).ok()); | |
130 } | |
131 | |
132 // Deletes link from parent of |file_id| to |file_id|. | |
133 void DeleteHierarchyLink(FileId file_id) { | |
134 FileInfo file_info; | |
135 ASSERT_TRUE(db()->GetFileInfo(file_id, &file_info)); | |
136 ASSERT_TRUE(db()->db_->Delete( | |
137 leveldb::WriteOptions(), | |
138 "CHILD_OF:" + base::Int64ToString(file_info.parent_id) + ":" + | |
139 FilePathToString(FilePath(file_info.name))).ok()); | |
140 } | |
141 | |
46 protected: | 142 protected: |
47 // Common temp base for nondestructive uses. | 143 // Common temp base for nondestructive uses. |
48 ScopedTempDir base_; | 144 ScopedTempDir base_; |
49 scoped_ptr<FileSystemDirectoryDatabase> db_; | 145 scoped_ptr<FileSystemDirectoryDatabase> db_; |
50 | 146 |
51 DISALLOW_COPY_AND_ASSIGN(FileSystemDirectoryDatabaseTest); | 147 DISALLOW_COPY_AND_ASSIGN(FileSystemDirectoryDatabaseTest); |
52 }; | 148 }; |
53 | 149 |
54 TEST_F(FileSystemDirectoryDatabaseTest, TestMissingFileGetInfo) { | 150 TEST_F(FileSystemDirectoryDatabaseTest, TestMissingFileGetInfo) { |
55 FileId file_id = 888; | 151 FileId file_id = 888; |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 InitDatabase(); | 507 InitDatabase(); |
412 EXPECT_TRUE(db()->GetNextInteger(&next)); | 508 EXPECT_TRUE(db()->GetNextInteger(&next)); |
413 EXPECT_EQ(2, next); | 509 EXPECT_EQ(2, next); |
414 EXPECT_TRUE(db()->GetNextInteger(&next)); | 510 EXPECT_TRUE(db()->GetNextInteger(&next)); |
415 EXPECT_EQ(3, next); | 511 EXPECT_EQ(3, next); |
416 InitDatabase(); | 512 InitDatabase(); |
417 EXPECT_TRUE(db()->GetNextInteger(&next)); | 513 EXPECT_TRUE(db()->GetNextInteger(&next)); |
418 EXPECT_EQ(4, next); | 514 EXPECT_EQ(4, next); |
419 } | 515 } |
420 | 516 |
517 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Empty) { | |
518 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
519 | |
520 int64 next; | |
kinuko
2012/04/11 10:58:49
nit: initialize next
tzik
2012/04/11 13:39:06
Done.
| |
521 EXPECT_TRUE(db()->GetNextInteger(&next)); | |
522 EXPECT_EQ(0, next); | |
523 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
524 } | |
525 | |
526 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Consistent) { | |
527 FileId dir_id; | |
528 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); | |
529 CreateDirectory(0, FPL("bar"), &dir_id); | |
530 CreateFile(dir_id, FPL("baz"), FPL("fuga"), NULL); | |
531 CreateFile(dir_id, FPL("fizz"), FPL("buzz"), NULL); | |
532 | |
533 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
534 } | |
535 | |
536 TEST_F(FileSystemDirectoryDatabaseTest, | |
537 TestConsistencyCheck_BackingMultiEntry) { | |
538 const FilePath::CharType kBackingFileName[] = FPL("the celeb"); | |
539 CreateFile(0, FPL("foo"), kBackingFileName, NULL); | |
540 | |
541 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
542 ASSERT_TRUE(file_util::Delete(path().Append(kBackingFileName), false)); | |
543 CreateFile(0, FPL("bar"), kBackingFileName, NULL); | |
544 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
545 } | |
546 | |
547 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_FileLost) { | |
548 const FilePath::CharType kBackingFileName[] = FPL("hoge"); | |
549 CreateFile(0, FPL("foo"), kBackingFileName, NULL); | |
550 | |
551 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
552 ASSERT_TRUE(file_util::Delete(path().Append(kBackingFileName), false)); | |
553 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
554 } | |
555 | |
556 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_OrphanFile) { | |
557 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); | |
558 | |
559 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
560 | |
561 bool created; | |
562 base::PlatformFileError error; | |
kinuko
2012/04/11 10:58:49
ditto
tzik
2012/04/11 13:39:06
Done.
| |
563 base::PlatformFile file = base::CreatePlatformFile( | |
564 path().Append(FPL("Orphan File")), | |
565 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, | |
566 &created, &error); | |
567 ASSERT_EQ(base::PLATFORM_FILE_OK, error); | |
568 ASSERT_TRUE(created); | |
569 ASSERT_TRUE(base::ClosePlatformFile(file)); | |
570 | |
571 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
572 } | |
573 | |
574 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_RootLoop) { | |
575 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
576 MakeHierarchyLink(0, 0, FPL("")); | |
577 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
578 } | |
579 | |
580 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_DirectoryLoop) { | |
581 FileId dir1_id; | |
582 FileId dir2_id; | |
583 FilePath::StringType dir1_name = FPL("foo"); | |
584 CreateDirectory(0, dir1_name, &dir1_id); | |
585 CreateDirectory(dir1_id, FPL("bar"), &dir2_id); | |
586 | |
587 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
588 MakeHierarchyLink(dir2_id, dir1_id, dir1_name); | |
589 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
590 } | |
591 | |
592 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_NameMismatch) { | |
593 FileId dir_id; | |
594 FileId file_id; | |
595 CreateDirectory(0, FPL("foo"), &dir_id); | |
596 CreateFile(dir_id, FPL("bar"), FPL("hoge/fuga/piyo"), &file_id); | |
597 | |
598 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
599 DeleteHierarchyLink(file_id); | |
600 MakeHierarchyLink(dir_id, file_id, FPL("baz")); | |
601 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
602 } | |
603 | |
604 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_WreckedEntries) { | |
605 FileId dir1_id; | |
606 FileId dir2_id; | |
607 CreateDirectory(0, FPL("foo"), &dir1_id); | |
608 CreateDirectory(dir1_id, FPL("bar"), &dir2_id); | |
609 CreateFile(dir2_id, FPL("baz"), FPL("fizz/buzz"), NULL); | |
610 | |
611 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
612 DeleteHierarchyLink(dir2_id); // Delete link from |dir1_id| to |dir2_id|. | |
613 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
614 } | |
615 | |
616 TEST_F(FileSystemDirectoryDatabaseTest, TestRepairDatabase_Success) { | |
617 FilePath::StringType kFileName = FPL("bar"); | |
618 | |
619 FileId file_id_prev; | |
620 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); | |
621 CreateFile(0, kFileName, FPL("fuga"), &file_id_prev); | |
622 | |
623 const FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName); | |
624 CloseDatabase(); | |
625 CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile, | |
626 0, std::numeric_limits<size_t>::max()); | |
627 InitDatabase(); | |
628 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
629 | |
630 FileId file_id; | |
631 EXPECT_TRUE(db()->GetChildWithName(0, kFileName, &file_id)); | |
632 EXPECT_EQ(file_id_prev, file_id); | |
633 | |
634 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
635 } | |
636 | |
637 TEST_F(FileSystemDirectoryDatabaseTest, TestRepairDatabase_Failure) { | |
638 FilePath::StringType kFileName = FPL("bar"); | |
639 | |
640 CreateFile(0, FPL("foo"), FPL("hoge"), NULL); | |
641 CreateFile(0, kFileName, FPL("fuga"), NULL); | |
642 | |
643 const FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName); | |
644 CloseDatabase(); | |
645 CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile, | |
646 0, std::numeric_limits<size_t>::max()); | |
647 CorruptDatabase(kDatabaseDirectory, leveldb::kLogFile, | |
648 -1, 1); | |
649 InitDatabase(); | |
650 EXPECT_FALSE(db()->IsFileSystemConsistent()); | |
651 | |
652 FileId file_id; | |
653 EXPECT_FALSE(db()->GetChildWithName(0, kFileName, &file_id)); | |
654 EXPECT_TRUE(db()->IsFileSystemConsistent()); | |
655 } | |
656 | |
421 } // namespace fileapi | 657 } // namespace fileapi |
OLD | NEW |