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

Side by Side Diff: webkit/fileapi/file_system_origin_database_unittest.cc

Issue 9663021: Add database recovery for FileSystemOriginDatabase (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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/fileapi/file_system_origin_database.cc ('k') | webkit/fileapi/file_system_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h" 5 #include "testing/gtest/include/gtest/gtest.h"
6 6
7 #include <algorithm>
7 #include <string> 8 #include <string>
8 9
10 #include "base/file_path.h"
9 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/platform_file.h"
10 #include "base/scoped_temp_dir.h" 13 #include "base/scoped_temp_dir.h"
14 #include "base/stl_util.h"
15 #include "third_party/leveldatabase/src/db/filename.h"
16 #include "third_party/leveldatabase/src/include/leveldb/db.h"
11 #include "webkit/fileapi/file_system_origin_database.h" 17 #include "webkit/fileapi/file_system_origin_database.h"
18 #include "webkit/fileapi/file_system_util.h"
12 19
13 namespace fileapi { 20 namespace fileapi {
14 21
22 namespace {
23 const FilePath::CharType kFileSystemDirName[] =
24 FILE_PATH_LITERAL("File System");
25 const FilePath::CharType kOriginDatabaseName[] = FILE_PATH_LITERAL("Origins");
26
27 void CorruptDatabase(const FilePath& db_path,
28 leveldb::FileType type,
29 ptrdiff_t offset,
30 size_t size) {
31 file_util::FileEnumerator file_enum(
32 db_path, false /* recursive */,
33 static_cast<file_util::FileEnumerator::FileType>(
34 file_util::FileEnumerator::DIRECTORIES |
35 file_util::FileEnumerator::FILES));
36 FilePath file_path;
37 FilePath picked_file_path;
38 uint64 picked_file_number = kuint64max;
39
40 while (!(file_path = file_enum.Next()).empty()) {
41 uint64 number = kuint64max;
42 leveldb::FileType file_type;
43 EXPECT_TRUE(leveldb::ParseFileName(FilePathToString(file_path.BaseName()),
44 &number, &file_type));
45 if (file_type == type &&
46 (picked_file_number == kuint64max || picked_file_number < number)) {
47 picked_file_path = file_path;
48 picked_file_number = number;
49 }
50 }
51
52 EXPECT_FALSE(picked_file_path.empty());
53 EXPECT_NE(kuint64max, picked_file_number);
54
55 bool created = true;
56 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
57 base::PlatformFile file =
58 CreatePlatformFile(picked_file_path,
59 base::PLATFORM_FILE_OPEN |
60 base::PLATFORM_FILE_READ |
61 base::PLATFORM_FILE_WRITE,
62 &created, &error);
63 EXPECT_EQ(base::PLATFORM_FILE_OK, error);
64 EXPECT_FALSE(created);
65
66 base::PlatformFileInfo file_info;
67 EXPECT_TRUE(base::GetPlatformFileInfo(file, &file_info));
68 if (offset < 0)
69 offset += file_info.size;
70 EXPECT_GE(offset, 0);
71 EXPECT_LE(offset, file_info.size);
72
73 size = std::min(size, static_cast<size_t>(file_info.size - offset));
74
75 std::vector<char> buf(size);
76 int read_size = base::ReadPlatformFile(file, offset,
77 vector_as_array(&buf), buf.size());
78 EXPECT_LT(0, read_size);
79 EXPECT_GE(buf.size(), static_cast<size_t>(read_size));
80 buf.resize(read_size);
81
82 std::transform(buf.begin(), buf.end(), buf.begin(),
83 std::logical_not<char>());
84
85 int written_size = base::WritePlatformFile(file, offset,
86 vector_as_array(&buf), buf.size());
87 EXPECT_GT(written_size, 0);
88 EXPECT_EQ(buf.size(), static_cast<size_t>(written_size));
89
90 base::ClosePlatformFile(file);
91 }
92
93 }
94
15 TEST(FileSystemOriginDatabaseTest, BasicTest) { 95 TEST(FileSystemOriginDatabaseTest, BasicTest) {
16 ScopedTempDir dir; 96 ScopedTempDir dir;
17 ASSERT_TRUE(dir.CreateUniqueTempDir()); 97 ASSERT_TRUE(dir.CreateUniqueTempDir());
18 const FilePath kDBFile = dir.path().AppendASCII("fsod.db"); 98 const FilePath kFSDir = dir.path().Append(kFileSystemDirName);
19 EXPECT_FALSE(file_util::PathExists(kDBFile)); 99 EXPECT_FALSE(file_util::PathExists(kFSDir));
100 EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
20 101
21 FileSystemOriginDatabase database(kDBFile); 102 FileSystemOriginDatabase database(kFSDir);
22 std::string origin("origin"); 103 std::string origin("origin");
23 104
24 EXPECT_FALSE(database.HasOriginPath(origin)); 105 EXPECT_FALSE(database.HasOriginPath(origin));
25 // Double-check to make sure that had no side effects. 106 // Double-check to make sure that had no side effects.
26 EXPECT_FALSE(database.HasOriginPath(origin)); 107 EXPECT_FALSE(database.HasOriginPath(origin));
27 108
28 FilePath path0; 109 FilePath path0;
29 FilePath path1; 110 FilePath path1;
30 111
31 // Empty strings aren't valid origins. 112 // Empty strings aren't valid origins.
32 EXPECT_FALSE(database.GetPathForOrigin(std::string(), &path0)); 113 EXPECT_FALSE(database.GetPathForOrigin(std::string(), &path0));
33 114
34 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0)); 115 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0));
35 EXPECT_TRUE(database.HasOriginPath(origin)); 116 EXPECT_TRUE(database.HasOriginPath(origin));
36 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1)); 117 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1));
37 EXPECT_FALSE(path0.empty()); 118 EXPECT_FALSE(path0.empty());
38 EXPECT_FALSE(path1.empty()); 119 EXPECT_FALSE(path1.empty());
39 EXPECT_EQ(path0, path1); 120 EXPECT_EQ(path0, path1);
40 121
41 EXPECT_TRUE(file_util::PathExists(kDBFile)); 122 EXPECT_TRUE(file_util::PathExists(kFSDir.Append(kOriginDatabaseName)));
42 } 123 }
43 124
44 TEST(FileSystemOriginDatabaseTest, TwoPathTest) { 125 TEST(FileSystemOriginDatabaseTest, TwoPathTest) {
45 ScopedTempDir dir; 126 ScopedTempDir dir;
46 ASSERT_TRUE(dir.CreateUniqueTempDir()); 127 ASSERT_TRUE(dir.CreateUniqueTempDir());
47 const FilePath kDBFile = dir.path().AppendASCII("fsod.db"); 128 const FilePath kFSDir = dir.path().Append(kFileSystemDirName);
48 EXPECT_FALSE(file_util::PathExists(kDBFile)); 129 EXPECT_FALSE(file_util::PathExists(kFSDir));
130 EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
49 131
50 FileSystemOriginDatabase database(kDBFile); 132 FileSystemOriginDatabase database(kFSDir);
51 std::string origin0("origin0"); 133 std::string origin0("origin0");
52 std::string origin1("origin1"); 134 std::string origin1("origin1");
53 135
54 EXPECT_FALSE(database.HasOriginPath(origin0)); 136 EXPECT_FALSE(database.HasOriginPath(origin0));
55 EXPECT_FALSE(database.HasOriginPath(origin1)); 137 EXPECT_FALSE(database.HasOriginPath(origin1));
56 138
57 FilePath path0; 139 FilePath path0;
58 FilePath path1; 140 FilePath path1;
59 EXPECT_TRUE(database.GetPathForOrigin(origin0, &path0)); 141 EXPECT_TRUE(database.GetPathForOrigin(origin0, &path0));
60 EXPECT_TRUE(database.HasOriginPath(origin0)); 142 EXPECT_TRUE(database.HasOriginPath(origin0));
61 EXPECT_FALSE(database.HasOriginPath(origin1)); 143 EXPECT_FALSE(database.HasOriginPath(origin1));
62 EXPECT_TRUE(database.GetPathForOrigin(origin1, &path1)); 144 EXPECT_TRUE(database.GetPathForOrigin(origin1, &path1));
63 EXPECT_TRUE(database.HasOriginPath(origin1)); 145 EXPECT_TRUE(database.HasOriginPath(origin1));
64 EXPECT_FALSE(path0.empty()); 146 EXPECT_FALSE(path0.empty());
65 EXPECT_FALSE(path1.empty()); 147 EXPECT_FALSE(path1.empty());
66 EXPECT_NE(path0, path1); 148 EXPECT_NE(path0, path1);
67 149
68 EXPECT_TRUE(file_util::PathExists(kDBFile)); 150 EXPECT_TRUE(file_util::PathExists(kFSDir.Append(kOriginDatabaseName)));
69 } 151 }
70 152
71 TEST(FileSystemOriginDatabaseTest, DropDatabaseTest) { 153 TEST(FileSystemOriginDatabaseTest, DropDatabaseTest) {
72 ScopedTempDir dir; 154 ScopedTempDir dir;
73 ASSERT_TRUE(dir.CreateUniqueTempDir()); 155 ASSERT_TRUE(dir.CreateUniqueTempDir());
74 const FilePath kDBFile = dir.path().AppendASCII("fsod.db"); 156 const FilePath kFSDir = dir.path().Append(kFileSystemDirName);
75 EXPECT_FALSE(file_util::PathExists(kDBFile)); 157 EXPECT_FALSE(file_util::PathExists(kFSDir));
158 EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
76 159
77 FileSystemOriginDatabase database(kDBFile); 160 FileSystemOriginDatabase database(kFSDir);
78 std::string origin("origin"); 161 std::string origin("origin");
79 162
80 EXPECT_FALSE(database.HasOriginPath(origin)); 163 EXPECT_FALSE(database.HasOriginPath(origin));
81 164
82 FilePath path0; 165 FilePath path0;
83 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0)); 166 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0));
84 EXPECT_TRUE(database.HasOriginPath(origin)); 167 EXPECT_TRUE(database.HasOriginPath(origin));
85 EXPECT_FALSE(path0.empty()); 168 EXPECT_FALSE(path0.empty());
86 169
87 EXPECT_TRUE(file_util::PathExists(kDBFile)); 170 EXPECT_TRUE(file_util::PathExists(kFSDir.Append(kOriginDatabaseName)));
88 171
89 database.DropDatabase(); 172 database.DropDatabase();
90 173
91 FilePath path1; 174 FilePath path1;
92 EXPECT_TRUE(database.HasOriginPath(origin)); 175 EXPECT_TRUE(database.HasOriginPath(origin));
93 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1)); 176 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1));
94 EXPECT_FALSE(path1.empty()); 177 EXPECT_FALSE(path1.empty());
95 EXPECT_EQ(path0, path1); 178 EXPECT_EQ(path0, path1);
96 } 179 }
97 180
98 TEST(FileSystemOriginDatabaseTest, DeleteOriginTest) { 181 TEST(FileSystemOriginDatabaseTest, DeleteOriginTest) {
99 ScopedTempDir dir; 182 ScopedTempDir dir;
100 ASSERT_TRUE(dir.CreateUniqueTempDir()); 183 ASSERT_TRUE(dir.CreateUniqueTempDir());
101 const FilePath kDBFile = dir.path().AppendASCII("fsod.db"); 184 const FilePath kFSDir = dir.path().Append(kFileSystemDirName);
102 EXPECT_FALSE(file_util::PathExists(kDBFile)); 185 EXPECT_FALSE(file_util::PathExists(kFSDir));
186 EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
103 187
104 FileSystemOriginDatabase database(kDBFile); 188 FileSystemOriginDatabase database(kFSDir);
105 std::string origin("origin"); 189 std::string origin("origin");
106 190
107 EXPECT_FALSE(database.HasOriginPath(origin)); 191 EXPECT_FALSE(database.HasOriginPath(origin));
108 EXPECT_TRUE(database.RemovePathForOrigin(origin)); 192 EXPECT_TRUE(database.RemovePathForOrigin(origin));
109 193
110 FilePath path0; 194 FilePath path0;
111 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0)); 195 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0));
112 EXPECT_TRUE(database.HasOriginPath(origin)); 196 EXPECT_TRUE(database.HasOriginPath(origin));
113 EXPECT_FALSE(path0.empty()); 197 EXPECT_FALSE(path0.empty());
114 198
115 EXPECT_TRUE(database.RemovePathForOrigin(origin)); 199 EXPECT_TRUE(database.RemovePathForOrigin(origin));
116 EXPECT_FALSE(database.HasOriginPath(origin)); 200 EXPECT_FALSE(database.HasOriginPath(origin));
117 201
118 FilePath path1; 202 FilePath path1;
119 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1)); 203 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1));
120 EXPECT_FALSE(path1.empty()); 204 EXPECT_FALSE(path1.empty());
121 EXPECT_NE(path0, path1); 205 EXPECT_NE(path0, path1);
122 } 206 }
123 207
124 TEST(FileSystemOriginDatabaseTest, ListOriginsTest) { 208 TEST(FileSystemOriginDatabaseTest, ListOriginsTest) {
125 ScopedTempDir dir; 209 ScopedTempDir dir;
126 ASSERT_TRUE(dir.CreateUniqueTempDir()); 210 ASSERT_TRUE(dir.CreateUniqueTempDir());
127 const FilePath kDBFile = dir.path().AppendASCII("fsod.db"); 211 const FilePath kFSDir = dir.path().Append(kFileSystemDirName);
128 EXPECT_FALSE(file_util::PathExists(kDBFile)); 212 EXPECT_FALSE(file_util::PathExists(kFSDir));
213 EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
129 214
130 std::vector<FileSystemOriginDatabase::OriginRecord> origins; 215 std::vector<FileSystemOriginDatabase::OriginRecord> origins;
131 216
132 FileSystemOriginDatabase database(kDBFile); 217 FileSystemOriginDatabase database(kFSDir);
133 EXPECT_TRUE(database.ListAllOrigins(&origins)); 218 EXPECT_TRUE(database.ListAllOrigins(&origins));
134 EXPECT_TRUE(origins.empty()); 219 EXPECT_TRUE(origins.empty());
135 origins.clear(); 220 origins.clear();
136 221
137 std::string origin0("origin0"); 222 std::string origin0("origin0");
138 std::string origin1("origin1"); 223 std::string origin1("origin1");
139 224
140 EXPECT_FALSE(database.HasOriginPath(origin0)); 225 EXPECT_FALSE(database.HasOriginPath(origin0));
141 EXPECT_FALSE(database.HasOriginPath(origin1)); 226 EXPECT_FALSE(database.HasOriginPath(origin1));
142 227
(...skipping 13 matching lines...) Expand all
156 EXPECT_EQ(origins[1].origin, origin1); 241 EXPECT_EQ(origins[1].origin, origin1);
157 EXPECT_EQ(origins[1].path, path1); 242 EXPECT_EQ(origins[1].path, path1);
158 } else { 243 } else {
159 EXPECT_EQ(origins[0].origin, origin1); 244 EXPECT_EQ(origins[0].origin, origin1);
160 EXPECT_EQ(origins[0].path, path1); 245 EXPECT_EQ(origins[0].path, path1);
161 EXPECT_EQ(origins[1].origin, origin0); 246 EXPECT_EQ(origins[1].origin, origin0);
162 EXPECT_EQ(origins[1].path, path0); 247 EXPECT_EQ(origins[1].path, path0);
163 } 248 }
164 } 249 }
165 250
251 TEST(FileSystemOriginDatabaseTest, DatabaseRecoveryTest) {
252 // Checks if FileSystemOriginDatabase properly handles database corruption.
253 // In this test, we'll register some origins to the origin database, then
254 // corrupt database and its log file.
255 // After repairing, the origin database should be consistent even when some
256 // entries lost.
257
258 ScopedTempDir dir;
259 ASSERT_TRUE(dir.CreateUniqueTempDir());
260 const FilePath kFSDir = dir.path().Append(kFileSystemDirName);
261 const FilePath kDBDir = kFSDir.Append(kOriginDatabaseName);
262 EXPECT_FALSE(file_util::PathExists(kFSDir));
263 EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
264
265 const std::string kOrigins[] = {
266 "foo.example.com",
267 "bar.example.com",
268 "baz.example.com",
269 "hoge.example.com",
270 "fuga.example.com",
271 };
272
273 scoped_ptr<FileSystemOriginDatabase> database(
274 new FileSystemOriginDatabase(kFSDir));
275 for (size_t i = 0; i < arraysize(kOrigins); ++i) {
276 FilePath path;
277 EXPECT_FALSE(database->HasOriginPath(kOrigins[i]));
278 EXPECT_TRUE(database->GetPathForOrigin(kOrigins[i], &path));
279 EXPECT_FALSE(path.empty());
280 EXPECT_TRUE(database->GetPathForOrigin(kOrigins[i], &path));
281
282 if (i != 1)
283 EXPECT_TRUE(file_util::CreateDirectory(kFSDir.Append(path)));
284 }
285 database.reset();
286
287 const FilePath kGarbageDir = kFSDir.AppendASCII("foo");
288 const FilePath kGarbageFile = kGarbageDir.AppendASCII("bar");
289 EXPECT_TRUE(file_util::CreateDirectory(kGarbageDir));
290 bool created = false;
291 base::PlatformFileError error;
292 base::PlatformFile file = base::CreatePlatformFile(
293 kGarbageFile,
294 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
295 &created, &error);
296 EXPECT_EQ(base::PLATFORM_FILE_OK, error);
297 EXPECT_TRUE(created);
298 EXPECT_TRUE(base::ClosePlatformFile(file));
299
300 // Corrupt database itself and last log entry to drop last 1 database
301 // operation. The database should detect the corruption and should recover
302 // its consistency after recovery.
303 CorruptDatabase(kDBDir, leveldb::kDescriptorFile,
304 0, std::numeric_limits<size_t>::max());
305 CorruptDatabase(kDBDir, leveldb::kLogFile, -1, 1);
306
307 FilePath path;
308 database.reset(new FileSystemOriginDatabase(kFSDir));
309 std::vector<FileSystemOriginDatabase::OriginRecord> origins_in_db;
310 EXPECT_TRUE(database->ListAllOrigins(&origins_in_db));
311
312 // Expect all but last added origin will be repaired back, and kOrigins[1]
313 // should be dropped due to absence of backing directory.
314 EXPECT_EQ(arraysize(kOrigins) - 2, origins_in_db.size());
315
316 const std::string kOrigin("piyo.example.org");
317 EXPECT_FALSE(database->HasOriginPath(kOrigin));
318 EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path));
319 EXPECT_FALSE(path.empty());
320 EXPECT_TRUE(database->HasOriginPath(kOrigin));
321
322 EXPECT_FALSE(file_util::PathExists(kGarbageFile));
323 EXPECT_FALSE(file_util::PathExists(kGarbageDir));
324 }
325
166 } // namespace fileapi 326 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/file_system_origin_database.cc ('k') | webkit/fileapi/file_system_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698