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

Side by Side 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: '' 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_util.h"
18 #include "webkit/fileapi/file_system_database_test_helper.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
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);
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;
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 void MakeHierarchyLink(FileId parent_id, FileId child_id) {
122 FileInfo file_info;
123 ASSERT_TRUE(db()->GetFileInfo(child_id, &file_info));
124 ASSERT_TRUE(db()->db_->Put(
125 leveldb::WriteOptions(),
126 "CHILD_OF:" + base::Int64ToString(parent_id) + ":" + file_info.name,
127 base::Int64ToString(child_id)).ok());
128 }
129
130 void ReplaceHierarchyLinkName(FileId file_id,
ericu 2012/04/05 00:22:26 This could just use DeleteHierarchyLink and MakeHi
tzik 2012/04/05 05:54:33 Done.
131 const FilePath::StringType& new_name) {
132 FileInfo file_info;
133 ASSERT_TRUE(db()->GetFileInfo(file_id, &file_info));
134 ASSERT_TRUE(db()->db_->Delete(
135 leveldb::WriteOptions(),
136 "CHILD_OF:" + base::Int64ToString(file_info.parent_id) + ":" +
137 file_info.name).ok());
138 ASSERT_TRUE(db()->db_->Put(
139 leveldb::WriteOptions(),
140 "CHILD_OF:" + base::Int64ToString(file_info.parent_id) + ":" + new_name,
141 base::Int64ToString(file_id)).ok());
142 }
143
144 void DeleteHierarchyLink(FileId file_id) {
145 FileInfo file_info;
146 ASSERT_TRUE(db()->GetFileInfo(file_id, &file_info));
147 ASSERT_TRUE(db()->db_->Delete(
148 leveldb::WriteOptions(),
149 "CHILD_OF:" + base::Int64ToString(file_info.parent_id) + ":" +
150 file_info.name).ok());
151 }
152
46 protected: 153 protected:
47 // Common temp base for nondestructive uses. 154 // Common temp base for nondestructive uses.
48 ScopedTempDir base_; 155 ScopedTempDir base_;
49 scoped_ptr<FileSystemDirectoryDatabase> db_; 156 scoped_ptr<FileSystemDirectoryDatabase> db_;
50 157
51 DISALLOW_COPY_AND_ASSIGN(FileSystemDirectoryDatabaseTest); 158 DISALLOW_COPY_AND_ASSIGN(FileSystemDirectoryDatabaseTest);
52 }; 159 };
53 160
54 TEST_F(FileSystemDirectoryDatabaseTest, TestMissingFileGetInfo) { 161 TEST_F(FileSystemDirectoryDatabaseTest, TestMissingFileGetInfo) {
55 FileId file_id = 888; 162 FileId file_id = 888;
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 InitDatabase(); 518 InitDatabase();
412 EXPECT_TRUE(db()->GetNextInteger(&next)); 519 EXPECT_TRUE(db()->GetNextInteger(&next));
413 EXPECT_EQ(2, next); 520 EXPECT_EQ(2, next);
414 EXPECT_TRUE(db()->GetNextInteger(&next)); 521 EXPECT_TRUE(db()->GetNextInteger(&next));
415 EXPECT_EQ(3, next); 522 EXPECT_EQ(3, next);
416 InitDatabase(); 523 InitDatabase();
417 EXPECT_TRUE(db()->GetNextInteger(&next)); 524 EXPECT_TRUE(db()->GetNextInteger(&next));
418 EXPECT_EQ(4, next); 525 EXPECT_EQ(4, next);
419 } 526 }
420 527
528 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Empty) {
529 EXPECT_TRUE(db()->IsFileSystemConsistent());
530
531 int64 next;
532 EXPECT_TRUE(db()->GetNextInteger(&next));
533 EXPECT_EQ(0, next);
534 EXPECT_TRUE(db()->IsFileSystemConsistent());
535 }
536
537 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_Consistent) {
538 FileId dir_id;
539 CreateFile(0, FPL("foo"), FPL("hoge"), NULL);
540 CreateDirectory(0, FPL("bar"), &dir_id);
541 CreateFile(dir_id, FPL("baz"), FPL("fuga"), NULL);
542 CreateFile(dir_id, FPL("fizz"), FPL("buzz"), NULL);
543
544 EXPECT_TRUE(db()->IsFileSystemConsistent());
545 }
546
547 TEST_F(FileSystemDirectoryDatabaseTest,
548 TestConsistencyCheck_BackingMultiEntry) {
549 const FilePath::CharType kBackingFileName[] = FPL("the celeb");
550 CreateFile(0, FPL("foo"), kBackingFileName, NULL);
551 ASSERT_TRUE(file_util::Delete(path().Append(kBackingFileName), false));
552 CreateFile(0, FPL("bar"), kBackingFileName, NULL);
553
554 EXPECT_FALSE(db()->IsFileSystemConsistent());
555 }
556
557 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_FileLost) {
558 const FilePath::CharType kBackingFileName[] = FPL("hoge");
559 CreateFile(0, FPL("foo"), kBackingFileName, NULL);
560 ASSERT_TRUE(file_util::Delete(path().Append(kBackingFileName), false));
561
562 EXPECT_FALSE(db()->IsFileSystemConsistent());
563 }
564
565 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_OrphanFile) {
566 CreateFile(0, FPL("foo"), FPL("hoge"), NULL);
567
568 bool created;
569 base::PlatformFileError error;
570 base::PlatformFile file = base::CreatePlatformFile(
571 path().Append("Orphan File"),
572 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
573 &created, &error);
574 ASSERT_EQ(base::PLATFORM_FILE_OK, error);
575 ASSERT_TRUE(created);
576 ASSERT_TRUE(base::ClosePlatformFile(file));
577
578 EXPECT_FALSE(db()->IsFileSystemConsistent());
579 }
580
581 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_RootLoop) {
582 MakeHierarchyLink(0, 0);
583 EXPECT_FALSE(db()->IsFileSystemConsistent());
584 }
585
586 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_DirectoryLoop) {
587 FileId dir1_id;
588 FileId dir2_id;
589 CreateDirectory(0, FPL("foo"), &dir1_id);
590 CreateDirectory(dir1_id, FPL("bar"), &dir2_id);
591 MakeHierarchyLink(dir2_id, dir1_id);
592 EXPECT_FALSE(db()->IsFileSystemConsistent());
593 }
594
595 TEST_F(FileSystemDirectoryDatabaseTest, TestConsistencyCheck_NameMismatch) {
596 FileId dir_id;
597 FileId file_id;
598 CreateDirectory(0, FPL("foo"), &dir_id);
599 CreateFile(dir_id, FPL("bar"), FPL("hoge/fuga/piyo"), &file_id);
600 ReplaceHierarchyLinkName(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 DeleteHierarchyLink(dir2_id); // delete link from |dir1_id| to |dir2_id|
ericu 2012/04/05 00:22:26 In each of these tests, I think it would be good t
tzik 2012/04/05 05:54:33 Done.
612 EXPECT_FALSE(db()->IsFileSystemConsistent());
613 }
614
615 TEST_F(FileSystemDirectoryDatabaseTest, TestRepairDatabase_Success) {
616 FilePath::StringType kFileName = FPL("bar");
617
618 FileId file_id_prev;
619 CreateFile(0, FPL("foo"), FPL("hoge"), NULL);
620 CreateFile(0, kFileName, FPL("fuga"), &file_id_prev);
621
622 const FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName);
623 CloseDatabase();
624 CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile,
625 0, std::numeric_limits<size_t>::max());
626 InitDatabase();
627 EXPECT_FALSE(db()->IsFileSystemConsistent());
628
629 FileId file_id;
630 EXPECT_TRUE(db()->GetChildWithName(0, kFileName, &file_id));
631 EXPECT_EQ(file_id_prev, file_id);
632
633 EXPECT_TRUE(db()->IsFileSystemConsistent());
634 }
635
636 TEST_F(FileSystemDirectoryDatabaseTest, TestRepairDatabase_Failure) {
637 FilePath::StringType kFileName = FPL("bar");
638
639 CreateFile(0, FPL("foo"), FPL("hoge"), NULL);
640 CreateFile(0, kFileName, FPL("fuga"), NULL);
641
642 const FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName);
643 CloseDatabase();
644 CorruptDatabase(kDatabaseDirectory, leveldb::kDescriptorFile,
645 0, std::numeric_limits<size_t>::max());
646 CorruptDatabase(kDatabaseDirectory, leveldb::kLogFile,
647 -1, 1);
648 InitDatabase();
649 EXPECT_FALSE(db()->IsFileSystemConsistent());
650
651 FileId file_id;
652 EXPECT_FALSE(db()->GetChildWithName(0, kFileName, &file_id));
653 EXPECT_TRUE(db()->IsFileSystemConsistent());
654 }
655
421 } // namespace fileapi 656 } // namespace fileapi
OLDNEW
« 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