Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Unified Diff: webkit/fileapi/file_system_directory_database_unittest.cc

Issue 9910005: Add database recovery for FileSystemDirectoryDatabase. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..55fe68c7821c5edfcf775776530287c7108a264c 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
- // directory at once.
+ // Call CloseDatabase() to avoid having multiple database instances for
+ // single 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 = false;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ 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_;
@@ -403,7 +499,7 @@ TEST_F(FileSystemDirectoryDatabaseTest, TestOverwritingMoveFileSuccess) {
}
TEST_F(FileSystemDirectoryDatabaseTest, TestGetNextInteger) {
- int64 next;
+ int64 next = -1;
EXPECT_TRUE(db()->GetNextInteger(&next));
EXPECT_EQ(0, next);
EXPECT_TRUE(db()->GetNextInteger(&next));
@@ -418,4 +514,144 @@ TEST_F(FileSystemDirectoryDatabaseTest, TestGetNextInteger) {
EXPECT_EQ(4, next);
}
+TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Empty) {
+ EXPECT_TRUE(db()->IsFileSystemConsistent());
+
+ int64 next = -1;
+ 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 = false;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ 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
« no previous file with comments | « webkit/fileapi/file_system_directory_database.cc ('k') | webkit/fileapi/file_system_origin_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698