Refactor FacetManager into a separate file.
[chromium-blink-merge.git] / content / browser / fileapi / obfuscated_file_util_unittest.cc
blob7abaf7e895881d72d7be0bc97ec7d5c4f52ebd8f
1 // Copyright 2013 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.
5 #include <set>
6 #include <string>
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/files/file.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/run_loop.h"
16 #include "content/browser/fileapi/mock_file_change_observer.h"
17 #include "content/public/test/async_file_test_helper.h"
18 #include "content/public/test/mock_special_storage_policy.h"
19 #include "content/public/test/sandbox_file_system_test_helper.h"
20 #include "content/public/test/test_file_system_context.h"
21 #include "content/test/fileapi_test_file_set.h"
22 #include "storage/browser/fileapi/external_mount_points.h"
23 #include "storage/browser/fileapi/file_system_backend.h"
24 #include "storage/browser/fileapi/file_system_context.h"
25 #include "storage/browser/fileapi/file_system_operation_context.h"
26 #include "storage/browser/fileapi/file_system_usage_cache.h"
27 #include "storage/browser/fileapi/obfuscated_file_util.h"
28 #include "storage/browser/fileapi/sandbox_directory_database.h"
29 #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
30 #include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
31 #include "storage/browser/fileapi/sandbox_origin_database.h"
32 #include "storage/browser/quota/quota_manager.h"
33 #include "storage/common/database/database_identifier.h"
34 #include "storage/common/quota/quota_types.h"
35 #include "testing/gtest/include/gtest/gtest.h"
37 using content::AsyncFileTestHelper;
38 using storage::FileSystemContext;
39 using storage::FileSystemOperation;
40 using storage::FileSystemOperationContext;
41 using storage::FileSystemURL;
42 using storage::ObfuscatedFileUtil;
43 using storage::SandboxDirectoryDatabase;
44 using storage::SandboxIsolatedOriginDatabase;
45 using storage::kFileSystemTypeTemporary;
46 using storage::kFileSystemTypePersistent;
48 namespace content {
50 namespace {
52 bool FileExists(const base::FilePath& path) {
53 return base::PathExists(path) && !base::DirectoryExists(path);
56 int64 GetSize(const base::FilePath& path) {
57 int64 size;
58 EXPECT_TRUE(base::GetFileSize(path, &size));
59 return size;
62 // After a move, the dest exists and the source doesn't.
63 // After a copy, both source and dest exist.
64 struct CopyMoveTestCaseRecord {
65 bool is_copy_not_move;
66 const char source_path[64];
67 const char dest_path[64];
68 bool cause_overwrite;
71 const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
72 // This is the combinatoric set of:
73 // rename vs. same-name
74 // different directory vs. same directory
75 // overwrite vs. no-overwrite
76 // copy vs. move
77 // We can never be called with source and destination paths identical, so
78 // those cases are omitted.
79 {true, "dir0/file0", "dir0/file1", false},
80 {false, "dir0/file0", "dir0/file1", false},
81 {true, "dir0/file0", "dir0/file1", true},
82 {false, "dir0/file0", "dir0/file1", true},
84 {true, "dir0/file0", "dir1/file0", false},
85 {false, "dir0/file0", "dir1/file0", false},
86 {true, "dir0/file0", "dir1/file0", true},
87 {false, "dir0/file0", "dir1/file0", true},
88 {true, "dir0/file0", "dir1/file1", false},
89 {false, "dir0/file0", "dir1/file1", false},
90 {true, "dir0/file0", "dir1/file1", true},
91 {false, "dir0/file0", "dir1/file1", true},
94 struct OriginEnumerationTestRecord {
95 std::string origin_url;
96 bool has_temporary;
97 bool has_persistent;
100 const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
101 {"http://example.com", false, true},
102 {"http://example1.com", true, false},
103 {"https://example1.com", true, true},
104 {"file://", false, true},
105 {"http://example.com:8000", false, true},
108 FileSystemURL FileSystemURLAppend(
109 const FileSystemURL& url, const base::FilePath::StringType& child) {
110 return FileSystemURL::CreateForTest(
111 url.origin(), url.mount_type(), url.virtual_path().Append(child));
114 FileSystemURL FileSystemURLAppendUTF8(
115 const FileSystemURL& url, const std::string& child) {
116 return FileSystemURL::CreateForTest(
117 url.origin(),
118 url.mount_type(),
119 url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child)));
122 FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
123 return FileSystemURL::CreateForTest(
124 url.origin(),
125 url.mount_type(),
126 storage::VirtualPath::DirName(url.virtual_path()));
129 std::string GetTypeString(storage::FileSystemType type) {
130 return storage::SandboxFileSystemBackendDelegate::GetTypeString(type);
133 bool HasFileSystemType(ObfuscatedFileUtil::AbstractOriginEnumerator* enumerator,
134 storage::FileSystemType type) {
135 return enumerator->HasTypeDirectory(GetTypeString(type));
138 } // namespace
140 // TODO(ericu): The vast majority of this and the other FSFU subclass tests
141 // could theoretically be shared. It would basically be a FSFU interface
142 // compliance test, and only the subclass-specific bits that look into the
143 // implementation would need to be written per-subclass.
144 class ObfuscatedFileUtilTest : public testing::Test {
145 public:
146 ObfuscatedFileUtilTest()
147 : origin_(GURL("http://www.example.com")),
148 type_(storage::kFileSystemTypeTemporary),
149 sandbox_file_system_(origin_, type_),
150 quota_status_(storage::kQuotaStatusUnknown),
151 usage_(-1),
152 weak_factory_(this) {}
154 void SetUp() override {
155 ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
157 storage_policy_ = new MockSpecialStoragePolicy();
159 quota_manager_ =
160 new storage::QuotaManager(false /* is_incognito */,
161 data_dir_.path(),
162 base::MessageLoopProxy::current().get(),
163 base::MessageLoopProxy::current().get(),
164 storage_policy_.get());
166 // Every time we create a new sandbox_file_system helper,
167 // it creates another context, which creates another path manager,
168 // another sandbox_backend, and another OFU.
169 // We need to pass in the context to skip all that.
170 file_system_context_ = CreateFileSystemContextForTesting(
171 quota_manager_->proxy(),
172 data_dir_.path());
174 sandbox_file_system_.SetUp(file_system_context_.get());
176 change_observers_ =
177 storage::MockFileChangeObserver::CreateList(&change_observer_);
180 void TearDown() override {
181 quota_manager_ = NULL;
182 sandbox_file_system_.TearDown();
185 scoped_ptr<FileSystemOperationContext> LimitedContext(
186 int64 allowed_bytes_growth) {
187 scoped_ptr<FileSystemOperationContext> context(
188 sandbox_file_system_.NewOperationContext());
189 context->set_allowed_bytes_growth(allowed_bytes_growth);
190 return context.Pass();
193 scoped_ptr<FileSystemOperationContext> UnlimitedContext() {
194 return LimitedContext(kint64max);
197 FileSystemOperationContext* NewContext(
198 SandboxFileSystemTestHelper* file_system) {
199 change_observer()->ResetCount();
200 FileSystemOperationContext* context;
201 if (file_system)
202 context = file_system->NewOperationContext();
203 else
204 context = sandbox_file_system_.NewOperationContext();
205 // Setting allowed_bytes_growth big enough for all tests.
206 context->set_allowed_bytes_growth(1024 * 1024);
207 context->set_change_observers(change_observers());
208 return context;
211 const storage::ChangeObserverList& change_observers() const {
212 return change_observers_;
215 storage::MockFileChangeObserver* change_observer() {
216 return &change_observer_;
219 // This can only be used after SetUp has run and created file_system_context_
220 // and obfuscated_file_util_.
221 // Use this for tests which need to run in multiple origins; we need a test
222 // helper per origin.
223 SandboxFileSystemTestHelper* NewFileSystem(const GURL& origin,
224 storage::FileSystemType type) {
225 SandboxFileSystemTestHelper* file_system =
226 new SandboxFileSystemTestHelper(origin, type);
228 file_system->SetUp(file_system_context_.get());
229 return file_system;
232 scoped_ptr<ObfuscatedFileUtil> CreateObfuscatedFileUtil(
233 storage::SpecialStoragePolicy* storage_policy) {
234 return scoped_ptr<ObfuscatedFileUtil>(
235 ObfuscatedFileUtil::CreateForTesting(
236 storage_policy, data_dir_path(), NULL,
237 base::MessageLoopProxy::current().get()));
240 ObfuscatedFileUtil* ofu() {
241 return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util());
244 const base::FilePath& test_directory() const {
245 return data_dir_.path();
248 const GURL& origin() const {
249 return origin_;
252 storage::FileSystemType type() const { return type_; }
254 std::string type_string() const {
255 return GetTypeString(type_);
258 int64 ComputeTotalFileSize() {
259 return sandbox_file_system_.ComputeCurrentOriginUsage() -
260 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
263 void GetUsageFromQuotaManager() {
264 int64 quota = -1;
265 quota_status_ =
266 AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
267 origin(),
268 sandbox_file_system_.type(),
269 &usage_,
270 &quota);
271 EXPECT_EQ(storage::kQuotaStatusOk, quota_status_);
274 void RevokeUsageCache() {
275 quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type());
276 usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath());
279 int64 SizeByQuotaUtil() {
280 return sandbox_file_system_.GetCachedOriginUsage();
283 int64 SizeInUsageFile() {
284 base::RunLoop().RunUntilIdle();
285 int64 usage = 0;
286 return usage_cache()->GetUsage(
287 sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1;
290 bool PathExists(const FileSystemURL& url) {
291 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
292 base::File::Info file_info;
293 base::FilePath platform_path;
294 base::File::Error error = ofu()->GetFileInfo(
295 context.get(), url, &file_info, &platform_path);
296 return error == base::File::FILE_OK;
299 bool DirectoryExists(const FileSystemURL& url) {
300 return AsyncFileTestHelper::DirectoryExists(file_system_context(), url);
303 int64 usage() const { return usage_; }
304 storage::FileSystemUsageCache* usage_cache() {
305 return sandbox_file_system_.usage_cache();
308 FileSystemURL CreateURLFromUTF8(const std::string& path) {
309 return sandbox_file_system_.CreateURLFromUTF8(path);
312 int64 PathCost(const FileSystemURL& url) {
313 return ObfuscatedFileUtil::ComputeFilePathCost(url.path());
316 FileSystemURL CreateURL(const base::FilePath& path) {
317 return sandbox_file_system_.CreateURL(path);
320 void CheckFileAndCloseHandle(const FileSystemURL& url, base::File file) {
321 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
322 base::FilePath local_path;
323 EXPECT_EQ(base::File::FILE_OK,
324 ofu()->GetLocalFilePath(context.get(), url, &local_path));
326 base::File::Info file_info0;
327 base::FilePath data_path;
328 EXPECT_EQ(base::File::FILE_OK,
329 ofu()->GetFileInfo(context.get(), url, &file_info0, &data_path));
330 EXPECT_EQ(data_path, local_path);
331 EXPECT_TRUE(FileExists(data_path));
332 EXPECT_EQ(0, GetSize(data_path));
334 const char data[] = "test data";
335 const int length = arraysize(data) - 1;
337 if (!file.IsValid()) {
338 file.Initialize(data_path,
339 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
340 ASSERT_TRUE(file.IsValid());
341 EXPECT_FALSE(file.created());
343 ASSERT_EQ(length, file.Write(0, data, length));
344 file.Close();
346 base::File::Info file_info1;
347 EXPECT_EQ(length, GetSize(data_path));
348 context.reset(NewContext(NULL));
349 EXPECT_EQ(base::File::FILE_OK,
350 ofu()->GetFileInfo(context.get(), url, &file_info1, &data_path));
351 EXPECT_EQ(data_path, local_path);
353 EXPECT_FALSE(file_info0.is_directory);
354 EXPECT_FALSE(file_info1.is_directory);
355 EXPECT_FALSE(file_info0.is_symbolic_link);
356 EXPECT_FALSE(file_info1.is_symbolic_link);
357 EXPECT_EQ(0, file_info0.size);
358 EXPECT_EQ(length, file_info1.size);
359 EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
361 context.reset(NewContext(NULL));
362 EXPECT_EQ(base::File::FILE_OK,
363 ofu()->Truncate(context.get(), url, length * 2));
364 EXPECT_EQ(length * 2, GetSize(data_path));
366 context.reset(NewContext(NULL));
367 EXPECT_EQ(base::File::FILE_OK,
368 ofu()->Truncate(context.get(), url, 0));
369 EXPECT_EQ(0, GetSize(data_path));
372 void ValidateTestDirectory(
373 const FileSystemURL& root_url,
374 const std::set<base::FilePath::StringType>& files,
375 const std::set<base::FilePath::StringType>& directories) {
376 scoped_ptr<FileSystemOperationContext> context;
377 std::set<base::FilePath::StringType>::const_iterator iter;
378 for (iter = files.begin(); iter != files.end(); ++iter) {
379 bool created = true;
380 context.reset(NewContext(NULL));
381 ASSERT_EQ(base::File::FILE_OK,
382 ofu()->EnsureFileExists(context.get(),
383 FileSystemURLAppend(root_url, *iter),
384 &created));
385 ASSERT_FALSE(created);
387 for (iter = directories.begin(); iter != directories.end(); ++iter) {
388 context.reset(NewContext(NULL));
389 EXPECT_TRUE(DirectoryExists(
390 FileSystemURLAppend(root_url, *iter)));
394 class UsageVerifyHelper {
395 public:
396 UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context,
397 SandboxFileSystemTestHelper* file_system,
398 int64 expected_usage)
399 : context_(context.Pass()),
400 sandbox_file_system_(file_system),
401 expected_usage_(expected_usage) {}
403 ~UsageVerifyHelper() {
404 base::RunLoop().RunUntilIdle();
405 Check();
408 FileSystemOperationContext* context() {
409 return context_.get();
412 private:
413 void Check() {
414 ASSERT_EQ(expected_usage_,
415 sandbox_file_system_->GetCachedOriginUsage());
418 scoped_ptr<FileSystemOperationContext> context_;
419 SandboxFileSystemTestHelper* sandbox_file_system_;
420 int64 expected_usage_;
423 scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) {
424 int64 usage = sandbox_file_system_.GetCachedOriginUsage();
425 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
426 LimitedContext(requested_growth),
427 &sandbox_file_system_, usage + requested_growth));
430 scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) {
431 int64 usage = sandbox_file_system_.GetCachedOriginUsage();
432 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
433 LimitedContext(requested_growth - 1), &sandbox_file_system_, usage));
436 void FillTestDirectory(
437 const FileSystemURL& root_url,
438 std::set<base::FilePath::StringType>* files,
439 std::set<base::FilePath::StringType>* directories) {
440 scoped_ptr<FileSystemOperationContext> context;
441 std::vector<storage::DirectoryEntry> entries;
442 EXPECT_EQ(base::File::FILE_OK,
443 AsyncFileTestHelper::ReadDirectory(file_system_context(),
444 root_url, &entries));
445 EXPECT_EQ(0UL, entries.size());
447 files->clear();
448 files->insert(FILE_PATH_LITERAL("first"));
449 files->insert(FILE_PATH_LITERAL("second"));
450 files->insert(FILE_PATH_LITERAL("third"));
451 directories->clear();
452 directories->insert(FILE_PATH_LITERAL("fourth"));
453 directories->insert(FILE_PATH_LITERAL("fifth"));
454 directories->insert(FILE_PATH_LITERAL("sixth"));
455 std::set<base::FilePath::StringType>::iterator iter;
456 for (iter = files->begin(); iter != files->end(); ++iter) {
457 bool created = false;
458 context.reset(NewContext(NULL));
459 ASSERT_EQ(base::File::FILE_OK,
460 ofu()->EnsureFileExists(context.get(),
461 FileSystemURLAppend(root_url, *iter),
462 &created));
463 ASSERT_TRUE(created);
465 for (iter = directories->begin(); iter != directories->end(); ++iter) {
466 bool exclusive = true;
467 bool recursive = false;
468 context.reset(NewContext(NULL));
469 EXPECT_EQ(base::File::FILE_OK,
470 ofu()->CreateDirectory(context.get(),
471 FileSystemURLAppend(root_url, *iter),
472 exclusive, recursive));
474 ValidateTestDirectory(root_url, *files, *directories);
477 void TestReadDirectoryHelper(const FileSystemURL& root_url) {
478 std::set<base::FilePath::StringType> files;
479 std::set<base::FilePath::StringType> directories;
480 FillTestDirectory(root_url, &files, &directories);
482 scoped_ptr<FileSystemOperationContext> context;
483 std::vector<storage::DirectoryEntry> entries;
484 context.reset(NewContext(NULL));
485 EXPECT_EQ(base::File::FILE_OK,
486 AsyncFileTestHelper::ReadDirectory(
487 file_system_context(), root_url, &entries));
488 std::vector<storage::DirectoryEntry>::iterator entry_iter;
489 EXPECT_EQ(files.size() + directories.size(), entries.size());
490 EXPECT_TRUE(change_observer()->HasNoChange());
491 for (entry_iter = entries.begin(); entry_iter != entries.end();
492 ++entry_iter) {
493 const storage::DirectoryEntry& entry = *entry_iter;
494 std::set<base::FilePath::StringType>::iterator iter =
495 files.find(entry.name);
496 if (iter != files.end()) {
497 EXPECT_FALSE(entry.is_directory);
498 files.erase(iter);
499 continue;
501 iter = directories.find(entry.name);
502 EXPECT_FALSE(directories.end() == iter);
503 EXPECT_TRUE(entry.is_directory);
504 directories.erase(iter);
508 void TestTouchHelper(const FileSystemURL& url, bool is_file) {
509 base::Time last_access_time = base::Time::Now();
510 base::Time last_modified_time = base::Time::Now();
512 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
513 EXPECT_EQ(base::File::FILE_OK,
514 ofu()->Touch(context.get(), url, last_access_time,
515 last_modified_time));
516 // Currently we fire no change notifications for Touch.
517 EXPECT_TRUE(change_observer()->HasNoChange());
518 base::FilePath local_path;
519 base::File::Info file_info;
520 context.reset(NewContext(NULL));
521 EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(
522 context.get(), url, &file_info, &local_path));
523 // We compare as time_t here to lower our resolution, to avoid false
524 // negatives caused by conversion to the local filesystem's native
525 // representation and back.
526 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
528 context.reset(NewContext(NULL));
529 last_modified_time += base::TimeDelta::FromHours(1);
530 last_access_time += base::TimeDelta::FromHours(14);
531 EXPECT_EQ(base::File::FILE_OK,
532 ofu()->Touch(context.get(), url, last_access_time,
533 last_modified_time));
534 EXPECT_TRUE(change_observer()->HasNoChange());
535 context.reset(NewContext(NULL));
536 EXPECT_EQ(base::File::FILE_OK,
537 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
538 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
539 if (is_file) // Directories in OFU don't support atime.
540 EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT());
543 void TestCopyInForeignFileHelper(bool overwrite) {
544 base::ScopedTempDir source_dir;
545 ASSERT_TRUE(source_dir.CreateUniqueTempDir());
546 base::FilePath root_file_path = source_dir.path();
547 base::FilePath src_file_path = root_file_path.AppendASCII("file_name");
548 FileSystemURL dest_url = CreateURLFromUTF8("new file");
549 int64 src_file_length = 87;
551 base::File file(src_file_path,
552 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
553 ASSERT_TRUE(file.IsValid());
554 EXPECT_TRUE(file.created());
555 ASSERT_TRUE(file.SetLength(src_file_length));
556 file.Close();
558 scoped_ptr<FileSystemOperationContext> context;
560 if (overwrite) {
561 context.reset(NewContext(NULL));
562 bool created = false;
563 EXPECT_EQ(base::File::FILE_OK,
564 ofu()->EnsureFileExists(context.get(), dest_url, &created));
565 EXPECT_TRUE(created);
567 // We must have observed one (and only one) create_file_count.
568 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
569 EXPECT_TRUE(change_observer()->HasNoChange());
572 const int64 path_cost =
573 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
574 if (!overwrite) {
575 // Verify that file creation requires sufficient quota for the path.
576 context.reset(NewContext(NULL));
577 context->set_allowed_bytes_growth(path_cost + src_file_length - 1);
578 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
579 ofu()->CopyInForeignFile(context.get(),
580 src_file_path, dest_url));
583 context.reset(NewContext(NULL));
584 context->set_allowed_bytes_growth(path_cost + src_file_length);
585 EXPECT_EQ(base::File::FILE_OK,
586 ofu()->CopyInForeignFile(context.get(),
587 src_file_path, dest_url));
589 EXPECT_TRUE(PathExists(dest_url));
590 EXPECT_FALSE(DirectoryExists(dest_url));
592 context.reset(NewContext(NULL));
593 base::File::Info file_info;
594 base::FilePath data_path;
595 EXPECT_EQ(base::File::FILE_OK,
596 ofu()->GetFileInfo(context.get(), dest_url, &file_info,
597 &data_path));
598 EXPECT_NE(data_path, src_file_path);
599 EXPECT_TRUE(FileExists(data_path));
600 EXPECT_EQ(src_file_length, GetSize(data_path));
602 EXPECT_EQ(base::File::FILE_OK,
603 ofu()->DeleteFile(context.get(), dest_url));
606 void ClearTimestamp(const FileSystemURL& url) {
607 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
608 EXPECT_EQ(base::File::FILE_OK,
609 ofu()->Touch(context.get(), url, base::Time(), base::Time()));
610 EXPECT_EQ(base::Time(), GetModifiedTime(url));
613 base::Time GetModifiedTime(const FileSystemURL& url) {
614 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
615 base::FilePath data_path;
616 base::File::Info file_info;
617 context.reset(NewContext(NULL));
618 EXPECT_EQ(base::File::FILE_OK,
619 ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
620 EXPECT_TRUE(change_observer()->HasNoChange());
621 return file_info.last_modified;
624 void TestDirectoryTimestampHelper(const FileSystemURL& base_dir,
625 bool copy,
626 bool overwrite) {
627 scoped_ptr<FileSystemOperationContext> context;
628 const FileSystemURL src_dir_url(
629 FileSystemURLAppendUTF8(base_dir, "foo_dir"));
630 const FileSystemURL dest_dir_url(
631 FileSystemURLAppendUTF8(base_dir, "bar_dir"));
633 const FileSystemURL src_file_url(
634 FileSystemURLAppendUTF8(src_dir_url, "hoge"));
635 const FileSystemURL dest_file_url(
636 FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
638 context.reset(NewContext(NULL));
639 EXPECT_EQ(base::File::FILE_OK,
640 ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
641 context.reset(NewContext(NULL));
642 EXPECT_EQ(base::File::FILE_OK,
643 ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
645 bool created = false;
646 context.reset(NewContext(NULL));
647 EXPECT_EQ(base::File::FILE_OK,
648 ofu()->EnsureFileExists(context.get(), src_file_url, &created));
649 if (overwrite) {
650 context.reset(NewContext(NULL));
651 EXPECT_EQ(base::File::FILE_OK,
652 ofu()->EnsureFileExists(context.get(),
653 dest_file_url, &created));
656 ClearTimestamp(src_dir_url);
657 ClearTimestamp(dest_dir_url);
658 context.reset(NewContext(NULL));
659 EXPECT_EQ(base::File::FILE_OK,
660 ofu()->CopyOrMoveFile(context.get(),
661 src_file_url, dest_file_url,
662 FileSystemOperation::OPTION_NONE,
663 copy));
664 if (copy)
665 EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url));
666 else
667 EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url));
668 EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url));
671 void MaybeDropDatabasesAliveCaseTestBody() {
672 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(NULL);
673 file_util->InitOriginDatabase(GURL(), true /*create*/);
674 ASSERT_TRUE(file_util->origin_database_ != NULL);
676 // Callback to Drop DB is called while ObfuscatedFileUtilTest is
677 // still alive.
678 file_util->db_flush_delay_seconds_ = 0;
679 file_util->MarkUsed();
680 base::RunLoop().RunUntilIdle();
682 ASSERT_TRUE(file_util->origin_database_ == NULL);
685 void MaybeDropDatabasesAlreadyDeletedCaseTestBody() {
686 // Run message loop after OFU is already deleted to make sure callback
687 // doesn't cause a crash for use after free.
689 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(NULL);
690 file_util->InitOriginDatabase(GURL(), true /*create*/);
691 file_util->db_flush_delay_seconds_ = 0;
692 file_util->MarkUsed();
695 // At this point the callback is still in the message queue but OFU is gone.
696 base::RunLoop().RunUntilIdle();
699 void DestroyDirectoryDatabase_IsolatedTestBody() {
700 storage_policy_->AddIsolated(origin_);
701 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(
702 storage_policy_.get());
703 const FileSystemURL url = FileSystemURL::CreateForTest(
704 origin_, kFileSystemTypePersistent, base::FilePath());
706 // Create DirectoryDatabase for isolated origin.
707 SandboxDirectoryDatabase* db =
708 file_util->GetDirectoryDatabase(url, true /* create */);
709 ASSERT_TRUE(db != NULL);
711 // Destory it.
712 file_util->DestroyDirectoryDatabase(
713 url.origin(), GetTypeString(url.type()));
714 ASSERT_TRUE(file_util->directories_.empty());
717 void GetDirectoryDatabase_IsolatedTestBody() {
718 storage_policy_->AddIsolated(origin_);
719 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(
720 storage_policy_.get());
721 const FileSystemURL url = FileSystemURL::CreateForTest(
722 origin_, kFileSystemTypePersistent, base::FilePath());
724 // Create DirectoryDatabase for isolated origin.
725 SandboxDirectoryDatabase* db =
726 file_util->GetDirectoryDatabase(url, true /* create */);
727 ASSERT_TRUE(db != NULL);
728 ASSERT_EQ(1U, file_util->directories_.size());
730 // Remove isolated.
731 storage_policy_->RemoveIsolated(url.origin());
733 // This should still get the same database.
734 SandboxDirectoryDatabase* db2 =
735 file_util->GetDirectoryDatabase(url, false /* create */);
736 ASSERT_EQ(db, db2);
739 void MigrationBackFromIsolatedTestBody() {
740 std::string kFakeDirectoryData("0123456789");
741 base::FilePath old_directory_db_path;
743 // Initialize the directory with one origin using
744 // SandboxIsolatedOriginDatabase.
746 std::string origin_string = storage::GetIdentifierFromOrigin(origin_);
747 SandboxIsolatedOriginDatabase database_old(
748 origin_string, data_dir_path(),
749 base::FilePath(
750 SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory));
751 base::FilePath path;
752 EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path));
753 EXPECT_FALSE(path.empty());
755 // Populate the origin directory with some fake data.
756 old_directory_db_path = data_dir_path().Append(path);
757 ASSERT_TRUE(base::CreateDirectory(old_directory_db_path));
758 EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()),
759 base::WriteFile(old_directory_db_path.AppendASCII("dummy"),
760 kFakeDirectoryData.data(),
761 kFakeDirectoryData.size()));
764 storage_policy_->AddIsolated(origin_);
765 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(
766 storage_policy_.get());
767 base::File::Error error = base::File::FILE_ERROR_FAILED;
768 base::FilePath origin_directory = file_util->GetDirectoryForOrigin(
769 origin_, true /* create */, &error);
770 EXPECT_EQ(base::File::FILE_OK, error);
772 // The database is migrated from the old one.
773 EXPECT_TRUE(base::DirectoryExists(origin_directory));
774 EXPECT_FALSE(base::DirectoryExists(old_directory_db_path));
776 // Check we see the same contents in the new origin directory.
777 std::string origin_db_data;
778 EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy")));
779 EXPECT_TRUE(base::ReadFileToString(
780 origin_directory.AppendASCII("dummy"), &origin_db_data));
781 EXPECT_EQ(kFakeDirectoryData, origin_db_data);
784 int64 ComputeCurrentUsage() {
785 return sandbox_file_system_.ComputeCurrentOriginUsage() -
786 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
789 FileSystemContext* file_system_context() {
790 return sandbox_file_system_.file_system_context();
793 const base::FilePath& data_dir_path() const {
794 return data_dir_.path();
797 protected:
798 base::ScopedTempDir data_dir_;
799 base::MessageLoopForIO message_loop_;
800 scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
801 scoped_refptr<storage::QuotaManager> quota_manager_;
802 scoped_refptr<FileSystemContext> file_system_context_;
803 GURL origin_;
804 storage::FileSystemType type_;
805 SandboxFileSystemTestHelper sandbox_file_system_;
806 storage::QuotaStatusCode quota_status_;
807 int64 usage_;
808 storage::MockFileChangeObserver change_observer_;
809 storage::ChangeObserverList change_observers_;
810 base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_;
812 private:
813 DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest);
816 TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
817 FileSystemURL url = CreateURLFromUTF8("fake/file");
818 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
819 int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE;
821 base::File file = ofu()->CreateOrOpen(context.get(), url, file_flags);
822 EXPECT_FALSE(file.IsValid());
823 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
825 context.reset(NewContext(NULL));
826 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
827 ofu()->DeleteFile(context.get(), url));
829 url = CreateURLFromUTF8("test file");
831 EXPECT_TRUE(change_observer()->HasNoChange());
833 // Verify that file creation requires sufficient quota for the path.
834 context.reset(NewContext(NULL));
835 context->set_allowed_bytes_growth(
836 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
837 file = ofu()->CreateOrOpen(context.get(), url, file_flags);
838 EXPECT_FALSE(file.IsValid());
839 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, file.error_details());
841 context.reset(NewContext(NULL));
842 context->set_allowed_bytes_growth(
843 ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
844 file = ofu()->CreateOrOpen(context.get(), url, file_flags);
845 EXPECT_TRUE(file.IsValid());
846 ASSERT_TRUE(file.created());
847 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
849 CheckFileAndCloseHandle(url, file.Pass());
851 context.reset(NewContext(NULL));
852 base::FilePath local_path;
853 EXPECT_EQ(base::File::FILE_OK,
854 ofu()->GetLocalFilePath(context.get(), url, &local_path));
855 EXPECT_TRUE(base::PathExists(local_path));
857 // Verify that deleting a file isn't stopped by zero quota, and that it frees
858 // up quote from its path.
859 context.reset(NewContext(NULL));
860 context->set_allowed_bytes_growth(0);
861 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
862 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
863 EXPECT_FALSE(base::PathExists(local_path));
864 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
865 context->allowed_bytes_growth());
867 context.reset(NewContext(NULL));
868 bool exclusive = true;
869 bool recursive = true;
870 FileSystemURL directory_url = CreateURLFromUTF8(
871 "series/of/directories");
872 url = FileSystemURLAppendUTF8(directory_url, "file name");
873 EXPECT_EQ(base::File::FILE_OK,
874 ofu()->CreateDirectory(context.get(), directory_url, exclusive,
875 recursive));
876 // The oepration created 3 directories recursively.
877 EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
879 context.reset(NewContext(NULL));
880 file = ofu()->CreateOrOpen(context.get(), url, file_flags);
881 ASSERT_TRUE(file.IsValid());
882 ASSERT_TRUE(file.created());
883 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
885 CheckFileAndCloseHandle(url, file.Pass());
887 context.reset(NewContext(NULL));
888 EXPECT_EQ(base::File::FILE_OK,
889 ofu()->GetLocalFilePath(context.get(), url, &local_path));
890 EXPECT_TRUE(base::PathExists(local_path));
892 context.reset(NewContext(NULL));
893 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
894 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
895 EXPECT_FALSE(base::PathExists(local_path));
897 // Make sure we have no unexpected changes.
898 EXPECT_TRUE(change_observer()->HasNoChange());
901 TEST_F(ObfuscatedFileUtilTest, TestTruncate) {
902 bool created = false;
903 FileSystemURL url = CreateURLFromUTF8("file");
904 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
906 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
907 ofu()->Truncate(context.get(), url, 4));
909 context.reset(NewContext(NULL));
910 ASSERT_EQ(base::File::FILE_OK,
911 ofu()->EnsureFileExists(context.get(), url, &created));
912 ASSERT_TRUE(created);
913 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
915 context.reset(NewContext(NULL));
916 base::FilePath local_path;
917 EXPECT_EQ(base::File::FILE_OK,
918 ofu()->GetLocalFilePath(context.get(), url, &local_path));
919 EXPECT_EQ(0, GetSize(local_path));
921 context.reset(NewContext(NULL));
922 EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 10));
923 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
924 EXPECT_EQ(10, GetSize(local_path));
926 context.reset(NewContext(NULL));
927 EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 1));
928 EXPECT_EQ(1, GetSize(local_path));
929 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
931 EXPECT_FALSE(DirectoryExists(url));
932 EXPECT_TRUE(PathExists(url));
934 // Make sure we have no unexpected changes.
935 EXPECT_TRUE(change_observer()->HasNoChange());
938 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
939 bool created = false;
940 FileSystemURL url = CreateURLFromUTF8("file");
942 ASSERT_EQ(base::File::FILE_OK,
943 ofu()->EnsureFileExists(
944 AllowUsageIncrease(PathCost(url))->context(),
945 url, &created));
946 ASSERT_TRUE(created);
947 ASSERT_EQ(0, ComputeTotalFileSize());
949 ASSERT_EQ(base::File::FILE_OK,
950 ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020));
951 ASSERT_EQ(1020, ComputeTotalFileSize());
953 ASSERT_EQ(base::File::FILE_OK,
954 ofu()->Truncate(AllowUsageIncrease(-1020)->context(), url, 0));
955 ASSERT_EQ(0, ComputeTotalFileSize());
957 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
958 ofu()->Truncate(DisallowUsageIncrease(1021)->context(),
959 url, 1021));
960 ASSERT_EQ(0, ComputeTotalFileSize());
962 EXPECT_EQ(base::File::FILE_OK,
963 ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020));
964 ASSERT_EQ(1020, ComputeTotalFileSize());
966 EXPECT_EQ(base::File::FILE_OK,
967 ofu()->Truncate(AllowUsageIncrease(0)->context(), url, 1020));
968 ASSERT_EQ(1020, ComputeTotalFileSize());
970 // quota exceeded
972 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1);
973 helper->context()->set_allowed_bytes_growth(
974 helper->context()->allowed_bytes_growth() - 1);
975 EXPECT_EQ(base::File::FILE_OK,
976 ofu()->Truncate(helper->context(), url, 1019));
977 ASSERT_EQ(1019, ComputeTotalFileSize());
980 // Delete backing file to make following truncation fail.
981 base::FilePath local_path;
982 ASSERT_EQ(base::File::FILE_OK,
983 ofu()->GetLocalFilePath(UnlimitedContext().get(), url,
984 &local_path));
985 ASSERT_FALSE(local_path.empty());
986 ASSERT_TRUE(base::DeleteFile(local_path, false));
988 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
989 ofu()->Truncate(LimitedContext(1234).get(), url, 1234));
990 ASSERT_EQ(0, ComputeTotalFileSize());
993 TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) {
994 FileSystemURL url = CreateURLFromUTF8("fake/file");
995 bool created = false;
996 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
997 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
998 ofu()->EnsureFileExists(context.get(), url, &created));
999 EXPECT_TRUE(change_observer()->HasNoChange());
1001 // Verify that file creation requires sufficient quota for the path.
1002 context.reset(NewContext(NULL));
1003 url = CreateURLFromUTF8("test file");
1004 created = false;
1005 context->set_allowed_bytes_growth(
1006 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
1007 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE,
1008 ofu()->EnsureFileExists(context.get(), url, &created));
1009 ASSERT_FALSE(created);
1010 EXPECT_TRUE(change_observer()->HasNoChange());
1012 context.reset(NewContext(NULL));
1013 context->set_allowed_bytes_growth(
1014 ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
1015 ASSERT_EQ(base::File::FILE_OK,
1016 ofu()->EnsureFileExists(context.get(), url, &created));
1017 ASSERT_TRUE(created);
1018 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
1020 CheckFileAndCloseHandle(url, base::File());
1022 context.reset(NewContext(NULL));
1023 ASSERT_EQ(base::File::FILE_OK,
1024 ofu()->EnsureFileExists(context.get(), url, &created));
1025 ASSERT_FALSE(created);
1026 EXPECT_TRUE(change_observer()->HasNoChange());
1028 // Also test in a subdirectory.
1029 url = CreateURLFromUTF8("path/to/file.txt");
1030 context.reset(NewContext(NULL));
1031 bool exclusive = true;
1032 bool recursive = true;
1033 EXPECT_EQ(base::File::FILE_OK,
1034 ofu()->CreateDirectory(context.get(), FileSystemURLDirName(url),
1035 exclusive, recursive));
1036 // 2 directories: path/ and path/to.
1037 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
1039 context.reset(NewContext(NULL));
1040 ASSERT_EQ(base::File::FILE_OK,
1041 ofu()->EnsureFileExists(context.get(), url, &created));
1042 ASSERT_TRUE(created);
1043 EXPECT_FALSE(DirectoryExists(url));
1044 EXPECT_TRUE(PathExists(url));
1045 EXPECT_TRUE(change_observer()->HasNoChange());
1048 TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) {
1049 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1051 bool exclusive = false;
1052 bool recursive = false;
1053 FileSystemURL url = CreateURLFromUTF8("foo/bar");
1054 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1055 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1057 context.reset(NewContext(NULL));
1058 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1059 ofu()->DeleteDirectory(context.get(), url));
1061 FileSystemURL root = CreateURLFromUTF8(std::string());
1062 EXPECT_FALSE(DirectoryExists(url));
1063 EXPECT_FALSE(PathExists(url));
1064 context.reset(NewContext(NULL));
1065 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
1067 context.reset(NewContext(NULL));
1068 exclusive = false;
1069 recursive = true;
1070 EXPECT_EQ(base::File::FILE_OK,
1071 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1072 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
1074 EXPECT_TRUE(DirectoryExists(url));
1075 EXPECT_TRUE(PathExists(url));
1077 context.reset(NewContext(NULL));
1078 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
1079 EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
1081 context.reset(NewContext(NULL));
1082 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(),
1083 FileSystemURLDirName(url)));
1085 // Can't remove a non-empty directory.
1086 context.reset(NewContext(NULL));
1087 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
1088 ofu()->DeleteDirectory(context.get(),
1089 FileSystemURLDirName(url)));
1090 EXPECT_TRUE(change_observer()->HasNoChange());
1092 base::File::Info file_info;
1093 base::FilePath local_path;
1094 EXPECT_EQ(base::File::FILE_OK,
1095 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
1096 EXPECT_TRUE(local_path.empty());
1097 EXPECT_TRUE(file_info.is_directory);
1098 EXPECT_FALSE(file_info.is_symbolic_link);
1100 // Same create again should succeed, since exclusive is false.
1101 context.reset(NewContext(NULL));
1102 EXPECT_EQ(base::File::FILE_OK,
1103 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1104 EXPECT_TRUE(change_observer()->HasNoChange());
1106 exclusive = true;
1107 recursive = true;
1108 context.reset(NewContext(NULL));
1109 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1110 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1111 EXPECT_TRUE(change_observer()->HasNoChange());
1113 // Verify that deleting a directory isn't stopped by zero quota, and that it
1114 // frees up quota from its path.
1115 context.reset(NewContext(NULL));
1116 context->set_allowed_bytes_growth(0);
1117 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
1118 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
1119 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
1120 context->allowed_bytes_growth());
1122 url = CreateURLFromUTF8("foo/bop");
1124 EXPECT_FALSE(DirectoryExists(url));
1125 EXPECT_FALSE(PathExists(url));
1127 context.reset(NewContext(NULL));
1128 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
1129 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1130 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
1132 // Verify that file creation requires sufficient quota for the path.
1133 exclusive = true;
1134 recursive = false;
1135 context.reset(NewContext(NULL));
1136 context->set_allowed_bytes_growth(
1137 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
1138 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1139 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1140 EXPECT_TRUE(change_observer()->HasNoChange());
1142 context.reset(NewContext(NULL));
1143 context->set_allowed_bytes_growth(
1144 ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
1145 EXPECT_EQ(base::File::FILE_OK,
1146 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1147 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
1149 EXPECT_TRUE(DirectoryExists(url));
1150 EXPECT_TRUE(PathExists(url));
1152 exclusive = true;
1153 recursive = false;
1154 context.reset(NewContext(NULL));
1155 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1156 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1157 EXPECT_TRUE(change_observer()->HasNoChange());
1159 exclusive = true;
1160 recursive = false;
1161 url = CreateURLFromUTF8("foo");
1162 context.reset(NewContext(NULL));
1163 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1164 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1165 EXPECT_TRUE(change_observer()->HasNoChange());
1167 url = CreateURLFromUTF8("blah");
1169 EXPECT_FALSE(DirectoryExists(url));
1170 EXPECT_FALSE(PathExists(url));
1172 exclusive = true;
1173 recursive = false;
1174 context.reset(NewContext(NULL));
1175 EXPECT_EQ(base::File::FILE_OK,
1176 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1177 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
1179 EXPECT_TRUE(DirectoryExists(url));
1180 EXPECT_TRUE(PathExists(url));
1182 exclusive = true;
1183 recursive = false;
1184 context.reset(NewContext(NULL));
1185 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1186 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1187 EXPECT_TRUE(change_observer()->HasNoChange());
1190 TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) {
1191 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1192 bool exclusive = true;
1193 bool recursive = true;
1194 FileSystemURL url = CreateURLFromUTF8("directory/to/use");
1195 EXPECT_EQ(base::File::FILE_OK,
1196 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1197 TestReadDirectoryHelper(url);
1200 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) {
1201 TestReadDirectoryHelper(CreateURLFromUTF8(std::string()));
1204 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) {
1205 TestReadDirectoryHelper(CreateURLFromUTF8("/"));
1208 TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
1209 FileSystemURL url = CreateURLFromUTF8("file");
1210 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1212 bool created = false;
1213 ASSERT_EQ(base::File::FILE_OK,
1214 ofu()->EnsureFileExists(context.get(), url, &created));
1215 ASSERT_TRUE(created);
1217 std::vector<storage::DirectoryEntry> entries;
1218 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
1219 AsyncFileTestHelper::ReadDirectory(file_system_context(), url,
1220 &entries));
1222 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
1225 TEST_F(ObfuscatedFileUtilTest, TestTouch) {
1226 FileSystemURL url = CreateURLFromUTF8("file");
1227 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1229 base::Time last_access_time = base::Time::Now();
1230 base::Time last_modified_time = base::Time::Now();
1232 // It's not there yet.
1233 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1234 ofu()->Touch(context.get(), url, last_access_time,
1235 last_modified_time));
1237 // OK, now create it.
1238 context.reset(NewContext(NULL));
1239 bool created = false;
1240 ASSERT_EQ(base::File::FILE_OK,
1241 ofu()->EnsureFileExists(context.get(), url, &created));
1242 ASSERT_TRUE(created);
1243 TestTouchHelper(url, true);
1245 // Now test a directory:
1246 context.reset(NewContext(NULL));
1247 bool exclusive = true;
1248 bool recursive = false;
1249 url = CreateURLFromUTF8("dir");
1250 ASSERT_EQ(base::File::FILE_OK,
1251 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1252 TestTouchHelper(url, false);
1255 TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) {
1256 FileSystemURL url = CreateURLFromUTF8("fake/file");
1257 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1259 url = CreateURLFromUTF8("file name");
1260 context->set_allowed_bytes_growth(5);
1261 bool created = false;
1262 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1263 ofu()->EnsureFileExists(context.get(), url, &created));
1264 EXPECT_FALSE(created);
1265 context->set_allowed_bytes_growth(1024);
1266 EXPECT_EQ(base::File::FILE_OK,
1267 ofu()->EnsureFileExists(context.get(), url, &created));
1268 EXPECT_TRUE(created);
1269 int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path());
1270 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
1272 context->set_allowed_bytes_growth(1024);
1273 bool exclusive = true;
1274 bool recursive = true;
1275 url = CreateURLFromUTF8("directory/to/use");
1276 std::vector<base::FilePath::StringType> components;
1277 url.path().GetComponents(&components);
1278 path_cost = 0;
1279 typedef std::vector<base::FilePath::StringType>::iterator iterator;
1280 for (iterator iter = components.begin();
1281 iter != components.end(); ++iter) {
1282 path_cost += ObfuscatedFileUtil::ComputeFilePathCost(
1283 base::FilePath(*iter));
1285 context.reset(NewContext(NULL));
1286 context->set_allowed_bytes_growth(1024);
1287 EXPECT_EQ(base::File::FILE_OK,
1288 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1289 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
1292 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
1293 FileSystemURL source_url = CreateURLFromUTF8("path0.txt");
1294 FileSystemURL dest_url = CreateURLFromUTF8("path1.txt");
1295 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1297 bool is_copy_not_move = false;
1298 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1299 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1300 FileSystemOperation::OPTION_NONE,
1301 is_copy_not_move));
1302 EXPECT_TRUE(change_observer()->HasNoChange());
1303 context.reset(NewContext(NULL));
1304 is_copy_not_move = true;
1305 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1306 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1307 FileSystemOperation::OPTION_NONE,
1308 is_copy_not_move));
1309 EXPECT_TRUE(change_observer()->HasNoChange());
1310 source_url = CreateURLFromUTF8("dir/dir/file");
1311 bool exclusive = true;
1312 bool recursive = true;
1313 context.reset(NewContext(NULL));
1314 ASSERT_EQ(base::File::FILE_OK,
1315 ofu()->CreateDirectory(context.get(),
1316 FileSystemURLDirName(source_url),
1317 exclusive, recursive));
1318 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
1319 is_copy_not_move = false;
1320 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1321 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1322 FileSystemOperation::OPTION_NONE,
1323 is_copy_not_move));
1324 EXPECT_TRUE(change_observer()->HasNoChange());
1325 context.reset(NewContext(NULL));
1326 is_copy_not_move = true;
1327 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1328 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1329 FileSystemOperation::OPTION_NONE,
1330 is_copy_not_move));
1331 EXPECT_TRUE(change_observer()->HasNoChange());
1334 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
1335 const int64 kSourceLength = 5;
1336 const int64 kDestLength = 50;
1338 for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) {
1339 SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
1340 const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
1341 SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " <<
1342 test_case.is_copy_not_move);
1343 SCOPED_TRACE(testing::Message() << "\t source_path " <<
1344 test_case.source_path);
1345 SCOPED_TRACE(testing::Message() << "\t dest_path " <<
1346 test_case.dest_path);
1347 SCOPED_TRACE(testing::Message() << "\t cause_overwrite " <<
1348 test_case.cause_overwrite);
1349 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1351 bool exclusive = false;
1352 bool recursive = true;
1353 FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
1354 FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
1356 context.reset(NewContext(NULL));
1357 ASSERT_EQ(base::File::FILE_OK,
1358 ofu()->CreateDirectory(context.get(),
1359 FileSystemURLDirName(source_url),
1360 exclusive, recursive));
1361 context.reset(NewContext(NULL));
1362 ASSERT_EQ(base::File::FILE_OK,
1363 ofu()->CreateDirectory(context.get(),
1364 FileSystemURLDirName(dest_url),
1365 exclusive, recursive));
1367 bool created = false;
1368 context.reset(NewContext(NULL));
1369 ASSERT_EQ(base::File::FILE_OK,
1370 ofu()->EnsureFileExists(context.get(), source_url, &created));
1371 ASSERT_TRUE(created);
1372 context.reset(NewContext(NULL));
1373 ASSERT_EQ(base::File::FILE_OK,
1374 ofu()->Truncate(context.get(), source_url, kSourceLength));
1376 if (test_case.cause_overwrite) {
1377 context.reset(NewContext(NULL));
1378 created = false;
1379 ASSERT_EQ(base::File::FILE_OK,
1380 ofu()->EnsureFileExists(context.get(), dest_url, &created));
1381 ASSERT_TRUE(created);
1382 context.reset(NewContext(NULL));
1383 ASSERT_EQ(base::File::FILE_OK,
1384 ofu()->Truncate(context.get(), dest_url, kDestLength));
1387 context.reset(NewContext(NULL));
1388 EXPECT_EQ(base::File::FILE_OK,
1389 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1390 FileSystemOperation::OPTION_NONE,
1391 test_case.is_copy_not_move));
1393 if (test_case.is_copy_not_move) {
1394 base::File::Info file_info;
1395 base::FilePath local_path;
1396 context.reset(NewContext(NULL));
1397 EXPECT_EQ(base::File::FILE_OK,
1398 ofu()->GetFileInfo(context.get(), source_url, &file_info,
1399 &local_path));
1400 EXPECT_EQ(kSourceLength, file_info.size);
1401 EXPECT_EQ(base::File::FILE_OK,
1402 ofu()->DeleteFile(context.get(), source_url));
1403 } else {
1404 base::File::Info file_info;
1405 base::FilePath local_path;
1406 context.reset(NewContext(NULL));
1407 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1408 ofu()->GetFileInfo(context.get(), source_url, &file_info,
1409 &local_path));
1411 base::File::Info file_info;
1412 base::FilePath local_path;
1413 EXPECT_EQ(base::File::FILE_OK,
1414 ofu()->GetFileInfo(context.get(), dest_url, &file_info,
1415 &local_path));
1416 EXPECT_EQ(kSourceLength, file_info.size);
1418 EXPECT_EQ(base::File::FILE_OK,
1419 ofu()->DeleteFile(context.get(), dest_url));
1423 TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
1424 FileSystemURL src_url = CreateURLFromUTF8("src path");
1425 FileSystemURL dest_url = CreateURLFromUTF8("destination path");
1426 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1427 bool created = false;
1428 ASSERT_EQ(base::File::FILE_OK,
1429 ofu()->EnsureFileExists(context.get(), src_url, &created));
1431 bool is_copy = true;
1432 // Copy, no overwrite.
1433 context->set_allowed_bytes_growth(
1434 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1);
1435 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1436 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1437 FileSystemOperation::OPTION_NONE, is_copy));
1438 context.reset(NewContext(NULL));
1439 context->set_allowed_bytes_growth(
1440 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
1441 EXPECT_EQ(base::File::FILE_OK,
1442 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1443 FileSystemOperation::OPTION_NONE, is_copy));
1445 // Copy, with overwrite.
1446 context.reset(NewContext(NULL));
1447 context->set_allowed_bytes_growth(0);
1448 EXPECT_EQ(base::File::FILE_OK,
1449 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1450 FileSystemOperation::OPTION_NONE, is_copy));
1453 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
1454 FileSystemURL src_url = CreateURLFromUTF8("src path");
1455 FileSystemURL dest_url = CreateURLFromUTF8("destination path");
1456 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1457 bool created = false;
1458 ASSERT_EQ(base::File::FILE_OK,
1459 ofu()->EnsureFileExists(context.get(), src_url, &created));
1461 bool is_copy = false;
1462 // Move, rename, no overwrite.
1463 context.reset(NewContext(NULL));
1464 context->set_allowed_bytes_growth(
1465 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
1466 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
1467 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1468 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1469 FileSystemOperation::OPTION_NONE, is_copy));
1470 context.reset(NewContext(NULL));
1471 context->set_allowed_bytes_growth(
1472 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
1473 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
1474 EXPECT_EQ(base::File::FILE_OK,
1475 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1476 FileSystemOperation::OPTION_NONE, is_copy));
1478 context.reset(NewContext(NULL));
1479 ASSERT_EQ(base::File::FILE_OK,
1480 ofu()->EnsureFileExists(context.get(), src_url, &created));
1482 // Move, rename, with overwrite.
1483 context.reset(NewContext(NULL));
1484 context->set_allowed_bytes_growth(0);
1485 EXPECT_EQ(base::File::FILE_OK,
1486 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1487 FileSystemOperation::OPTION_NONE, is_copy));
1490 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
1491 FileSystemURL src_url = CreateURLFromUTF8("src path");
1492 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1493 bool created = false;
1494 ASSERT_EQ(base::File::FILE_OK,
1495 ofu()->EnsureFileExists(context.get(), src_url, &created));
1497 bool exclusive = true;
1498 bool recursive = false;
1499 FileSystemURL dir_url = CreateURLFromUTF8("directory path");
1500 context.reset(NewContext(NULL));
1501 ASSERT_EQ(base::File::FILE_OK,
1502 ofu()->CreateDirectory(context.get(), dir_url, exclusive,
1503 recursive));
1505 FileSystemURL dest_url = FileSystemURLAppend(
1506 dir_url, src_url.path().value());
1508 bool is_copy = false;
1509 int64 allowed_bytes_growth = -1000; // Over quota, this should still work.
1510 // Move, no rename, no overwrite.
1511 context.reset(NewContext(NULL));
1512 context->set_allowed_bytes_growth(allowed_bytes_growth);
1513 EXPECT_EQ(base::File::FILE_OK,
1514 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1515 FileSystemOperation::OPTION_NONE, is_copy));
1516 EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
1518 // Move, no rename, with overwrite.
1519 context.reset(NewContext(NULL));
1520 ASSERT_EQ(base::File::FILE_OK,
1521 ofu()->EnsureFileExists(context.get(), src_url, &created));
1522 context.reset(NewContext(NULL));
1523 context->set_allowed_bytes_growth(allowed_bytes_growth);
1524 EXPECT_EQ(base::File::FILE_OK,
1525 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1526 FileSystemOperation::OPTION_NONE, is_copy));
1527 EXPECT_EQ(
1528 allowed_bytes_growth +
1529 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()),
1530 context->allowed_bytes_growth());
1533 TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) {
1534 TestCopyInForeignFileHelper(false /* overwrite */);
1535 TestCopyInForeignFileHelper(true /* overwrite */);
1538 TEST_F(ObfuscatedFileUtilTest, TestEnumerator) {
1539 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1540 FileSystemURL src_url = CreateURLFromUTF8("source dir");
1541 bool exclusive = true;
1542 bool recursive = false;
1543 ASSERT_EQ(base::File::FILE_OK,
1544 ofu()->CreateDirectory(context.get(), src_url, exclusive,
1545 recursive));
1547 std::set<base::FilePath::StringType> files;
1548 std::set<base::FilePath::StringType> directories;
1549 FillTestDirectory(src_url, &files, &directories);
1551 FileSystemURL dest_url = CreateURLFromUTF8("destination dir");
1553 EXPECT_FALSE(DirectoryExists(dest_url));
1554 ASSERT_EQ(base::File::FILE_OK,
1555 AsyncFileTestHelper::Copy(
1556 file_system_context(), src_url, dest_url));
1558 ValidateTestDirectory(dest_url, files, directories);
1559 EXPECT_TRUE(DirectoryExists(src_url));
1560 EXPECT_TRUE(DirectoryExists(dest_url));
1561 recursive = true;
1562 ASSERT_EQ(base::File::FILE_OK,
1563 AsyncFileTestHelper::Remove(
1564 file_system_context(), dest_url, recursive));
1565 EXPECT_FALSE(DirectoryExists(dest_url));
1568 TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) {
1569 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator>
1570 enumerator(ofu()->CreateOriginEnumerator());
1571 // The test helper starts out with a single filesystem.
1572 EXPECT_TRUE(enumerator.get());
1573 EXPECT_EQ(origin(), enumerator->Next());
1574 ASSERT_TRUE(type() == kFileSystemTypeTemporary);
1575 EXPECT_TRUE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
1576 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
1577 EXPECT_EQ(GURL(), enumerator->Next());
1578 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
1579 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
1581 std::set<GURL> origins_expected;
1582 origins_expected.insert(origin());
1584 for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) {
1585 SCOPED_TRACE(testing::Message() <<
1586 "Validating kOriginEnumerationTestRecords " << i);
1587 const OriginEnumerationTestRecord& record =
1588 kOriginEnumerationTestRecords[i];
1589 GURL origin_url(record.origin_url);
1590 origins_expected.insert(origin_url);
1591 if (record.has_temporary) {
1592 scoped_ptr<SandboxFileSystemTestHelper> file_system(
1593 NewFileSystem(origin_url, kFileSystemTypeTemporary));
1594 scoped_ptr<FileSystemOperationContext> context(
1595 NewContext(file_system.get()));
1596 bool created = false;
1597 ASSERT_EQ(base::File::FILE_OK,
1598 ofu()->EnsureFileExists(
1599 context.get(),
1600 file_system->CreateURLFromUTF8("file"),
1601 &created));
1602 EXPECT_TRUE(created);
1604 if (record.has_persistent) {
1605 scoped_ptr<SandboxFileSystemTestHelper> file_system(
1606 NewFileSystem(origin_url, kFileSystemTypePersistent));
1607 scoped_ptr<FileSystemOperationContext> context(
1608 NewContext(file_system.get()));
1609 bool created = false;
1610 ASSERT_EQ(base::File::FILE_OK,
1611 ofu()->EnsureFileExists(
1612 context.get(),
1613 file_system->CreateURLFromUTF8("file"),
1614 &created));
1615 EXPECT_TRUE(created);
1618 enumerator.reset(ofu()->CreateOriginEnumerator());
1619 EXPECT_TRUE(enumerator.get());
1620 std::set<GURL> origins_found;
1621 GURL origin_url;
1622 while (!(origin_url = enumerator->Next()).is_empty()) {
1623 origins_found.insert(origin_url);
1624 SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec());
1625 bool found = false;
1626 for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords);
1627 ++i) {
1628 const OriginEnumerationTestRecord& record =
1629 kOriginEnumerationTestRecords[i];
1630 if (GURL(record.origin_url) != origin_url)
1631 continue;
1632 found = true;
1633 EXPECT_EQ(record.has_temporary,
1634 HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
1635 EXPECT_EQ(record.has_persistent,
1636 HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
1638 // Deal with the default filesystem created by the test helper.
1639 if (!found && origin_url == origin()) {
1640 ASSERT_TRUE(type() == kFileSystemTypeTemporary);
1641 EXPECT_TRUE(HasFileSystemType(enumerator.get(),
1642 kFileSystemTypeTemporary));
1643 EXPECT_FALSE(HasFileSystemType(enumerator.get(),
1644 kFileSystemTypePersistent));
1645 found = true;
1647 EXPECT_TRUE(found);
1650 std::set<GURL> diff;
1651 std::set_symmetric_difference(origins_expected.begin(),
1652 origins_expected.end(), origins_found.begin(), origins_found.end(),
1653 inserter(diff, diff.begin()));
1654 EXPECT_TRUE(diff.empty());
1657 TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) {
1658 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1660 int64 expected_quota = 0;
1662 for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
1663 SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i);
1664 const FileSystemTestCaseRecord& test_case =
1665 kRegularFileSystemTestCases[i];
1666 base::FilePath file_path(test_case.path);
1667 expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path);
1668 if (test_case.is_directory) {
1669 bool exclusive = true;
1670 bool recursive = false;
1671 ASSERT_EQ(base::File::FILE_OK,
1672 ofu()->CreateDirectory(context.get(), CreateURL(file_path),
1673 exclusive, recursive));
1674 } else {
1675 bool created = false;
1676 ASSERT_EQ(base::File::FILE_OK,
1677 ofu()->EnsureFileExists(context.get(), CreateURL(file_path),
1678 &created));
1679 ASSERT_TRUE(created);
1680 ASSERT_EQ(base::File::FILE_OK,
1681 ofu()->Truncate(context.get(), CreateURL(file_path),
1682 test_case.data_file_size));
1683 expected_quota += test_case.data_file_size;
1687 // Usually raw size in usage cache and the usage returned by QuotaUtil
1688 // should be same.
1689 EXPECT_EQ(expected_quota, SizeInUsageFile());
1690 EXPECT_EQ(expected_quota, SizeByQuotaUtil());
1692 RevokeUsageCache();
1693 EXPECT_EQ(-1, SizeInUsageFile());
1694 EXPECT_EQ(expected_quota, SizeByQuotaUtil());
1696 // This should reconstruct the cache.
1697 GetUsageFromQuotaManager();
1698 EXPECT_EQ(expected_quota, SizeInUsageFile());
1699 EXPECT_EQ(expected_quota, SizeByQuotaUtil());
1700 EXPECT_EQ(expected_quota, usage());
1703 TEST_F(ObfuscatedFileUtilTest, TestInconsistency) {
1704 const FileSystemURL kPath1 = CreateURLFromUTF8("hoge");
1705 const FileSystemURL kPath2 = CreateURLFromUTF8("fuga");
1707 scoped_ptr<FileSystemOperationContext> context;
1708 base::File::Info file_info;
1709 base::FilePath data_path;
1710 bool created = false;
1712 // Create a non-empty file.
1713 context.reset(NewContext(NULL));
1714 EXPECT_EQ(base::File::FILE_OK,
1715 ofu()->EnsureFileExists(context.get(), kPath1, &created));
1716 EXPECT_TRUE(created);
1717 context.reset(NewContext(NULL));
1718 EXPECT_EQ(base::File::FILE_OK,
1719 ofu()->Truncate(context.get(), kPath1, 10));
1720 context.reset(NewContext(NULL));
1721 EXPECT_EQ(base::File::FILE_OK,
1722 ofu()->GetFileInfo(
1723 context.get(), kPath1, &file_info, &data_path));
1724 EXPECT_EQ(10, file_info.size);
1726 // Destroy database to make inconsistency between database and filesystem.
1727 ofu()->DestroyDirectoryDatabase(origin(), type_string());
1729 // Try to get file info of broken file.
1730 EXPECT_FALSE(PathExists(kPath1));
1731 context.reset(NewContext(NULL));
1732 EXPECT_EQ(base::File::FILE_OK,
1733 ofu()->EnsureFileExists(context.get(), kPath1, &created));
1734 EXPECT_TRUE(created);
1735 context.reset(NewContext(NULL));
1736 EXPECT_EQ(base::File::FILE_OK,
1737 ofu()->GetFileInfo(
1738 context.get(), kPath1, &file_info, &data_path));
1739 EXPECT_EQ(0, file_info.size);
1741 // Make another broken file to |kPath2|.
1742 context.reset(NewContext(NULL));
1743 EXPECT_EQ(base::File::FILE_OK,
1744 ofu()->EnsureFileExists(context.get(), kPath2, &created));
1745 EXPECT_TRUE(created);
1747 // Destroy again.
1748 ofu()->DestroyDirectoryDatabase(origin(), type_string());
1750 // Repair broken |kPath1|.
1751 context.reset(NewContext(NULL));
1752 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1753 ofu()->Touch(context.get(), kPath1, base::Time::Now(),
1754 base::Time::Now()));
1755 EXPECT_EQ(base::File::FILE_OK,
1756 ofu()->EnsureFileExists(context.get(), kPath1, &created));
1757 EXPECT_TRUE(created);
1759 // Copy from sound |kPath1| to broken |kPath2|.
1760 context.reset(NewContext(NULL));
1761 EXPECT_EQ(base::File::FILE_OK,
1762 ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
1763 FileSystemOperation::OPTION_NONE,
1764 true /* copy */));
1766 ofu()->DestroyDirectoryDatabase(origin(), type_string());
1767 context.reset(NewContext(NULL));
1768 base::File file =
1769 ofu()->CreateOrOpen(context.get(), kPath1,
1770 base::File::FLAG_READ | base::File::FLAG_CREATE);
1771 EXPECT_TRUE(file.IsValid());
1772 EXPECT_TRUE(file.created());
1774 EXPECT_TRUE(file.GetInfo(&file_info));
1775 EXPECT_EQ(0, file_info.size);
1778 TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
1779 const FileSystemURL kPath[] = {
1780 CreateURLFromUTF8("foo"),
1781 CreateURLFromUTF8("bar"),
1782 CreateURLFromUTF8("baz")
1784 const FileSystemURL empty_path = CreateURL(base::FilePath());
1785 scoped_ptr<FileSystemOperationContext> context;
1787 for (size_t i = 0; i < arraysize(kPath); ++i) {
1788 bool created = false;
1789 context.reset(NewContext(NULL));
1790 EXPECT_EQ(base::File::FILE_OK,
1791 ofu()->EnsureFileExists(context.get(), kPath[i], &created));
1792 EXPECT_TRUE(created);
1795 std::vector<storage::DirectoryEntry> entries;
1796 EXPECT_EQ(base::File::FILE_OK,
1797 AsyncFileTestHelper::ReadDirectory(
1798 file_system_context(), empty_path, &entries));
1799 EXPECT_EQ(3u, entries.size());
1801 base::FilePath local_path;
1802 EXPECT_EQ(base::File::FILE_OK,
1803 ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path));
1804 EXPECT_TRUE(base::DeleteFile(local_path, false));
1806 entries.clear();
1807 EXPECT_EQ(base::File::FILE_OK,
1808 AsyncFileTestHelper::ReadDirectory(
1809 file_system_context(), empty_path, &entries));
1810 EXPECT_EQ(arraysize(kPath) - 1, entries.size());
1813 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
1814 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1815 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
1817 // Create working directory.
1818 EXPECT_EQ(base::File::FILE_OK,
1819 ofu()->CreateDirectory(context.get(), dir_url, false, false));
1821 // EnsureFileExists, create case.
1822 FileSystemURL url(FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_file"));
1823 bool created = false;
1824 ClearTimestamp(dir_url);
1825 context.reset(NewContext(NULL));
1826 EXPECT_EQ(base::File::FILE_OK,
1827 ofu()->EnsureFileExists(context.get(), url, &created));
1828 EXPECT_TRUE(created);
1829 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1831 // non create case.
1832 created = true;
1833 ClearTimestamp(dir_url);
1834 context.reset(NewContext(NULL));
1835 EXPECT_EQ(base::File::FILE_OK,
1836 ofu()->EnsureFileExists(context.get(), url, &created));
1837 EXPECT_FALSE(created);
1838 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1840 // fail case.
1841 url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
1842 context.reset(NewContext(NULL));
1843 EXPECT_EQ(base::File::FILE_OK,
1844 ofu()->CreateDirectory(context.get(), url, false, false));
1846 ClearTimestamp(dir_url);
1847 context.reset(NewContext(NULL));
1848 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
1849 ofu()->EnsureFileExists(context.get(), url, &created));
1850 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1852 // CreateOrOpen, create case.
1853 url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
1854 ClearTimestamp(dir_url);
1855 context.reset(NewContext(NULL));
1856 base::File file =
1857 ofu()->CreateOrOpen(context.get(), url,
1858 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1860 EXPECT_TRUE(file.IsValid());
1861 EXPECT_TRUE(file.created());
1862 file.Close();
1863 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1865 // open case.
1866 ClearTimestamp(dir_url);
1867 context.reset(NewContext(NULL));
1868 file = ofu()->CreateOrOpen(context.get(), url,
1869 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
1870 EXPECT_TRUE(file.IsValid());
1871 EXPECT_FALSE(file.created());
1872 file.Close();
1873 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1875 // fail case
1876 ClearTimestamp(dir_url);
1877 context.reset(NewContext(NULL));
1878 file = ofu()->CreateOrOpen(context.get(), url,
1879 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1880 EXPECT_FALSE(file.IsValid());
1881 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
1882 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1884 // CreateDirectory, create case.
1885 // Creating CreateDirectory_dir and CreateDirectory_dir/subdir.
1886 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
1887 FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
1888 ClearTimestamp(dir_url);
1889 context.reset(NewContext(NULL));
1890 EXPECT_EQ(base::File::FILE_OK,
1891 ofu()->CreateDirectory(context.get(), subdir_url,
1892 true /* exclusive */, true /* recursive */));
1893 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1895 // create subdir case.
1896 // Creating CreateDirectory_dir/subdir2.
1897 subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
1898 ClearTimestamp(dir_url);
1899 ClearTimestamp(url);
1900 context.reset(NewContext(NULL));
1901 EXPECT_EQ(base::File::FILE_OK,
1902 ofu()->CreateDirectory(context.get(), subdir_url,
1903 true /* exclusive */, true /* recursive */));
1904 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1905 EXPECT_NE(base::Time(), GetModifiedTime(url));
1907 // fail case.
1908 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
1909 ClearTimestamp(dir_url);
1910 context.reset(NewContext(NULL));
1911 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1912 ofu()->CreateDirectory(context.get(), url,
1913 true /* exclusive */, true /* recursive */));
1914 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1916 // CopyInForeignFile, create case.
1917 url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file");
1918 FileSystemURL src_path = FileSystemURLAppendUTF8(
1919 dir_url, "CopyInForeignFile_src_file");
1920 context.reset(NewContext(NULL));
1921 EXPECT_EQ(base::File::FILE_OK,
1922 ofu()->EnsureFileExists(context.get(), src_path, &created));
1923 EXPECT_TRUE(created);
1924 base::FilePath src_local_path;
1925 context.reset(NewContext(NULL));
1926 EXPECT_EQ(base::File::FILE_OK,
1927 ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path));
1929 ClearTimestamp(dir_url);
1930 context.reset(NewContext(NULL));
1931 EXPECT_EQ(base::File::FILE_OK,
1932 ofu()->CopyInForeignFile(context.get(),
1933 src_local_path,
1934 url));
1935 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1938 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
1939 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1940 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
1942 // Create working directory.
1943 EXPECT_EQ(base::File::FILE_OK,
1944 ofu()->CreateDirectory(context.get(), dir_url, false, false));
1946 // DeleteFile, delete case.
1947 FileSystemURL url = FileSystemURLAppendUTF8(
1948 dir_url, "DeleteFile_file");
1949 bool created = false;
1950 context.reset(NewContext(NULL));
1951 EXPECT_EQ(base::File::FILE_OK,
1952 ofu()->EnsureFileExists(context.get(), url, &created));
1953 EXPECT_TRUE(created);
1955 ClearTimestamp(dir_url);
1956 context.reset(NewContext(NULL));
1957 EXPECT_EQ(base::File::FILE_OK,
1958 ofu()->DeleteFile(context.get(), url));
1959 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1961 // fail case.
1962 ClearTimestamp(dir_url);
1963 context.reset(NewContext(NULL));
1964 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1965 ofu()->DeleteFile(context.get(), url));
1966 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1968 // DeleteDirectory, fail case.
1969 url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
1970 FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
1971 context.reset(NewContext(NULL));
1972 EXPECT_EQ(base::File::FILE_OK,
1973 ofu()->CreateDirectory(context.get(), url, true, true));
1974 created = false;
1975 context.reset(NewContext(NULL));
1976 EXPECT_EQ(base::File::FILE_OK,
1977 ofu()->EnsureFileExists(context.get(), file_path, &created));
1978 EXPECT_TRUE(created);
1980 ClearTimestamp(dir_url);
1981 context.reset(NewContext(NULL));
1982 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
1983 ofu()->DeleteDirectory(context.get(), url));
1984 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1986 // delete case.
1987 context.reset(NewContext(NULL));
1988 EXPECT_EQ(base::File::FILE_OK,
1989 ofu()->DeleteFile(context.get(), file_path));
1991 ClearTimestamp(dir_url);
1992 context.reset(NewContext(NULL));
1993 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
1994 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1997 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) {
1998 TestDirectoryTimestampHelper(
1999 CreateURLFromUTF8("copy overwrite"), true, true);
2000 TestDirectoryTimestampHelper(
2001 CreateURLFromUTF8("copy non-overwrite"), true, false);
2002 TestDirectoryTimestampHelper(
2003 CreateURLFromUTF8("move overwrite"), false, true);
2004 TestDirectoryTimestampHelper(
2005 CreateURLFromUTF8("move non-overwrite"), false, false);
2008 TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
2009 FileSystemURL dir = CreateURLFromUTF8("foo");
2010 FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar");
2011 FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz");
2013 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
2014 EXPECT_EQ(base::File::FILE_OK,
2015 ofu()->CreateDirectory(context.get(), dir, false, false));
2017 bool created = false;
2018 context.reset(NewContext(NULL));
2019 EXPECT_EQ(base::File::FILE_OK,
2020 ofu()->EnsureFileExists(context.get(), url1, &created));
2021 EXPECT_TRUE(created);
2023 context.reset(NewContext(NULL));
2024 EXPECT_EQ(base::File::FILE_OK,
2025 ofu()->CreateDirectory(context.get(), url2, false, false));
2027 base::FilePath file_path;
2028 context.reset(NewContext(NULL));
2029 EXPECT_EQ(base::File::FILE_OK,
2030 ofu()->GetLocalFilePath(context.get(), url1, &file_path));
2031 EXPECT_FALSE(file_path.empty());
2033 context.reset(NewContext(NULL));
2034 EXPECT_EQ(base::File::FILE_OK,
2035 ofu()->Touch(context.get(), url1,
2036 base::Time::Now() + base::TimeDelta::FromHours(1),
2037 base::Time()));
2039 context.reset(NewContext(NULL));
2040 scoped_ptr<storage::FileSystemFileUtil::AbstractFileEnumerator> file_enum(
2041 ofu()->CreateFileEnumerator(context.get(), dir, false));
2043 int count = 0;
2044 base::FilePath file_path_each;
2045 while (!(file_path_each = file_enum->Next()).empty()) {
2046 context.reset(NewContext(NULL));
2047 base::File::Info file_info;
2048 base::FilePath file_path;
2049 EXPECT_EQ(base::File::FILE_OK,
2050 ofu()->GetFileInfo(context.get(),
2051 FileSystemURL::CreateForTest(
2052 dir.origin(),
2053 dir.mount_type(),
2054 file_path_each),
2055 &file_info, &file_path));
2056 EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory());
2057 EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime());
2058 EXPECT_EQ(file_info.size, file_enum->Size());
2059 ++count;
2061 EXPECT_EQ(2, count);
2064 // crbug.com/176470
2065 #if defined(OS_WIN) || defined(OS_ANDROID)
2066 #define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile
2067 #else
2068 #define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile
2069 #endif
2070 TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) {
2071 FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
2072 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
2073 FileSystemURL to_file1(CreateURLFromUTF8("tofile1"));
2074 FileSystemURL to_file2(CreateURLFromUTF8("tofile2"));
2075 bool created;
2077 int64 expected_total_file_size = 0;
2078 ASSERT_EQ(base::File::FILE_OK,
2079 ofu()->EnsureFileExists(
2080 AllowUsageIncrease(PathCost(from_file))->context(),
2081 from_file, &created));
2082 ASSERT_TRUE(created);
2083 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2085 ASSERT_EQ(base::File::FILE_OK,
2086 ofu()->EnsureFileExists(
2087 AllowUsageIncrease(PathCost(obstacle_file))->context(),
2088 obstacle_file, &created));
2089 ASSERT_TRUE(created);
2090 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2092 int64 from_file_size = 1020;
2093 expected_total_file_size += from_file_size;
2094 ASSERT_EQ(base::File::FILE_OK,
2095 ofu()->Truncate(
2096 AllowUsageIncrease(from_file_size)->context(),
2097 from_file, from_file_size));
2098 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2100 int64 obstacle_file_size = 1;
2101 expected_total_file_size += obstacle_file_size;
2102 ASSERT_EQ(base::File::FILE_OK,
2103 ofu()->Truncate(
2104 AllowUsageIncrease(obstacle_file_size)->context(),
2105 obstacle_file, obstacle_file_size));
2106 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2108 int64 to_file1_size = from_file_size;
2109 expected_total_file_size += to_file1_size;
2110 ASSERT_EQ(base::File::FILE_OK,
2111 ofu()->CopyOrMoveFile(
2112 AllowUsageIncrease(
2113 PathCost(to_file1) + to_file1_size)->context(),
2114 from_file, to_file1,
2115 FileSystemOperation::OPTION_NONE,
2116 true /* copy */));
2117 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2119 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE,
2120 ofu()->CopyOrMoveFile(
2121 DisallowUsageIncrease(
2122 PathCost(to_file2) + from_file_size)->context(),
2123 from_file, to_file2, FileSystemOperation::OPTION_NONE,
2124 true /* copy */));
2125 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2127 int64 old_obstacle_file_size = obstacle_file_size;
2128 obstacle_file_size = from_file_size;
2129 expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
2130 ASSERT_EQ(base::File::FILE_OK,
2131 ofu()->CopyOrMoveFile(
2132 AllowUsageIncrease(
2133 obstacle_file_size - old_obstacle_file_size)->context(),
2134 from_file, obstacle_file,
2135 FileSystemOperation::OPTION_NONE,
2136 true /* copy */));
2137 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2139 int64 old_from_file_size = from_file_size;
2140 from_file_size = old_from_file_size - 1;
2141 expected_total_file_size += from_file_size - old_from_file_size;
2142 ASSERT_EQ(base::File::FILE_OK,
2143 ofu()->Truncate(
2144 AllowUsageIncrease(
2145 from_file_size - old_from_file_size)->context(),
2146 from_file, from_file_size));
2147 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2149 // quota exceeded
2151 old_obstacle_file_size = obstacle_file_size;
2152 obstacle_file_size = from_file_size;
2153 expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
2154 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(
2155 obstacle_file_size - old_obstacle_file_size);
2156 helper->context()->set_allowed_bytes_growth(
2157 helper->context()->allowed_bytes_growth() - 1);
2158 ASSERT_EQ(base::File::FILE_OK,
2159 ofu()->CopyOrMoveFile(
2160 helper->context(),
2161 from_file, obstacle_file,
2162 FileSystemOperation::OPTION_NONE,
2163 true /* copy */));
2164 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2168 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) {
2169 FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
2170 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
2171 FileSystemURL to_file(CreateURLFromUTF8("tofile"));
2172 bool created;
2174 int64 expected_total_file_size = 0;
2175 ASSERT_EQ(base::File::FILE_OK,
2176 ofu()->EnsureFileExists(
2177 AllowUsageIncrease(PathCost(from_file))->context(),
2178 from_file, &created));
2179 ASSERT_TRUE(created);
2180 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2182 int64 from_file_size = 1020;
2183 expected_total_file_size += from_file_size;
2184 ASSERT_EQ(base::File::FILE_OK,
2185 ofu()->Truncate(
2186 AllowUsageIncrease(from_file_size)->context(),
2187 from_file, from_file_size));
2188 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2190 from_file_size = 0;
2191 ASSERT_EQ(base::File::FILE_OK,
2192 ofu()->CopyOrMoveFile(
2193 AllowUsageIncrease(-PathCost(from_file) +
2194 PathCost(to_file))->context(),
2195 from_file, to_file,
2196 FileSystemOperation::OPTION_NONE,
2197 false /* move */));
2198 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2200 ASSERT_EQ(base::File::FILE_OK,
2201 ofu()->EnsureFileExists(
2202 AllowUsageIncrease(PathCost(from_file))->context(),
2203 from_file, &created));
2204 ASSERT_TRUE(created);
2205 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2207 ASSERT_EQ(base::File::FILE_OK,
2208 ofu()->EnsureFileExists(
2209 AllowUsageIncrease(PathCost(obstacle_file))->context(),
2210 obstacle_file, &created));
2211 ASSERT_TRUE(created);
2212 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2214 from_file_size = 1020;
2215 expected_total_file_size += from_file_size;
2216 ASSERT_EQ(base::File::FILE_OK,
2217 ofu()->Truncate(
2218 AllowUsageIncrease(from_file_size)->context(),
2219 from_file, from_file_size));
2220 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2222 int64 obstacle_file_size = 1;
2223 expected_total_file_size += obstacle_file_size;
2224 ASSERT_EQ(base::File::FILE_OK,
2225 ofu()->Truncate(
2226 AllowUsageIncrease(1)->context(),
2227 obstacle_file, obstacle_file_size));
2228 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2230 int64 old_obstacle_file_size = obstacle_file_size;
2231 obstacle_file_size = from_file_size;
2232 from_file_size = 0;
2233 expected_total_file_size -= old_obstacle_file_size;
2234 ASSERT_EQ(base::File::FILE_OK,
2235 ofu()->CopyOrMoveFile(
2236 AllowUsageIncrease(
2237 -old_obstacle_file_size - PathCost(from_file))->context(),
2238 from_file, obstacle_file,
2239 FileSystemOperation::OPTION_NONE,
2240 false /* move */));
2241 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2243 ASSERT_EQ(base::File::FILE_OK,
2244 ofu()->EnsureFileExists(
2245 AllowUsageIncrease(PathCost(from_file))->context(),
2246 from_file, &created));
2247 ASSERT_TRUE(created);
2248 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2250 from_file_size = 10;
2251 expected_total_file_size += from_file_size;
2252 ASSERT_EQ(base::File::FILE_OK,
2253 ofu()->Truncate(
2254 AllowUsageIncrease(from_file_size)->context(),
2255 from_file, from_file_size));
2256 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2258 // quota exceeded even after operation
2259 old_obstacle_file_size = obstacle_file_size;
2260 obstacle_file_size = from_file_size;
2261 from_file_size = 0;
2262 expected_total_file_size -= old_obstacle_file_size;
2263 scoped_ptr<FileSystemOperationContext> context =
2264 LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1);
2265 ASSERT_EQ(base::File::FILE_OK,
2266 ofu()->CopyOrMoveFile(
2267 context.get(), from_file, obstacle_file,
2268 FileSystemOperation::OPTION_NONE,
2269 false /* move */));
2270 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2271 context.reset();
2274 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) {
2275 FileSystemURL dir(CreateURLFromUTF8("dir"));
2276 FileSystemURL file(CreateURLFromUTF8("file"));
2277 FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1"));
2278 FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2"));
2279 bool created;
2281 ASSERT_EQ(base::File::FILE_OK,
2282 ofu()->EnsureFileExists(
2283 AllowUsageIncrease(PathCost(file))->context(),
2284 file, &created));
2285 ASSERT_TRUE(created);
2286 ASSERT_EQ(0, ComputeTotalFileSize());
2288 ASSERT_EQ(base::File::FILE_OK,
2289 ofu()->CreateDirectory(
2290 AllowUsageIncrease(PathCost(dir))->context(),
2291 dir, false, false));
2292 ASSERT_EQ(0, ComputeTotalFileSize());
2294 ASSERT_EQ(base::File::FILE_OK,
2295 ofu()->EnsureFileExists(
2296 AllowUsageIncrease(PathCost(dfile1))->context(),
2297 dfile1, &created));
2298 ASSERT_TRUE(created);
2299 ASSERT_EQ(0, ComputeTotalFileSize());
2301 ASSERT_EQ(base::File::FILE_OK,
2302 ofu()->EnsureFileExists(
2303 AllowUsageIncrease(PathCost(dfile2))->context(),
2304 dfile2, &created));
2305 ASSERT_TRUE(created);
2306 ASSERT_EQ(0, ComputeTotalFileSize());
2308 ASSERT_EQ(base::File::FILE_OK,
2309 ofu()->Truncate(
2310 AllowUsageIncrease(340)->context(),
2311 file, 340));
2312 ASSERT_EQ(340, ComputeTotalFileSize());
2314 ASSERT_EQ(base::File::FILE_OK,
2315 ofu()->Truncate(
2316 AllowUsageIncrease(1020)->context(),
2317 dfile1, 1020));
2318 ASSERT_EQ(1360, ComputeTotalFileSize());
2320 ASSERT_EQ(base::File::FILE_OK,
2321 ofu()->Truncate(
2322 AllowUsageIncrease(120)->context(),
2323 dfile2, 120));
2324 ASSERT_EQ(1480, ComputeTotalFileSize());
2326 ASSERT_EQ(base::File::FILE_OK,
2327 ofu()->DeleteFile(
2328 AllowUsageIncrease(-PathCost(file) - 340)->context(),
2329 file));
2330 ASSERT_EQ(1140, ComputeTotalFileSize());
2332 ASSERT_EQ(base::File::FILE_OK,
2333 AsyncFileTestHelper::Remove(
2334 file_system_context(), dir, true /* recursive */));
2335 ASSERT_EQ(0, ComputeTotalFileSize());
2338 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) {
2339 FileSystemURL url(CreateURLFromUTF8("file"));
2341 bool created;
2342 // Creating a file.
2343 ASSERT_EQ(base::File::FILE_OK,
2344 ofu()->EnsureFileExists(
2345 AllowUsageIncrease(PathCost(url))->context(),
2346 url, &created));
2347 ASSERT_TRUE(created);
2348 ASSERT_EQ(0, ComputeTotalFileSize());
2350 // Opening it, which shouldn't change the usage.
2351 base::File file =
2352 ofu()->CreateOrOpen(AllowUsageIncrease(0)->context(), url,
2353 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
2354 ASSERT_TRUE(file.IsValid());
2355 ASSERT_EQ(0, ComputeTotalFileSize());
2356 file.Close();
2358 const int length = 33;
2359 ASSERT_EQ(base::File::FILE_OK,
2360 ofu()->Truncate(
2361 AllowUsageIncrease(length)->context(), url, length));
2362 ASSERT_EQ(length, ComputeTotalFileSize());
2364 // Opening it with CREATE_ALWAYS flag, which should truncate the file size.
2365 file = ofu()->CreateOrOpen(
2366 AllowUsageIncrease(-length)->context(), url,
2367 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
2368 ASSERT_TRUE(file.IsValid());
2369 ASSERT_EQ(0, ComputeTotalFileSize());
2370 file.Close();
2372 // Extending the file again.
2373 ASSERT_EQ(base::File::FILE_OK,
2374 ofu()->Truncate(
2375 AllowUsageIncrease(length)->context(), url, length));
2376 ASSERT_EQ(length, ComputeTotalFileSize());
2378 // Opening it with TRUNCATED flag, which should truncate the file size.
2379 file = ofu()->CreateOrOpen(
2380 AllowUsageIncrease(-length)->context(), url,
2381 base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_WRITE);
2382 ASSERT_TRUE(file.IsValid());
2383 ASSERT_EQ(0, ComputeTotalFileSize());
2384 file.Close();
2387 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) {
2388 MaybeDropDatabasesAliveCaseTestBody();
2391 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) {
2392 MaybeDropDatabasesAlreadyDeletedCaseTestBody();
2395 TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) {
2396 DestroyDirectoryDatabase_IsolatedTestBody();
2399 TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) {
2400 GetDirectoryDatabase_IsolatedTestBody();
2403 TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) {
2404 MigrationBackFromIsolatedTestBody();
2407 TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) {
2408 FileSystemURL url(CreateURLFromUTF8("file"));
2409 FileSystemURL path_in_file(CreateURLFromUTF8("file/file"));
2410 bool created;
2412 ASSERT_EQ(base::File::FILE_OK,
2413 ofu()->EnsureFileExists(UnlimitedContext().get(), url, &created));
2414 ASSERT_TRUE(created);
2416 int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE;
2417 base::File file =
2418 ofu()->CreateOrOpen(UnlimitedContext().get(), path_in_file, file_flags);
2419 ASSERT_FALSE(file.IsValid());
2420 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, file.error_details());
2422 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
2423 ofu()->CreateDirectory(UnlimitedContext().get(),
2424 path_in_file,
2425 false /* exclusive */,
2426 false /* recursive */));
2429 TEST_F(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) {
2430 FileSystemURL file(CreateURLFromUTF8("file"));
2431 FileSystemURL path_in_file(CreateURLFromUTF8("file/child"));
2432 FileSystemURL path_in_file_in_file(
2433 CreateURLFromUTF8("file/child/grandchild"));
2434 bool created;
2436 ASSERT_EQ(base::File::FILE_OK,
2437 ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created));
2438 ASSERT_TRUE(created);
2440 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
2441 ofu()->CreateDirectory(UnlimitedContext().get(),
2442 path_in_file,
2443 false /* exclusive */,
2444 true /* recursive */));
2445 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
2446 ofu()->CreateDirectory(UnlimitedContext().get(),
2447 path_in_file_in_file,
2448 false /* exclusive */,
2449 true /* recursive */));
2452 TEST_F(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType) {
2453 const GURL origin1("http://www.example.com:12");
2454 const GURL origin2("http://www.example.com:1234");
2456 // Create origin directories.
2457 scoped_ptr<SandboxFileSystemTestHelper> fs1(
2458 NewFileSystem(origin1, kFileSystemTypeTemporary));
2459 scoped_ptr<SandboxFileSystemTestHelper> fs2(
2460 NewFileSystem(origin1, kFileSystemTypePersistent));
2461 scoped_ptr<SandboxFileSystemTestHelper> fs3(
2462 NewFileSystem(origin2, kFileSystemTypeTemporary));
2463 scoped_ptr<SandboxFileSystemTestHelper> fs4(
2464 NewFileSystem(origin2, kFileSystemTypePersistent));
2466 // Make sure directories for origin1 exist.
2467 base::File::Error error = base::File::FILE_ERROR_FAILED;
2468 ofu()->GetDirectoryForOriginAndType(
2469 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2470 ASSERT_EQ(base::File::FILE_OK, error);
2471 error = base::File::FILE_ERROR_FAILED;
2472 ofu()->GetDirectoryForOriginAndType(
2473 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2474 ASSERT_EQ(base::File::FILE_OK, error);
2476 // Make sure directories for origin2 exist.
2477 error = base::File::FILE_ERROR_FAILED;
2478 ofu()->GetDirectoryForOriginAndType(
2479 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2480 ASSERT_EQ(base::File::FILE_OK, error);
2481 error = base::File::FILE_ERROR_FAILED;
2482 ofu()->GetDirectoryForOriginAndType(
2483 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2484 ASSERT_EQ(base::File::FILE_OK, error);
2486 // Delete a directory for origin1's persistent filesystem.
2487 ofu()->DeleteDirectoryForOriginAndType(
2488 origin1, GetTypeString(kFileSystemTypePersistent));
2490 // The directory for origin1's temporary filesystem should not be removed.
2491 error = base::File::FILE_ERROR_FAILED;
2492 ofu()->GetDirectoryForOriginAndType(
2493 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2494 ASSERT_EQ(base::File::FILE_OK, error);
2496 // The directory for origin1's persistent filesystem should be removed.
2497 error = base::File::FILE_ERROR_FAILED;
2498 ofu()->GetDirectoryForOriginAndType(
2499 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2500 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
2502 // The directories for origin2 should not be removed.
2503 error = base::File::FILE_ERROR_FAILED;
2504 ofu()->GetDirectoryForOriginAndType(
2505 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2506 ASSERT_EQ(base::File::FILE_OK, error);
2507 error = base::File::FILE_ERROR_FAILED;
2508 ofu()->GetDirectoryForOriginAndType(
2509 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2510 ASSERT_EQ(base::File::FILE_OK, error);
2513 TEST_F(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType_DeleteAll) {
2514 const GURL origin1("http://www.example.com:12");
2515 const GURL origin2("http://www.example.com:1234");
2517 // Create origin directories.
2518 scoped_ptr<SandboxFileSystemTestHelper> fs1(
2519 NewFileSystem(origin1, kFileSystemTypeTemporary));
2520 scoped_ptr<SandboxFileSystemTestHelper> fs2(
2521 NewFileSystem(origin1, kFileSystemTypePersistent));
2522 scoped_ptr<SandboxFileSystemTestHelper> fs3(
2523 NewFileSystem(origin2, kFileSystemTypeTemporary));
2524 scoped_ptr<SandboxFileSystemTestHelper> fs4(
2525 NewFileSystem(origin2, kFileSystemTypePersistent));
2527 // Make sure directories for origin1 exist.
2528 base::File::Error error = base::File::FILE_ERROR_FAILED;
2529 ofu()->GetDirectoryForOriginAndType(
2530 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2531 ASSERT_EQ(base::File::FILE_OK, error);
2532 error = base::File::FILE_ERROR_FAILED;
2533 ofu()->GetDirectoryForOriginAndType(
2534 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2535 ASSERT_EQ(base::File::FILE_OK, error);
2537 // Make sure directories for origin2 exist.
2538 error = base::File::FILE_ERROR_FAILED;
2539 ofu()->GetDirectoryForOriginAndType(
2540 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2541 ASSERT_EQ(base::File::FILE_OK, error);
2542 error = base::File::FILE_ERROR_FAILED;
2543 ofu()->GetDirectoryForOriginAndType(
2544 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2545 ASSERT_EQ(base::File::FILE_OK, error);
2547 // Delete all directories for origin1.
2548 ofu()->DeleteDirectoryForOriginAndType(origin1, std::string());
2550 // The directories for origin1 should be removed.
2551 error = base::File::FILE_ERROR_FAILED;
2552 ofu()->GetDirectoryForOriginAndType(
2553 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2554 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
2555 error = base::File::FILE_ERROR_FAILED;
2556 ofu()->GetDirectoryForOriginAndType(
2557 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2558 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
2560 // The directories for origin2 should not be removed.
2561 error = base::File::FILE_ERROR_FAILED;
2562 ofu()->GetDirectoryForOriginAndType(
2563 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2564 ASSERT_EQ(base::File::FILE_OK, error);
2565 error = base::File::FILE_ERROR_FAILED;
2566 ofu()->GetDirectoryForOriginAndType(
2567 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2568 ASSERT_EQ(base::File::FILE_OK, error);
2571 } // namespace content