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