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 <algorithm> 6#include <functional> 7#include <limits> 8#include <string> 9#include <vector> 10 11#include "base/files/file.h" 12#include "base/files/file_path.h" 13#include "base/files/file_util.h" 14#include "base/files/scoped_temp_dir.h" 15#include "base/stl_util.h" 16#include "content/browser/fileapi/sandbox_database_test_helper.h" 17#include "storage/browser/fileapi/sandbox_origin_database.h" 18#include "storage/common/fileapi/file_system_util.h" 19#include "testing/gtest/include/gtest/gtest.h" 20#include "third_party/leveldatabase/src/db/filename.h" 21#include "third_party/leveldatabase/src/include/leveldb/db.h" 22 23using storage::SandboxOriginDatabase; 24 25namespace content { 26 27namespace { 28const base::FilePath::CharType kFileSystemDirName[] = 29 FILE_PATH_LITERAL("File System"); 30const base::FilePath::CharType kOriginDatabaseName[] = 31 FILE_PATH_LITERAL("Origins"); 32} // namespace 33 34TEST(SandboxOriginDatabaseTest, BasicTest) { 35 base::ScopedTempDir dir; 36 ASSERT_TRUE(dir.CreateUniqueTempDir()); 37 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 38 EXPECT_FALSE(base::PathExists(kFSDir)); 39 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 40 41 SandboxOriginDatabase database(kFSDir, NULL); 42 std::string origin("origin"); 43 44 EXPECT_FALSE(database.HasOriginPath(origin)); 45 // Double-check to make sure that had no side effects. 46 EXPECT_FALSE(database.HasOriginPath(origin)); 47 48 base::FilePath path0; 49 base::FilePath path1; 50 51 // Empty strings aren't valid origins. 52 EXPECT_FALSE(database.GetPathForOrigin(std::string(), &path0)); 53 54 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0)); 55 EXPECT_TRUE(database.HasOriginPath(origin)); 56 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1)); 57 EXPECT_FALSE(path0.empty()); 58 EXPECT_FALSE(path1.empty()); 59 EXPECT_EQ(path0, path1); 60 61 EXPECT_TRUE(base::PathExists(kFSDir.Append(kOriginDatabaseName))); 62} 63 64TEST(SandboxOriginDatabaseTest, TwoPathTest) { 65 base::ScopedTempDir dir; 66 ASSERT_TRUE(dir.CreateUniqueTempDir()); 67 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 68 EXPECT_FALSE(base::PathExists(kFSDir)); 69 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 70 71 SandboxOriginDatabase database(kFSDir, NULL); 72 std::string origin0("origin0"); 73 std::string origin1("origin1"); 74 75 EXPECT_FALSE(database.HasOriginPath(origin0)); 76 EXPECT_FALSE(database.HasOriginPath(origin1)); 77 78 base::FilePath path0; 79 base::FilePath path1; 80 EXPECT_TRUE(database.GetPathForOrigin(origin0, &path0)); 81 EXPECT_TRUE(database.HasOriginPath(origin0)); 82 EXPECT_FALSE(database.HasOriginPath(origin1)); 83 EXPECT_TRUE(database.GetPathForOrigin(origin1, &path1)); 84 EXPECT_TRUE(database.HasOriginPath(origin1)); 85 EXPECT_FALSE(path0.empty()); 86 EXPECT_FALSE(path1.empty()); 87 EXPECT_NE(path0, path1); 88 89 EXPECT_TRUE(base::PathExists(kFSDir.Append(kOriginDatabaseName))); 90} 91 92TEST(SandboxOriginDatabaseTest, DropDatabaseTest) { 93 base::ScopedTempDir dir; 94 ASSERT_TRUE(dir.CreateUniqueTempDir()); 95 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 96 EXPECT_FALSE(base::PathExists(kFSDir)); 97 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 98 99 SandboxOriginDatabase database(kFSDir, NULL); 100 std::string origin("origin"); 101 102 EXPECT_FALSE(database.HasOriginPath(origin)); 103 104 base::FilePath path0; 105 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0)); 106 EXPECT_TRUE(database.HasOriginPath(origin)); 107 EXPECT_FALSE(path0.empty()); 108 109 EXPECT_TRUE(base::PathExists(kFSDir.Append(kOriginDatabaseName))); 110 111 database.DropDatabase(); 112 113 base::FilePath path1; 114 EXPECT_TRUE(database.HasOriginPath(origin)); 115 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1)); 116 EXPECT_FALSE(path1.empty()); 117 EXPECT_EQ(path0, path1); 118} 119 120TEST(SandboxOriginDatabaseTest, DeleteOriginTest) { 121 base::ScopedTempDir dir; 122 ASSERT_TRUE(dir.CreateUniqueTempDir()); 123 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 124 EXPECT_FALSE(base::PathExists(kFSDir)); 125 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 126 127 SandboxOriginDatabase database(kFSDir, NULL); 128 std::string origin("origin"); 129 130 EXPECT_FALSE(database.HasOriginPath(origin)); 131 EXPECT_TRUE(database.RemovePathForOrigin(origin)); 132 133 base::FilePath path0; 134 EXPECT_TRUE(database.GetPathForOrigin(origin, &path0)); 135 EXPECT_TRUE(database.HasOriginPath(origin)); 136 EXPECT_FALSE(path0.empty()); 137 138 EXPECT_TRUE(database.RemovePathForOrigin(origin)); 139 EXPECT_FALSE(database.HasOriginPath(origin)); 140 141 base::FilePath path1; 142 EXPECT_TRUE(database.GetPathForOrigin(origin, &path1)); 143 EXPECT_FALSE(path1.empty()); 144 EXPECT_NE(path0, path1); 145} 146 147TEST(SandboxOriginDatabaseTest, ListOriginsTest) { 148 base::ScopedTempDir dir; 149 ASSERT_TRUE(dir.CreateUniqueTempDir()); 150 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 151 EXPECT_FALSE(base::PathExists(kFSDir)); 152 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 153 154 std::vector<SandboxOriginDatabase::OriginRecord> origins; 155 156 SandboxOriginDatabase database(kFSDir, NULL); 157 EXPECT_TRUE(database.ListAllOrigins(&origins)); 158 EXPECT_TRUE(origins.empty()); 159 origins.clear(); 160 161 std::string origin0("origin0"); 162 std::string origin1("origin1"); 163 164 EXPECT_FALSE(database.HasOriginPath(origin0)); 165 EXPECT_FALSE(database.HasOriginPath(origin1)); 166 167 base::FilePath path0; 168 base::FilePath path1; 169 EXPECT_TRUE(database.GetPathForOrigin(origin0, &path0)); 170 EXPECT_TRUE(database.ListAllOrigins(&origins)); 171 EXPECT_EQ(origins.size(), 1UL); 172 EXPECT_EQ(origins[0].origin, origin0); 173 EXPECT_EQ(origins[0].path, path0); 174 origins.clear(); 175 EXPECT_TRUE(database.GetPathForOrigin(origin1, &path1)); 176 EXPECT_TRUE(database.ListAllOrigins(&origins)); 177 EXPECT_EQ(origins.size(), 2UL); 178 if (origins[0].origin == origin0) { 179 EXPECT_EQ(origins[0].path, path0); 180 EXPECT_EQ(origins[1].origin, origin1); 181 EXPECT_EQ(origins[1].path, path1); 182 } else { 183 EXPECT_EQ(origins[0].origin, origin1); 184 EXPECT_EQ(origins[0].path, path1); 185 EXPECT_EQ(origins[1].origin, origin0); 186 EXPECT_EQ(origins[1].path, path0); 187 } 188} 189 190TEST(SandboxOriginDatabaseTest, DatabaseRecoveryTest) { 191 // Checks if SandboxOriginDatabase properly handles database corruption. 192 // In this test, we'll register some origins to the origin database, then 193 // corrupt database and its log file. 194 // After repairing, the origin database should be consistent even when some 195 // entries lost. 196 197 base::ScopedTempDir dir; 198 ASSERT_TRUE(dir.CreateUniqueTempDir()); 199 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 200 const base::FilePath kDBDir = kFSDir.Append(kOriginDatabaseName); 201 EXPECT_FALSE(base::PathExists(kFSDir)); 202 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 203 204 const std::string kOrigins[] = { 205 "foo.example.com", 206 "bar.example.com", 207 "baz.example.com", 208 "hoge.example.com", 209 "fuga.example.com", 210 }; 211 212 scoped_ptr<SandboxOriginDatabase> database( 213 new SandboxOriginDatabase(kFSDir, NULL)); 214 for (size_t i = 0; i < arraysize(kOrigins); ++i) { 215 base::FilePath path; 216 EXPECT_FALSE(database->HasOriginPath(kOrigins[i])); 217 EXPECT_TRUE(database->GetPathForOrigin(kOrigins[i], &path)); 218 EXPECT_FALSE(path.empty()); 219 EXPECT_TRUE(database->GetPathForOrigin(kOrigins[i], &path)); 220 221 if (i != 1) 222 EXPECT_TRUE(base::CreateDirectory(kFSDir.Append(path))); 223 } 224 database.reset(); 225 226 const base::FilePath kGarbageDir = kFSDir.AppendASCII("foo"); 227 const base::FilePath kGarbageFile = kGarbageDir.AppendASCII("bar"); 228 EXPECT_TRUE(base::CreateDirectory(kGarbageDir)); 229 base::File file(kGarbageFile, 230 base::File::FLAG_CREATE | base::File::FLAG_WRITE); 231 EXPECT_TRUE(file.IsValid()); 232 file.Close(); 233 234 // Corrupt database itself and last log entry to drop last 1 database 235 // operation. The database should detect the corruption and should recover 236 // its consistency after recovery. 237 CorruptDatabase(kDBDir, leveldb::kDescriptorFile, 238 0, std::numeric_limits<size_t>::max()); 239 CorruptDatabase(kDBDir, leveldb::kLogFile, -1, 1); 240 241 base::FilePath path; 242 database.reset(new SandboxOriginDatabase(kFSDir, NULL)); 243 std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db; 244 EXPECT_TRUE(database->ListAllOrigins(&origins_in_db)); 245 246 // Expect all but last added origin will be repaired back, and kOrigins[1] 247 // should be dropped due to absence of backing directory. 248 EXPECT_EQ(arraysize(kOrigins) - 2, origins_in_db.size()); 249 250 const std::string kOrigin("piyo.example.org"); 251 EXPECT_FALSE(database->HasOriginPath(kOrigin)); 252 EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path)); 253 EXPECT_FALSE(path.empty()); 254 EXPECT_TRUE(database->HasOriginPath(kOrigin)); 255 256 EXPECT_FALSE(base::PathExists(kGarbageFile)); 257 EXPECT_FALSE(base::PathExists(kGarbageDir)); 258} 259 260TEST(SandboxOriginDatabaseTest, DatabaseRecoveryForMissingDBFileTest) { 261 const leveldb::FileType kLevelDBFileTypes[] = { 262 leveldb::kLogFile, 263 leveldb::kDBLockFile, 264 leveldb::kTableFile, 265 leveldb::kDescriptorFile, 266 leveldb::kCurrentFile, 267 leveldb::kTempFile, 268 leveldb::kInfoLogFile, 269 }; 270 271 for (size_t i = 0; i < arraysize(kLevelDBFileTypes); ++i) { 272 base::ScopedTempDir dir; 273 ASSERT_TRUE(dir.CreateUniqueTempDir()); 274 const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName); 275 const base::FilePath kDBDir = kFSDir.Append(kOriginDatabaseName); 276 EXPECT_FALSE(base::PathExists(kFSDir)); 277 EXPECT_TRUE(base::CreateDirectory(kFSDir)); 278 279 const std::string kOrigin = "foo.example.com"; 280 base::FilePath path; 281 282 scoped_ptr<SandboxOriginDatabase> database( 283 new SandboxOriginDatabase(kFSDir, NULL)); 284 EXPECT_FALSE(database->HasOriginPath(kOrigin)); 285 EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path)); 286 EXPECT_FALSE(path.empty()); 287 EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path)); 288 EXPECT_TRUE(base::CreateDirectory(kFSDir.Append(path))); 289 database.reset(); 290 291 DeleteDatabaseFile(kDBDir, kLevelDBFileTypes[i]); 292 293 database.reset(new SandboxOriginDatabase(kFSDir, NULL)); 294 std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db; 295 EXPECT_TRUE(database->ListAllOrigins(&origins_in_db)); 296 297 const std::string kOrigin2("piyo.example.org"); 298 EXPECT_FALSE(database->HasOriginPath(kOrigin2)); 299 EXPECT_TRUE(database->GetPathForOrigin(kOrigin2, &path)); 300 EXPECT_FALSE(path.empty()); 301 EXPECT_TRUE(database->HasOriginPath(kOrigin2)); 302 } 303} 304 305} // namespace content 306