Chromium Code Reviews| Index: webkit/fileapi/file_system_directory_database_unittest.cc |
| diff --git a/webkit/fileapi/file_system_directory_database_unittest.cc b/webkit/fileapi/file_system_directory_database_unittest.cc |
| index 2f78449d451a6a74c88e0941a25761bfa7909056..3920c188cbc1a51dac729bb8932bb9c9bc27c9b4 100644 |
| --- a/webkit/fileapi/file_system_directory_database_unittest.cc |
| +++ b/webkit/fileapi/file_system_directory_database_unittest.cc |
| @@ -6,14 +6,25 @@ |
| #include <math.h> |
| +#include "base/file_util.h" |
| +#include "base/platform_file.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/scoped_temp_dir.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +#include "third_party/leveldatabase/src/include/leveldb/db.h" |
| +#include "webkit/fileapi/file_system_database_test_helper.h" |
| +#include "webkit/fileapi/file_system_util.h" |
| + |
| +#define FPL(x) FILE_PATH_LITERAL(x) |
| namespace fileapi { |
| +namespace { |
| +const FilePath::CharType kDirectoryDatabaseName[] = FPL("Paths"); |
| +} |
| + |
| class FileSystemDirectoryDatabaseTest : public testing::Test { |
| public: |
| typedef FileSystemDirectoryDatabase::FileId FileId; |
| @@ -29,10 +40,14 @@ class FileSystemDirectoryDatabaseTest : public testing::Test { |
| } |
| void InitDatabase() { |
| - // First reset() is to avoid multiple database instance for single |
| + // 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.
|
| // directory at once. |
| + CloseDatabase(); |
| + db_.reset(new FileSystemDirectoryDatabase(path())); |
| + } |
| + |
| + void CloseDatabase() { |
| db_.reset(); |
| - db_.reset(new FileSystemDirectoryDatabase(base_.path())); |
| } |
| bool AddFileInfo(FileId parent_id, const FilePath::StringType& name) { |
| @@ -43,6 +58,87 @@ class FileSystemDirectoryDatabaseTest : public testing::Test { |
| return db_->AddFileInfo(info, &file_id); |
| } |
| + void CreateDirectory(FileId parent_id, |
| + const FilePath::StringType& name, |
| + FileId* file_id_out) { |
| + FileId file_id; |
| + |
| + FileInfo info; |
| + info.parent_id = parent_id; |
| + info.name = name; |
| + ASSERT_TRUE(db_->AddFileInfo(info, &file_id)); |
| + |
| + if (file_id_out) |
| + *file_id_out = file_id; |
| + } |
| + |
| + void CreateFile(FileId parent_id, |
| + const FilePath::StringType& name, |
| + const FilePath::StringType& data_path, |
| + FileId* file_id_out) { |
| + FileId file_id; |
| + |
| + FileInfo info; |
| + info.parent_id = parent_id; |
| + info.name = name; |
| + info.data_path = FilePath(data_path).NormalizePathSeparators(); |
| + ASSERT_TRUE(db_->AddFileInfo(info, &file_id)); |
| + |
| + FilePath local_path = path().Append(data_path); |
| + if (!file_util::DirectoryExists(local_path.DirName())) |
| + ASSERT_TRUE(file_util::CreateDirectory(local_path.DirName())); |
| + |
| + bool created; |
| + 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.
|
| + base::PlatformFile file = base::CreatePlatformFile( |
| + local_path, |
| + base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, |
| + &created, &error); |
| + ASSERT_EQ(base::PLATFORM_FILE_OK, error); |
| + ASSERT_TRUE(created); |
| + ASSERT_TRUE(base::ClosePlatformFile(file)); |
| + |
| + if (file_id_out) |
| + *file_id_out = file_id; |
| + } |
| + |
| + void ClearDatabaseAndDirectory() { |
| + db_.reset(); |
| + ASSERT_TRUE(file_util::Delete(path(), true /* recursive */)); |
| + ASSERT_TRUE(file_util::CreateDirectory(path())); |
| + db_.reset(new FileSystemDirectoryDatabase(path())); |
| + } |
| + |
| + bool RepairDatabase() { |
| + return db()->RepairDatabase( |
| + FilePathToString(path().Append(kDirectoryDatabaseName))); |
| + } |
| + |
| + const FilePath& path() { |
| + return base_.path(); |
| + } |
| + |
| + // Makes link from |parent_id| to |child_id| with |name|. |
| + void MakeHierarchyLink(FileId parent_id, |
| + FileId child_id, |
| + const FilePath::StringType& name) { |
| + ASSERT_TRUE(db()->db_->Put( |
| + leveldb::WriteOptions(), |
| + "CHILD_OF:" + base::Int64ToString(parent_id) + ":" + |
| + FilePathToString(FilePath(name)), |
| + base::Int64ToString(child_id)).ok()); |
| + } |
| + |
| + // Deletes link from parent of |file_id| to |file_id|. |
| + void DeleteHierarchyLink(FileId file_id) { |
| + FileInfo file_info; |
| + ASSERT_TRUE(db()->GetFileInfo(file_id, &file_info)); |
| + ASSERT_TRUE(db()->db_->Delete( |
| + leveldb::WriteOptions(), |
| + "CHILD_OF:" + base::Int64ToString(file_info.parent_id) + ":" + |
| + FilePathToString(FilePath(file_info.name))).ok()); |
| + } |
| + |
| protected: |
| // Common temp base for nondestructive uses. |
| ScopedTempDir base_; |
| @@ -418,4 +514,144 @@ TEST_F(FileSystemDirectoryDatabaseTest, TestGetNextInteger) { |
| EXPECT_EQ(4, next); |
| } |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Empty) { |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + |
| + int64 next; |
|
kinuko
2012/04/11 10:58:49
nit: initialize next
tzik
2012/04/11 13:39:06
Done.
|
| + EXPECT_TRUE(db()->GetNextInteger(&next)); |
| + EXPECT_EQ(0, next); |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Consistent) { |
| + FileId dir_id; |
| + CreateFile(0, FPL("foo"), FPL("hoge"), NULL); |
| + CreateDirectory(0, FPL("bar"), &dir_id); |
| + CreateFile(dir_id, FPL("baz"), FPL("fuga"), NULL); |
| + CreateFile(dir_id, FPL("fizz"), FPL("buzz"), NULL); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, |
| + TestConsistencyCheck_BackingMultiEntry) { |
| + const FilePath::CharType kBackingFileName[] = FPL("the celeb"); |
| + CreateFile(0, FPL("foo"), kBackingFileName, NULL); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + ASSERT_TRUE(file_util::Delete(path().Append(kBackingFileName), false)); |
| + CreateFile(0, FPL("bar"), kBackingFileName, NULL); |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_FileLost) { |
| + const FilePath::CharType kBackingFileName[] = FPL("hoge"); |
| + CreateFile(0, FPL("foo"), kBackingFileName, NULL); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + ASSERT_TRUE(file_util::Delete(path().Append(kBackingFileName), false)); |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_OrphanFile) { |
| + CreateFile(0, FPL("foo"), FPL("hoge"), NULL); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + |
| + bool created; |
| + base::PlatformFileError error; |
|
kinuko
2012/04/11 10:58:49
ditto
tzik
2012/04/11 13:39:06
Done.
|
| + base::PlatformFile file = base::CreatePlatformFile( |
| + path().Append(FPL("Orphan File")), |
| + base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, |
| + &created, &error); |
| + ASSERT_EQ(base::PLATFORM_FILE_OK, error); |
| + ASSERT_TRUE(created); |
| + ASSERT_TRUE(base::ClosePlatformFile(file)); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_RootLoop) { |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + MakeHierarchyLink(0, 0, FPL("")); |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_DirectoryLoop) { |
| + FileId dir1_id; |
| + FileId dir2_id; |
| + FilePath::StringType dir1_name = FPL("foo"); |
| + CreateDirectory(0, dir1_name, &dir1_id); |
| + CreateDirectory(dir1_id, FPL("bar"), &dir2_id); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + MakeHierarchyLink(dir2_id, dir1_id, dir1_name); |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_NameMismatch) { |
| + FileId dir_id; |
| + FileId file_id; |
| + CreateDirectory(0, FPL("foo"), &dir_id); |
| + CreateFile(dir_id, FPL("bar"), FPL("hoge/fuga/piyo"), &file_id); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + DeleteHierarchyLink(file_id); |
| + MakeHierarchyLink(dir_id, file_id, FPL("baz")); |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_WreckedEntries) { |
| + FileId dir1_id; |
| + FileId dir2_id; |
| + CreateDirectory(0, FPL("foo"), &dir1_id); |
| + CreateDirectory(dir1_id, FPL("bar"), &dir2_id); |
| + CreateFile(dir2_id, FPL("baz"), FPL("fizz/buzz"), NULL); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| + DeleteHierarchyLink(dir2_id); // Delete link from |dir1_id| to |dir2_id|. |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestRepairDatabase_Success) { |
| + FilePath::StringType kFileName = FPL("bar"); |
| + |
| + FileId file_id_prev; |
| + CreateFile(0, FPL("foo"), FPL("hoge"), NULL); |
| + CreateFile(0, kFileName, FPL("fuga"), &file_id_prev); |
| + |
| + const FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName); |
| + CloseDatabase(); |
| + CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile, |
| + 0, std::numeric_limits<size_t>::max()); |
| + InitDatabase(); |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| + |
| + FileId file_id; |
| + EXPECT_TRUE(db()->GetChildWithName(0, kFileName, &file_id)); |
| + EXPECT_EQ(file_id_prev, file_id); |
| + |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| +TEST_F(FileSystemDirectoryDatabaseTest, TestRepairDatabase_Failure) { |
| + FilePath::StringType kFileName = FPL("bar"); |
| + |
| + CreateFile(0, FPL("foo"), FPL("hoge"), NULL); |
| + CreateFile(0, kFileName, FPL("fuga"), NULL); |
| + |
| + const FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName); |
| + CloseDatabase(); |
| + CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile, |
| + 0, std::numeric_limits<size_t>::max()); |
| + CorruptDatabase(kDatabaseDirectory, leveldb::kLogFile, |
| + -1, 1); |
| + InitDatabase(); |
| + EXPECT_FALSE(db()->IsFileSystemConsistent()); |
| + |
| + FileId file_id; |
| + EXPECT_FALSE(db()->GetChildWithName(0, kFileName, &file_id)); |
| + EXPECT_TRUE(db()->IsFileSystemConsistent()); |
| +} |
| + |
| } // namespace fileapi |