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