Process Alt-Svc headers.
[chromium-blink-merge.git] / content / browser / fileapi / obfuscated_file_util_unittest.cc
blob06638ff9b8a0bdfdd42d0f4ca2df9d3564241fba
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 "base/thread_task_runner_handle.h"
17 #include "content/browser/fileapi/mock_file_change_observer.h"
18 #include "content/public/test/async_file_test_helper.h"
19 #include "content/public/test/mock_special_storage_policy.h"
20 #include "content/public/test/sandbox_file_system_test_helper.h"
21 #include "content/public/test/test_file_system_context.h"
22 #include "content/test/fileapi_test_file_set.h"
23 #include "storage/browser/fileapi/external_mount_points.h"
24 #include "storage/browser/fileapi/file_system_backend.h"
25 #include "storage/browser/fileapi/file_system_context.h"
26 #include "storage/browser/fileapi/file_system_operation_context.h"
27 #include "storage/browser/fileapi/file_system_usage_cache.h"
28 #include "storage/browser/fileapi/obfuscated_file_util.h"
29 #include "storage/browser/fileapi/sandbox_directory_database.h"
30 #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
31 #include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
32 #include "storage/browser/fileapi/sandbox_origin_database.h"
33 #include "storage/browser/quota/quota_manager.h"
34 #include "storage/common/database/database_identifier.h"
35 #include "storage/common/quota/quota_types.h"
36 #include "testing/gtest/include/gtest/gtest.h"
38 using content::AsyncFileTestHelper;
39 using storage::FileSystemContext;
40 using storage::FileSystemOperation;
41 using storage::FileSystemOperationContext;
42 using storage::FileSystemURL;
43 using storage::ObfuscatedFileUtil;
44 using storage::SandboxDirectoryDatabase;
45 using storage::SandboxIsolatedOriginDatabase;
46 using storage::kFileSystemTypeTemporary;
47 using storage::kFileSystemTypePersistent;
49 namespace content {
51 namespace {
53 bool FileExists(const base::FilePath& path) {
54 return base::PathExists(path) && !base::DirectoryExists(path);
57 int64 GetSize(const base::FilePath& path) {
58 int64 size;
59 EXPECT_TRUE(base::GetFileSize(path, &size));
60 return size;
63 // After a move, the dest exists and the source doesn't.
64 // After a copy, both source and dest exist.
65 struct CopyMoveTestCaseRecord {
66 bool is_copy_not_move;
67 const char source_path[64];
68 const char dest_path[64];
69 bool cause_overwrite;
72 const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
73 // This is the combinatoric set of:
74 // rename vs. same-name
75 // different directory vs. same directory
76 // overwrite vs. no-overwrite
77 // copy vs. move
78 // We can never be called with source and destination paths identical, so
79 // those cases are omitted.
80 {true, "dir0/file0", "dir0/file1", false},
81 {false, "dir0/file0", "dir0/file1", false},
82 {true, "dir0/file0", "dir0/file1", true},
83 {false, "dir0/file0", "dir0/file1", true},
85 {true, "dir0/file0", "dir1/file0", false},
86 {false, "dir0/file0", "dir1/file0", false},
87 {true, "dir0/file0", "dir1/file0", true},
88 {false, "dir0/file0", "dir1/file0", true},
89 {true, "dir0/file0", "dir1/file1", false},
90 {false, "dir0/file0", "dir1/file1", false},
91 {true, "dir0/file0", "dir1/file1", true},
92 {false, "dir0/file0", "dir1/file1", true},
95 struct OriginEnumerationTestRecord {
96 std::string origin_url;
97 bool has_temporary;
98 bool has_persistent;
101 const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
102 {"http://example.com", false, true},
103 {"http://example1.com", true, false},
104 {"https://example1.com", true, true},
105 {"file://", false, true},
106 {"http://example.com:8000", false, true},
109 FileSystemURL FileSystemURLAppend(
110 const FileSystemURL& url, const base::FilePath::StringType& child) {
111 return FileSystemURL::CreateForTest(
112 url.origin(), url.mount_type(), url.virtual_path().Append(child));
115 FileSystemURL FileSystemURLAppendUTF8(
116 const FileSystemURL& url, const std::string& child) {
117 return FileSystemURL::CreateForTest(
118 url.origin(),
119 url.mount_type(),
120 url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child)));
123 FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
124 return FileSystemURL::CreateForTest(
125 url.origin(),
126 url.mount_type(),
127 storage::VirtualPath::DirName(url.virtual_path()));
130 std::string GetTypeString(storage::FileSystemType type) {
131 return storage::SandboxFileSystemBackendDelegate::GetTypeString(type);
134 bool HasFileSystemType(ObfuscatedFileUtil::AbstractOriginEnumerator* enumerator,
135 storage::FileSystemType type) {
136 return enumerator->HasTypeDirectory(GetTypeString(type));
139 } // namespace
141 // TODO(ericu): The vast majority of this and the other FSFU subclass tests
142 // could theoretically be shared. It would basically be a FSFU interface
143 // compliance test, and only the subclass-specific bits that look into the
144 // implementation would need to be written per-subclass.
145 class ObfuscatedFileUtilTest : public testing::Test {
146 public:
147 ObfuscatedFileUtilTest()
148 : origin_(GURL("http://www.example.com")),
149 type_(storage::kFileSystemTypeTemporary),
150 sandbox_file_system_(origin_, type_),
151 quota_status_(storage::kQuotaStatusUnknown),
152 usage_(-1),
153 weak_factory_(this) {}
155 void SetUp() override {
156 ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
158 storage_policy_ = new MockSpecialStoragePolicy();
160 quota_manager_ = new storage::QuotaManager(
161 false /* is_incognito */, data_dir_.path(),
162 base::ThreadTaskRunnerHandle::Get().get(),
163 base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get());
165 // Every time we create a new sandbox_file_system helper,
166 // it creates another context, which creates another path manager,
167 // another sandbox_backend, and another OFU.
168 // We need to pass in the context to skip all that.
169 file_system_context_ = CreateFileSystemContextForTesting(
170 quota_manager_->proxy(),
171 data_dir_.path());
173 sandbox_file_system_.SetUp(file_system_context_.get());
175 change_observers_ =
176 storage::MockFileChangeObserver::CreateList(&change_observer_);
179 void TearDown() override {
180 quota_manager_ = NULL;
181 sandbox_file_system_.TearDown();
184 scoped_ptr<FileSystemOperationContext> LimitedContext(
185 int64 allowed_bytes_growth) {
186 scoped_ptr<FileSystemOperationContext> context(
187 sandbox_file_system_.NewOperationContext());
188 context->set_allowed_bytes_growth(allowed_bytes_growth);
189 return context.Pass();
192 scoped_ptr<FileSystemOperationContext> UnlimitedContext() {
193 return LimitedContext(kint64max);
196 FileSystemOperationContext* NewContext(
197 SandboxFileSystemTestHelper* file_system) {
198 change_observer()->ResetCount();
199 FileSystemOperationContext* context;
200 if (file_system)
201 context = file_system->NewOperationContext();
202 else
203 context = sandbox_file_system_.NewOperationContext();
204 // Setting allowed_bytes_growth big enough for all tests.
205 context->set_allowed_bytes_growth(1024 * 1024);
206 context->set_change_observers(change_observers());
207 return context;
210 const storage::ChangeObserverList& change_observers() const {
211 return change_observers_;
214 storage::MockFileChangeObserver* change_observer() {
215 return &change_observer_;
218 // This can only be used after SetUp has run and created file_system_context_
219 // and obfuscated_file_util_.
220 // Use this for tests which need to run in multiple origins; we need a test
221 // helper per origin.
222 SandboxFileSystemTestHelper* NewFileSystem(const GURL& origin,
223 storage::FileSystemType type) {
224 SandboxFileSystemTestHelper* file_system =
225 new SandboxFileSystemTestHelper(origin, type);
227 file_system->SetUp(file_system_context_.get());
228 return file_system;
231 scoped_ptr<ObfuscatedFileUtil> CreateObfuscatedFileUtil(
232 storage::SpecialStoragePolicy* storage_policy) {
233 return scoped_ptr<ObfuscatedFileUtil>(ObfuscatedFileUtil::CreateForTesting(
234 storage_policy, data_dir_path(), NULL,
235 base::ThreadTaskRunnerHandle::Get().get()));
238 ObfuscatedFileUtil* ofu() {
239 return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util());
242 const base::FilePath& test_directory() const {
243 return data_dir_.path();
246 const GURL& origin() const {
247 return origin_;
250 storage::FileSystemType type() const { return type_; }
252 std::string type_string() const {
253 return GetTypeString(type_);
256 int64 ComputeTotalFileSize() {
257 return sandbox_file_system_.ComputeCurrentOriginUsage() -
258 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
261 void GetUsageFromQuotaManager() {
262 int64 quota = -1;
263 quota_status_ =
264 AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
265 origin(),
266 sandbox_file_system_.type(),
267 &usage_,
268 &quota);
269 EXPECT_EQ(storage::kQuotaStatusOk, quota_status_);
272 void RevokeUsageCache() {
273 quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type());
274 usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath());
277 int64 SizeByQuotaUtil() {
278 return sandbox_file_system_.GetCachedOriginUsage();
281 int64 SizeInUsageFile() {
282 base::RunLoop().RunUntilIdle();
283 int64 usage = 0;
284 return usage_cache()->GetUsage(
285 sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1;
288 bool PathExists(const FileSystemURL& url) {
289 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
290 base::File::Info file_info;
291 base::FilePath platform_path;
292 base::File::Error error = ofu()->GetFileInfo(
293 context.get(), url, &file_info, &platform_path);
294 return error == base::File::FILE_OK;
297 bool DirectoryExists(const FileSystemURL& url) {
298 return AsyncFileTestHelper::DirectoryExists(file_system_context(), url);
301 int64 usage() const { return usage_; }
302 storage::FileSystemUsageCache* usage_cache() {
303 return sandbox_file_system_.usage_cache();
306 FileSystemURL CreateURLFromUTF8(const std::string& path) {
307 return sandbox_file_system_.CreateURLFromUTF8(path);
310 int64 PathCost(const FileSystemURL& url) {
311 return ObfuscatedFileUtil::ComputeFilePathCost(url.path());
314 FileSystemURL CreateURL(const base::FilePath& path) {
315 return sandbox_file_system_.CreateURL(path);
318 void CheckFileAndCloseHandle(const FileSystemURL& url, base::File file) {
319 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
320 base::FilePath local_path;
321 EXPECT_EQ(base::File::FILE_OK,
322 ofu()->GetLocalFilePath(context.get(), url, &local_path));
324 base::File::Info file_info0;
325 base::FilePath data_path;
326 EXPECT_EQ(base::File::FILE_OK,
327 ofu()->GetFileInfo(context.get(), url, &file_info0, &data_path));
328 EXPECT_EQ(data_path, local_path);
329 EXPECT_TRUE(FileExists(data_path));
330 EXPECT_EQ(0, GetSize(data_path));
332 const char data[] = "test data";
333 const int length = arraysize(data) - 1;
335 if (!file.IsValid()) {
336 file.Initialize(data_path,
337 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
338 ASSERT_TRUE(file.IsValid());
339 EXPECT_FALSE(file.created());
341 ASSERT_EQ(length, file.Write(0, data, length));
342 file.Close();
344 base::File::Info file_info1;
345 EXPECT_EQ(length, GetSize(data_path));
346 context.reset(NewContext(NULL));
347 EXPECT_EQ(base::File::FILE_OK,
348 ofu()->GetFileInfo(context.get(), url, &file_info1, &data_path));
349 EXPECT_EQ(data_path, local_path);
351 EXPECT_FALSE(file_info0.is_directory);
352 EXPECT_FALSE(file_info1.is_directory);
353 EXPECT_FALSE(file_info0.is_symbolic_link);
354 EXPECT_FALSE(file_info1.is_symbolic_link);
355 EXPECT_EQ(0, file_info0.size);
356 EXPECT_EQ(length, file_info1.size);
357 EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
359 context.reset(NewContext(NULL));
360 EXPECT_EQ(base::File::FILE_OK,
361 ofu()->Truncate(context.get(), url, length * 2));
362 EXPECT_EQ(length * 2, GetSize(data_path));
364 context.reset(NewContext(NULL));
365 EXPECT_EQ(base::File::FILE_OK,
366 ofu()->Truncate(context.get(), url, 0));
367 EXPECT_EQ(0, GetSize(data_path));
370 void ValidateTestDirectory(
371 const FileSystemURL& root_url,
372 const std::set<base::FilePath::StringType>& files,
373 const std::set<base::FilePath::StringType>& directories) {
374 scoped_ptr<FileSystemOperationContext> context;
375 std::set<base::FilePath::StringType>::const_iterator iter;
376 for (iter = files.begin(); iter != files.end(); ++iter) {
377 bool created = true;
378 context.reset(NewContext(NULL));
379 ASSERT_EQ(base::File::FILE_OK,
380 ofu()->EnsureFileExists(context.get(),
381 FileSystemURLAppend(root_url, *iter),
382 &created));
383 ASSERT_FALSE(created);
385 for (iter = directories.begin(); iter != directories.end(); ++iter) {
386 context.reset(NewContext(NULL));
387 EXPECT_TRUE(DirectoryExists(
388 FileSystemURLAppend(root_url, *iter)));
392 class UsageVerifyHelper {
393 public:
394 UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context,
395 SandboxFileSystemTestHelper* file_system,
396 int64 expected_usage)
397 : context_(context.Pass()),
398 sandbox_file_system_(file_system),
399 expected_usage_(expected_usage) {}
401 ~UsageVerifyHelper() {
402 base::RunLoop().RunUntilIdle();
403 Check();
406 FileSystemOperationContext* context() {
407 return context_.get();
410 private:
411 void Check() {
412 ASSERT_EQ(expected_usage_,
413 sandbox_file_system_->GetCachedOriginUsage());
416 scoped_ptr<FileSystemOperationContext> context_;
417 SandboxFileSystemTestHelper* sandbox_file_system_;
418 int64 expected_usage_;
421 scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) {
422 int64 usage = sandbox_file_system_.GetCachedOriginUsage();
423 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
424 LimitedContext(requested_growth),
425 &sandbox_file_system_, usage + requested_growth));
428 scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) {
429 int64 usage = sandbox_file_system_.GetCachedOriginUsage();
430 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
431 LimitedContext(requested_growth - 1), &sandbox_file_system_, usage));
434 void FillTestDirectory(
435 const FileSystemURL& root_url,
436 std::set<base::FilePath::StringType>* files,
437 std::set<base::FilePath::StringType>* directories) {
438 scoped_ptr<FileSystemOperationContext> context;
439 std::vector<storage::DirectoryEntry> entries;
440 EXPECT_EQ(base::File::FILE_OK,
441 AsyncFileTestHelper::ReadDirectory(file_system_context(),
442 root_url, &entries));
443 EXPECT_EQ(0UL, entries.size());
445 files->clear();
446 files->insert(FILE_PATH_LITERAL("first"));
447 files->insert(FILE_PATH_LITERAL("second"));
448 files->insert(FILE_PATH_LITERAL("third"));
449 directories->clear();
450 directories->insert(FILE_PATH_LITERAL("fourth"));
451 directories->insert(FILE_PATH_LITERAL("fifth"));
452 directories->insert(FILE_PATH_LITERAL("sixth"));
453 std::set<base::FilePath::StringType>::iterator iter;
454 for (iter = files->begin(); iter != files->end(); ++iter) {
455 bool created = false;
456 context.reset(NewContext(NULL));
457 ASSERT_EQ(base::File::FILE_OK,
458 ofu()->EnsureFileExists(context.get(),
459 FileSystemURLAppend(root_url, *iter),
460 &created));
461 ASSERT_TRUE(created);
463 for (iter = directories->begin(); iter != directories->end(); ++iter) {
464 bool exclusive = true;
465 bool recursive = false;
466 context.reset(NewContext(NULL));
467 EXPECT_EQ(base::File::FILE_OK,
468 ofu()->CreateDirectory(context.get(),
469 FileSystemURLAppend(root_url, *iter),
470 exclusive, recursive));
472 ValidateTestDirectory(root_url, *files, *directories);
475 void TestReadDirectoryHelper(const FileSystemURL& root_url) {
476 std::set<base::FilePath::StringType> files;
477 std::set<base::FilePath::StringType> directories;
478 FillTestDirectory(root_url, &files, &directories);
480 scoped_ptr<FileSystemOperationContext> context;
481 std::vector<storage::DirectoryEntry> entries;
482 context.reset(NewContext(NULL));
483 EXPECT_EQ(base::File::FILE_OK,
484 AsyncFileTestHelper::ReadDirectory(
485 file_system_context(), root_url, &entries));
486 std::vector<storage::DirectoryEntry>::iterator entry_iter;
487 EXPECT_EQ(files.size() + directories.size(), entries.size());
488 EXPECT_TRUE(change_observer()->HasNoChange());
489 for (entry_iter = entries.begin(); entry_iter != entries.end();
490 ++entry_iter) {
491 const storage::DirectoryEntry& entry = *entry_iter;
492 std::set<base::FilePath::StringType>::iterator iter =
493 files.find(entry.name);
494 if (iter != files.end()) {
495 EXPECT_FALSE(entry.is_directory);
496 files.erase(iter);
497 continue;
499 iter = directories.find(entry.name);
500 EXPECT_FALSE(directories.end() == iter);
501 EXPECT_TRUE(entry.is_directory);
502 directories.erase(iter);
506 void TestTouchHelper(const FileSystemURL& url, bool is_file) {
507 base::Time last_access_time = base::Time::Now();
508 base::Time last_modified_time = base::Time::Now();
510 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
511 EXPECT_EQ(base::File::FILE_OK,
512 ofu()->Touch(context.get(), url, last_access_time,
513 last_modified_time));
514 // Currently we fire no change notifications for Touch.
515 EXPECT_TRUE(change_observer()->HasNoChange());
516 base::FilePath local_path;
517 base::File::Info file_info;
518 context.reset(NewContext(NULL));
519 EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(
520 context.get(), url, &file_info, &local_path));
521 // We compare as time_t here to lower our resolution, to avoid false
522 // negatives caused by conversion to the local filesystem's native
523 // representation and back.
524 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
526 context.reset(NewContext(NULL));
527 last_modified_time += base::TimeDelta::FromHours(1);
528 last_access_time += base::TimeDelta::FromHours(14);
529 EXPECT_EQ(base::File::FILE_OK,
530 ofu()->Touch(context.get(), url, last_access_time,
531 last_modified_time));
532 EXPECT_TRUE(change_observer()->HasNoChange());
533 context.reset(NewContext(NULL));
534 EXPECT_EQ(base::File::FILE_OK,
535 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
536 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
537 if (is_file) // Directories in OFU don't support atime.
538 EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT());
541 void TestCopyInForeignFileHelper(bool overwrite) {
542 base::ScopedTempDir source_dir;
543 ASSERT_TRUE(source_dir.CreateUniqueTempDir());
544 base::FilePath root_file_path = source_dir.path();
545 base::FilePath src_file_path = root_file_path.AppendASCII("file_name");
546 FileSystemURL dest_url = CreateURLFromUTF8("new file");
547 int64 src_file_length = 87;
549 base::File file(src_file_path,
550 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
551 ASSERT_TRUE(file.IsValid());
552 EXPECT_TRUE(file.created());
553 ASSERT_TRUE(file.SetLength(src_file_length));
554 file.Close();
556 scoped_ptr<FileSystemOperationContext> context;
558 if (overwrite) {
559 context.reset(NewContext(NULL));
560 bool created = false;
561 EXPECT_EQ(base::File::FILE_OK,
562 ofu()->EnsureFileExists(context.get(), dest_url, &created));
563 EXPECT_TRUE(created);
565 // We must have observed one (and only one) create_file_count.
566 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
567 EXPECT_TRUE(change_observer()->HasNoChange());
570 const int64 path_cost =
571 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
572 if (!overwrite) {
573 // Verify that file creation requires sufficient quota for the path.
574 context.reset(NewContext(NULL));
575 context->set_allowed_bytes_growth(path_cost + src_file_length - 1);
576 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
577 ofu()->CopyInForeignFile(context.get(),
578 src_file_path, dest_url));
581 context.reset(NewContext(NULL));
582 context->set_allowed_bytes_growth(path_cost + src_file_length);
583 EXPECT_EQ(base::File::FILE_OK,
584 ofu()->CopyInForeignFile(context.get(),
585 src_file_path, dest_url));
587 EXPECT_TRUE(PathExists(dest_url));
588 EXPECT_FALSE(DirectoryExists(dest_url));
590 context.reset(NewContext(NULL));
591 base::File::Info file_info;
592 base::FilePath data_path;
593 EXPECT_EQ(base::File::FILE_OK,
594 ofu()->GetFileInfo(context.get(), dest_url, &file_info,
595 &data_path));
596 EXPECT_NE(data_path, src_file_path);
597 EXPECT_TRUE(FileExists(data_path));
598 EXPECT_EQ(src_file_length, GetSize(data_path));
600 EXPECT_EQ(base::File::FILE_OK,
601 ofu()->DeleteFile(context.get(), dest_url));
604 void ClearTimestamp(const FileSystemURL& url) {
605 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
606 EXPECT_EQ(base::File::FILE_OK,
607 ofu()->Touch(context.get(), url, base::Time(), base::Time()));
608 EXPECT_EQ(base::Time(), GetModifiedTime(url));
611 base::Time GetModifiedTime(const FileSystemURL& url) {
612 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
613 base::FilePath data_path;
614 base::File::Info file_info;
615 context.reset(NewContext(NULL));
616 EXPECT_EQ(base::File::FILE_OK,
617 ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
618 EXPECT_TRUE(change_observer()->HasNoChange());
619 return file_info.last_modified;
622 void TestDirectoryTimestampHelper(const FileSystemURL& base_dir,
623 bool copy,
624 bool overwrite) {
625 scoped_ptr<FileSystemOperationContext> context;
626 const FileSystemURL src_dir_url(
627 FileSystemURLAppendUTF8(base_dir, "foo_dir"));
628 const FileSystemURL dest_dir_url(
629 FileSystemURLAppendUTF8(base_dir, "bar_dir"));
631 const FileSystemURL src_file_url(
632 FileSystemURLAppendUTF8(src_dir_url, "hoge"));
633 const FileSystemURL dest_file_url(
634 FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
636 context.reset(NewContext(NULL));
637 EXPECT_EQ(base::File::FILE_OK,
638 ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
639 context.reset(NewContext(NULL));
640 EXPECT_EQ(base::File::FILE_OK,
641 ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
643 bool created = false;
644 context.reset(NewContext(NULL));
645 EXPECT_EQ(base::File::FILE_OK,
646 ofu()->EnsureFileExists(context.get(), src_file_url, &created));
647 if (overwrite) {
648 context.reset(NewContext(NULL));
649 EXPECT_EQ(base::File::FILE_OK,
650 ofu()->EnsureFileExists(context.get(),
651 dest_file_url, &created));
654 ClearTimestamp(src_dir_url);
655 ClearTimestamp(dest_dir_url);
656 context.reset(NewContext(NULL));
657 EXPECT_EQ(base::File::FILE_OK,
658 ofu()->CopyOrMoveFile(context.get(),
659 src_file_url, dest_file_url,
660 FileSystemOperation::OPTION_NONE,
661 copy));
662 if (copy)
663 EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url));
664 else
665 EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url));
666 EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url));
669 void MaybeDropDatabasesAliveCaseTestBody() {
670 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(NULL);
671 file_util->InitOriginDatabase(GURL(), true /*create*/);
672 ASSERT_TRUE(file_util->origin_database_ != NULL);
674 // Callback to Drop DB is called while ObfuscatedFileUtilTest is
675 // still alive.
676 file_util->db_flush_delay_seconds_ = 0;
677 file_util->MarkUsed();
678 base::RunLoop().RunUntilIdle();
680 ASSERT_TRUE(file_util->origin_database_ == NULL);
683 void MaybeDropDatabasesAlreadyDeletedCaseTestBody() {
684 // Run message loop after OFU is already deleted to make sure callback
685 // doesn't cause a crash for use after free.
687 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(NULL);
688 file_util->InitOriginDatabase(GURL(), true /*create*/);
689 file_util->db_flush_delay_seconds_ = 0;
690 file_util->MarkUsed();
693 // At this point the callback is still in the message queue but OFU is gone.
694 base::RunLoop().RunUntilIdle();
697 void DestroyDirectoryDatabase_IsolatedTestBody() {
698 storage_policy_->AddIsolated(origin_);
699 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(
700 storage_policy_.get());
701 const FileSystemURL url = FileSystemURL::CreateForTest(
702 origin_, kFileSystemTypePersistent, base::FilePath());
704 // Create DirectoryDatabase for isolated origin.
705 SandboxDirectoryDatabase* db =
706 file_util->GetDirectoryDatabase(url, true /* create */);
707 ASSERT_TRUE(db != NULL);
709 // Destory it.
710 file_util->DestroyDirectoryDatabase(
711 url.origin(), GetTypeString(url.type()));
712 ASSERT_TRUE(file_util->directories_.empty());
715 void GetDirectoryDatabase_IsolatedTestBody() {
716 storage_policy_->AddIsolated(origin_);
717 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(
718 storage_policy_.get());
719 const FileSystemURL url = FileSystemURL::CreateForTest(
720 origin_, kFileSystemTypePersistent, base::FilePath());
722 // Create DirectoryDatabase for isolated origin.
723 SandboxDirectoryDatabase* db =
724 file_util->GetDirectoryDatabase(url, true /* create */);
725 ASSERT_TRUE(db != NULL);
726 ASSERT_EQ(1U, file_util->directories_.size());
728 // Remove isolated.
729 storage_policy_->RemoveIsolated(url.origin());
731 // This should still get the same database.
732 SandboxDirectoryDatabase* db2 =
733 file_util->GetDirectoryDatabase(url, false /* create */);
734 ASSERT_EQ(db, db2);
737 void MigrationBackFromIsolatedTestBody() {
738 std::string kFakeDirectoryData("0123456789");
739 base::FilePath old_directory_db_path;
741 // Initialize the directory with one origin using
742 // SandboxIsolatedOriginDatabase.
744 std::string origin_string = storage::GetIdentifierFromOrigin(origin_);
745 SandboxIsolatedOriginDatabase database_old(
746 origin_string, data_dir_path(),
747 base::FilePath(
748 SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory));
749 base::FilePath path;
750 EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path));
751 EXPECT_FALSE(path.empty());
753 // Populate the origin directory with some fake data.
754 old_directory_db_path = data_dir_path().Append(path);
755 ASSERT_TRUE(base::CreateDirectory(old_directory_db_path));
756 EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()),
757 base::WriteFile(old_directory_db_path.AppendASCII("dummy"),
758 kFakeDirectoryData.data(),
759 kFakeDirectoryData.size()));
762 storage_policy_->AddIsolated(origin_);
763 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(
764 storage_policy_.get());
765 base::File::Error error = base::File::FILE_ERROR_FAILED;
766 base::FilePath origin_directory = file_util->GetDirectoryForOrigin(
767 origin_, true /* create */, &error);
768 EXPECT_EQ(base::File::FILE_OK, error);
770 // The database is migrated from the old one.
771 EXPECT_TRUE(base::DirectoryExists(origin_directory));
772 EXPECT_FALSE(base::DirectoryExists(old_directory_db_path));
774 // Check we see the same contents in the new origin directory.
775 std::string origin_db_data;
776 EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy")));
777 EXPECT_TRUE(base::ReadFileToString(
778 origin_directory.AppendASCII("dummy"), &origin_db_data));
779 EXPECT_EQ(kFakeDirectoryData, origin_db_data);
782 int64 ComputeCurrentUsage() {
783 return sandbox_file_system_.ComputeCurrentOriginUsage() -
784 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
787 FileSystemContext* file_system_context() {
788 return sandbox_file_system_.file_system_context();
791 const base::FilePath& data_dir_path() const {
792 return data_dir_.path();
795 protected:
796 base::ScopedTempDir data_dir_;
797 base::MessageLoopForIO message_loop_;
798 scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
799 scoped_refptr<storage::QuotaManager> quota_manager_;
800 scoped_refptr<FileSystemContext> file_system_context_;
801 GURL origin_;
802 storage::FileSystemType type_;
803 SandboxFileSystemTestHelper sandbox_file_system_;
804 storage::QuotaStatusCode quota_status_;
805 int64 usage_;
806 storage::MockFileChangeObserver change_observer_;
807 storage::ChangeObserverList change_observers_;
808 base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_;
810 private:
811 DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest);
814 TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
815 FileSystemURL url = CreateURLFromUTF8("fake/file");
816 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
817 int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE;
819 base::File file = ofu()->CreateOrOpen(context.get(), url, file_flags);
820 EXPECT_FALSE(file.IsValid());
821 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
823 context.reset(NewContext(NULL));
824 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
825 ofu()->DeleteFile(context.get(), url));
827 url = CreateURLFromUTF8("test file");
829 EXPECT_TRUE(change_observer()->HasNoChange());
831 // Verify that file creation requires sufficient quota for the path.
832 context.reset(NewContext(NULL));
833 context->set_allowed_bytes_growth(
834 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
835 file = ofu()->CreateOrOpen(context.get(), url, file_flags);
836 EXPECT_FALSE(file.IsValid());
837 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, file.error_details());
839 context.reset(NewContext(NULL));
840 context->set_allowed_bytes_growth(
841 ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
842 file = ofu()->CreateOrOpen(context.get(), url, file_flags);
843 EXPECT_TRUE(file.IsValid());
844 ASSERT_TRUE(file.created());
845 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
847 CheckFileAndCloseHandle(url, file.Pass());
849 context.reset(NewContext(NULL));
850 base::FilePath local_path;
851 EXPECT_EQ(base::File::FILE_OK,
852 ofu()->GetLocalFilePath(context.get(), url, &local_path));
853 EXPECT_TRUE(base::PathExists(local_path));
855 // Verify that deleting a file isn't stopped by zero quota, and that it frees
856 // up quote from its path.
857 context.reset(NewContext(NULL));
858 context->set_allowed_bytes_growth(0);
859 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
860 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
861 EXPECT_FALSE(base::PathExists(local_path));
862 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
863 context->allowed_bytes_growth());
865 context.reset(NewContext(NULL));
866 bool exclusive = true;
867 bool recursive = true;
868 FileSystemURL directory_url = CreateURLFromUTF8(
869 "series/of/directories");
870 url = FileSystemURLAppendUTF8(directory_url, "file name");
871 EXPECT_EQ(base::File::FILE_OK,
872 ofu()->CreateDirectory(context.get(), directory_url, exclusive,
873 recursive));
874 // The oepration created 3 directories recursively.
875 EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
877 context.reset(NewContext(NULL));
878 file = ofu()->CreateOrOpen(context.get(), url, file_flags);
879 ASSERT_TRUE(file.IsValid());
880 ASSERT_TRUE(file.created());
881 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
883 CheckFileAndCloseHandle(url, file.Pass());
885 context.reset(NewContext(NULL));
886 EXPECT_EQ(base::File::FILE_OK,
887 ofu()->GetLocalFilePath(context.get(), url, &local_path));
888 EXPECT_TRUE(base::PathExists(local_path));
890 context.reset(NewContext(NULL));
891 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
892 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
893 EXPECT_FALSE(base::PathExists(local_path));
895 // Make sure we have no unexpected changes.
896 EXPECT_TRUE(change_observer()->HasNoChange());
899 TEST_F(ObfuscatedFileUtilTest, TestTruncate) {
900 bool created = false;
901 FileSystemURL url = CreateURLFromUTF8("file");
902 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
904 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
905 ofu()->Truncate(context.get(), url, 4));
907 context.reset(NewContext(NULL));
908 ASSERT_EQ(base::File::FILE_OK,
909 ofu()->EnsureFileExists(context.get(), url, &created));
910 ASSERT_TRUE(created);
911 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
913 context.reset(NewContext(NULL));
914 base::FilePath local_path;
915 EXPECT_EQ(base::File::FILE_OK,
916 ofu()->GetLocalFilePath(context.get(), url, &local_path));
917 EXPECT_EQ(0, GetSize(local_path));
919 context.reset(NewContext(NULL));
920 EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 10));
921 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
922 EXPECT_EQ(10, GetSize(local_path));
924 context.reset(NewContext(NULL));
925 EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 1));
926 EXPECT_EQ(1, GetSize(local_path));
927 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
929 EXPECT_FALSE(DirectoryExists(url));
930 EXPECT_TRUE(PathExists(url));
932 // Make sure we have no unexpected changes.
933 EXPECT_TRUE(change_observer()->HasNoChange());
936 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
937 bool created = false;
938 FileSystemURL url = CreateURLFromUTF8("file");
940 ASSERT_EQ(base::File::FILE_OK,
941 ofu()->EnsureFileExists(
942 AllowUsageIncrease(PathCost(url))->context(),
943 url, &created));
944 ASSERT_TRUE(created);
945 ASSERT_EQ(0, ComputeTotalFileSize());
947 ASSERT_EQ(base::File::FILE_OK,
948 ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020));
949 ASSERT_EQ(1020, ComputeTotalFileSize());
951 ASSERT_EQ(base::File::FILE_OK,
952 ofu()->Truncate(AllowUsageIncrease(-1020)->context(), url, 0));
953 ASSERT_EQ(0, ComputeTotalFileSize());
955 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
956 ofu()->Truncate(DisallowUsageIncrease(1021)->context(),
957 url, 1021));
958 ASSERT_EQ(0, ComputeTotalFileSize());
960 EXPECT_EQ(base::File::FILE_OK,
961 ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020));
962 ASSERT_EQ(1020, ComputeTotalFileSize());
964 EXPECT_EQ(base::File::FILE_OK,
965 ofu()->Truncate(AllowUsageIncrease(0)->context(), url, 1020));
966 ASSERT_EQ(1020, ComputeTotalFileSize());
968 // quota exceeded
970 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1);
971 helper->context()->set_allowed_bytes_growth(
972 helper->context()->allowed_bytes_growth() - 1);
973 EXPECT_EQ(base::File::FILE_OK,
974 ofu()->Truncate(helper->context(), url, 1019));
975 ASSERT_EQ(1019, ComputeTotalFileSize());
978 // Delete backing file to make following truncation fail.
979 base::FilePath local_path;
980 ASSERT_EQ(base::File::FILE_OK,
981 ofu()->GetLocalFilePath(UnlimitedContext().get(), url,
982 &local_path));
983 ASSERT_FALSE(local_path.empty());
984 ASSERT_TRUE(base::DeleteFile(local_path, false));
986 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
987 ofu()->Truncate(LimitedContext(1234).get(), url, 1234));
988 ASSERT_EQ(0, ComputeTotalFileSize());
991 TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) {
992 FileSystemURL url = CreateURLFromUTF8("fake/file");
993 bool created = false;
994 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
995 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
996 ofu()->EnsureFileExists(context.get(), url, &created));
997 EXPECT_TRUE(change_observer()->HasNoChange());
999 // Verify that file creation requires sufficient quota for the path.
1000 context.reset(NewContext(NULL));
1001 url = CreateURLFromUTF8("test file");
1002 created = false;
1003 context->set_allowed_bytes_growth(
1004 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
1005 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE,
1006 ofu()->EnsureFileExists(context.get(), url, &created));
1007 ASSERT_FALSE(created);
1008 EXPECT_TRUE(change_observer()->HasNoChange());
1010 context.reset(NewContext(NULL));
1011 context->set_allowed_bytes_growth(
1012 ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
1013 ASSERT_EQ(base::File::FILE_OK,
1014 ofu()->EnsureFileExists(context.get(), url, &created));
1015 ASSERT_TRUE(created);
1016 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
1018 CheckFileAndCloseHandle(url, base::File());
1020 context.reset(NewContext(NULL));
1021 ASSERT_EQ(base::File::FILE_OK,
1022 ofu()->EnsureFileExists(context.get(), url, &created));
1023 ASSERT_FALSE(created);
1024 EXPECT_TRUE(change_observer()->HasNoChange());
1026 // Also test in a subdirectory.
1027 url = CreateURLFromUTF8("path/to/file.txt");
1028 context.reset(NewContext(NULL));
1029 bool exclusive = true;
1030 bool recursive = true;
1031 EXPECT_EQ(base::File::FILE_OK,
1032 ofu()->CreateDirectory(context.get(), FileSystemURLDirName(url),
1033 exclusive, recursive));
1034 // 2 directories: path/ and path/to.
1035 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
1037 context.reset(NewContext(NULL));
1038 ASSERT_EQ(base::File::FILE_OK,
1039 ofu()->EnsureFileExists(context.get(), url, &created));
1040 ASSERT_TRUE(created);
1041 EXPECT_FALSE(DirectoryExists(url));
1042 EXPECT_TRUE(PathExists(url));
1043 EXPECT_TRUE(change_observer()->HasNoChange());
1046 TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) {
1047 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1049 bool exclusive = false;
1050 bool recursive = false;
1051 FileSystemURL url = CreateURLFromUTF8("foo/bar");
1052 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1053 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1055 context.reset(NewContext(NULL));
1056 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1057 ofu()->DeleteDirectory(context.get(), url));
1059 FileSystemURL root = CreateURLFromUTF8(std::string());
1060 EXPECT_FALSE(DirectoryExists(url));
1061 EXPECT_FALSE(PathExists(url));
1062 context.reset(NewContext(NULL));
1063 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
1065 context.reset(NewContext(NULL));
1066 exclusive = false;
1067 recursive = true;
1068 EXPECT_EQ(base::File::FILE_OK,
1069 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1070 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
1072 EXPECT_TRUE(DirectoryExists(url));
1073 EXPECT_TRUE(PathExists(url));
1075 context.reset(NewContext(NULL));
1076 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
1077 EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
1079 context.reset(NewContext(NULL));
1080 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(),
1081 FileSystemURLDirName(url)));
1083 // Can't remove a non-empty directory.
1084 context.reset(NewContext(NULL));
1085 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
1086 ofu()->DeleteDirectory(context.get(),
1087 FileSystemURLDirName(url)));
1088 EXPECT_TRUE(change_observer()->HasNoChange());
1090 base::File::Info file_info;
1091 base::FilePath local_path;
1092 EXPECT_EQ(base::File::FILE_OK,
1093 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
1094 EXPECT_TRUE(local_path.empty());
1095 EXPECT_TRUE(file_info.is_directory);
1096 EXPECT_FALSE(file_info.is_symbolic_link);
1098 // Same create again should succeed, since exclusive is false.
1099 context.reset(NewContext(NULL));
1100 EXPECT_EQ(base::File::FILE_OK,
1101 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1102 EXPECT_TRUE(change_observer()->HasNoChange());
1104 exclusive = true;
1105 recursive = true;
1106 context.reset(NewContext(NULL));
1107 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1108 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1109 EXPECT_TRUE(change_observer()->HasNoChange());
1111 // Verify that deleting a directory isn't stopped by zero quota, and that it
1112 // frees up quota from its path.
1113 context.reset(NewContext(NULL));
1114 context->set_allowed_bytes_growth(0);
1115 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
1116 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
1117 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
1118 context->allowed_bytes_growth());
1120 url = CreateURLFromUTF8("foo/bop");
1122 EXPECT_FALSE(DirectoryExists(url));
1123 EXPECT_FALSE(PathExists(url));
1125 context.reset(NewContext(NULL));
1126 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
1127 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1128 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
1130 // Verify that file creation requires sufficient quota for the path.
1131 exclusive = true;
1132 recursive = false;
1133 context.reset(NewContext(NULL));
1134 context->set_allowed_bytes_growth(
1135 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
1136 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1137 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1138 EXPECT_TRUE(change_observer()->HasNoChange());
1140 context.reset(NewContext(NULL));
1141 context->set_allowed_bytes_growth(
1142 ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
1143 EXPECT_EQ(base::File::FILE_OK,
1144 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1145 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
1147 EXPECT_TRUE(DirectoryExists(url));
1148 EXPECT_TRUE(PathExists(url));
1150 exclusive = true;
1151 recursive = false;
1152 context.reset(NewContext(NULL));
1153 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1154 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1155 EXPECT_TRUE(change_observer()->HasNoChange());
1157 exclusive = true;
1158 recursive = false;
1159 url = CreateURLFromUTF8("foo");
1160 context.reset(NewContext(NULL));
1161 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1162 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1163 EXPECT_TRUE(change_observer()->HasNoChange());
1165 url = CreateURLFromUTF8("blah");
1167 EXPECT_FALSE(DirectoryExists(url));
1168 EXPECT_FALSE(PathExists(url));
1170 exclusive = true;
1171 recursive = false;
1172 context.reset(NewContext(NULL));
1173 EXPECT_EQ(base::File::FILE_OK,
1174 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1175 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
1177 EXPECT_TRUE(DirectoryExists(url));
1178 EXPECT_TRUE(PathExists(url));
1180 exclusive = true;
1181 recursive = false;
1182 context.reset(NewContext(NULL));
1183 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1184 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1185 EXPECT_TRUE(change_observer()->HasNoChange());
1188 TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) {
1189 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1190 bool exclusive = true;
1191 bool recursive = true;
1192 FileSystemURL url = CreateURLFromUTF8("directory/to/use");
1193 EXPECT_EQ(base::File::FILE_OK,
1194 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1195 TestReadDirectoryHelper(url);
1198 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) {
1199 TestReadDirectoryHelper(CreateURLFromUTF8(std::string()));
1202 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) {
1203 TestReadDirectoryHelper(CreateURLFromUTF8("/"));
1206 TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
1207 FileSystemURL url = CreateURLFromUTF8("file");
1208 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1210 bool created = false;
1211 ASSERT_EQ(base::File::FILE_OK,
1212 ofu()->EnsureFileExists(context.get(), url, &created));
1213 ASSERT_TRUE(created);
1215 std::vector<storage::DirectoryEntry> entries;
1216 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
1217 AsyncFileTestHelper::ReadDirectory(file_system_context(), url,
1218 &entries));
1220 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
1223 TEST_F(ObfuscatedFileUtilTest, TestTouch) {
1224 FileSystemURL url = CreateURLFromUTF8("file");
1225 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1227 base::Time last_access_time = base::Time::Now();
1228 base::Time last_modified_time = base::Time::Now();
1230 // It's not there yet.
1231 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1232 ofu()->Touch(context.get(), url, last_access_time,
1233 last_modified_time));
1235 // OK, now create it.
1236 context.reset(NewContext(NULL));
1237 bool created = false;
1238 ASSERT_EQ(base::File::FILE_OK,
1239 ofu()->EnsureFileExists(context.get(), url, &created));
1240 ASSERT_TRUE(created);
1241 TestTouchHelper(url, true);
1243 // Now test a directory:
1244 context.reset(NewContext(NULL));
1245 bool exclusive = true;
1246 bool recursive = false;
1247 url = CreateURLFromUTF8("dir");
1248 ASSERT_EQ(base::File::FILE_OK,
1249 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1250 TestTouchHelper(url, false);
1253 TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) {
1254 FileSystemURL url = CreateURLFromUTF8("fake/file");
1255 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1257 url = CreateURLFromUTF8("file name");
1258 context->set_allowed_bytes_growth(5);
1259 bool created = false;
1260 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1261 ofu()->EnsureFileExists(context.get(), url, &created));
1262 EXPECT_FALSE(created);
1263 context->set_allowed_bytes_growth(1024);
1264 EXPECT_EQ(base::File::FILE_OK,
1265 ofu()->EnsureFileExists(context.get(), url, &created));
1266 EXPECT_TRUE(created);
1267 int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path());
1268 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
1270 context->set_allowed_bytes_growth(1024);
1271 bool exclusive = true;
1272 bool recursive = true;
1273 url = CreateURLFromUTF8("directory/to/use");
1274 std::vector<base::FilePath::StringType> components;
1275 url.path().GetComponents(&components);
1276 path_cost = 0;
1277 typedef std::vector<base::FilePath::StringType>::iterator iterator;
1278 for (iterator iter = components.begin();
1279 iter != components.end(); ++iter) {
1280 path_cost += ObfuscatedFileUtil::ComputeFilePathCost(
1281 base::FilePath(*iter));
1283 context.reset(NewContext(NULL));
1284 context->set_allowed_bytes_growth(1024);
1285 EXPECT_EQ(base::File::FILE_OK,
1286 ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
1287 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
1290 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
1291 FileSystemURL source_url = CreateURLFromUTF8("path0.txt");
1292 FileSystemURL dest_url = CreateURLFromUTF8("path1.txt");
1293 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1295 bool is_copy_not_move = false;
1296 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1297 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1298 FileSystemOperation::OPTION_NONE,
1299 is_copy_not_move));
1300 EXPECT_TRUE(change_observer()->HasNoChange());
1301 context.reset(NewContext(NULL));
1302 is_copy_not_move = true;
1303 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1304 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1305 FileSystemOperation::OPTION_NONE,
1306 is_copy_not_move));
1307 EXPECT_TRUE(change_observer()->HasNoChange());
1308 source_url = CreateURLFromUTF8("dir/dir/file");
1309 bool exclusive = true;
1310 bool recursive = true;
1311 context.reset(NewContext(NULL));
1312 ASSERT_EQ(base::File::FILE_OK,
1313 ofu()->CreateDirectory(context.get(),
1314 FileSystemURLDirName(source_url),
1315 exclusive, recursive));
1316 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
1317 is_copy_not_move = false;
1318 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1319 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1320 FileSystemOperation::OPTION_NONE,
1321 is_copy_not_move));
1322 EXPECT_TRUE(change_observer()->HasNoChange());
1323 context.reset(NewContext(NULL));
1324 is_copy_not_move = true;
1325 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1326 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1327 FileSystemOperation::OPTION_NONE,
1328 is_copy_not_move));
1329 EXPECT_TRUE(change_observer()->HasNoChange());
1332 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
1333 const int64 kSourceLength = 5;
1334 const int64 kDestLength = 50;
1336 for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) {
1337 SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
1338 const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
1339 SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " <<
1340 test_case.is_copy_not_move);
1341 SCOPED_TRACE(testing::Message() << "\t source_path " <<
1342 test_case.source_path);
1343 SCOPED_TRACE(testing::Message() << "\t dest_path " <<
1344 test_case.dest_path);
1345 SCOPED_TRACE(testing::Message() << "\t cause_overwrite " <<
1346 test_case.cause_overwrite);
1347 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1349 bool exclusive = false;
1350 bool recursive = true;
1351 FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
1352 FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
1354 context.reset(NewContext(NULL));
1355 ASSERT_EQ(base::File::FILE_OK,
1356 ofu()->CreateDirectory(context.get(),
1357 FileSystemURLDirName(source_url),
1358 exclusive, recursive));
1359 context.reset(NewContext(NULL));
1360 ASSERT_EQ(base::File::FILE_OK,
1361 ofu()->CreateDirectory(context.get(),
1362 FileSystemURLDirName(dest_url),
1363 exclusive, recursive));
1365 bool created = false;
1366 context.reset(NewContext(NULL));
1367 ASSERT_EQ(base::File::FILE_OK,
1368 ofu()->EnsureFileExists(context.get(), source_url, &created));
1369 ASSERT_TRUE(created);
1370 context.reset(NewContext(NULL));
1371 ASSERT_EQ(base::File::FILE_OK,
1372 ofu()->Truncate(context.get(), source_url, kSourceLength));
1374 if (test_case.cause_overwrite) {
1375 context.reset(NewContext(NULL));
1376 created = false;
1377 ASSERT_EQ(base::File::FILE_OK,
1378 ofu()->EnsureFileExists(context.get(), dest_url, &created));
1379 ASSERT_TRUE(created);
1380 context.reset(NewContext(NULL));
1381 ASSERT_EQ(base::File::FILE_OK,
1382 ofu()->Truncate(context.get(), dest_url, kDestLength));
1385 context.reset(NewContext(NULL));
1386 EXPECT_EQ(base::File::FILE_OK,
1387 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
1388 FileSystemOperation::OPTION_NONE,
1389 test_case.is_copy_not_move));
1391 if (test_case.is_copy_not_move) {
1392 base::File::Info file_info;
1393 base::FilePath local_path;
1394 context.reset(NewContext(NULL));
1395 EXPECT_EQ(base::File::FILE_OK,
1396 ofu()->GetFileInfo(context.get(), source_url, &file_info,
1397 &local_path));
1398 EXPECT_EQ(kSourceLength, file_info.size);
1399 EXPECT_EQ(base::File::FILE_OK,
1400 ofu()->DeleteFile(context.get(), source_url));
1401 } else {
1402 base::File::Info file_info;
1403 base::FilePath local_path;
1404 context.reset(NewContext(NULL));
1405 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1406 ofu()->GetFileInfo(context.get(), source_url, &file_info,
1407 &local_path));
1409 base::File::Info file_info;
1410 base::FilePath local_path;
1411 EXPECT_EQ(base::File::FILE_OK,
1412 ofu()->GetFileInfo(context.get(), dest_url, &file_info,
1413 &local_path));
1414 EXPECT_EQ(kSourceLength, file_info.size);
1416 EXPECT_EQ(base::File::FILE_OK,
1417 ofu()->DeleteFile(context.get(), dest_url));
1421 TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
1422 FileSystemURL src_url = CreateURLFromUTF8("src path");
1423 FileSystemURL dest_url = CreateURLFromUTF8("destination path");
1424 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1425 bool created = false;
1426 ASSERT_EQ(base::File::FILE_OK,
1427 ofu()->EnsureFileExists(context.get(), src_url, &created));
1429 bool is_copy = true;
1430 // Copy, no overwrite.
1431 context->set_allowed_bytes_growth(
1432 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1);
1433 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1434 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1435 FileSystemOperation::OPTION_NONE, is_copy));
1436 context.reset(NewContext(NULL));
1437 context->set_allowed_bytes_growth(
1438 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
1439 EXPECT_EQ(base::File::FILE_OK,
1440 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1441 FileSystemOperation::OPTION_NONE, is_copy));
1443 // Copy, with overwrite.
1444 context.reset(NewContext(NULL));
1445 context->set_allowed_bytes_growth(0);
1446 EXPECT_EQ(base::File::FILE_OK,
1447 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1448 FileSystemOperation::OPTION_NONE, is_copy));
1451 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
1452 FileSystemURL src_url = CreateURLFromUTF8("src path");
1453 FileSystemURL dest_url = CreateURLFromUTF8("destination path");
1454 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1455 bool created = false;
1456 ASSERT_EQ(base::File::FILE_OK,
1457 ofu()->EnsureFileExists(context.get(), src_url, &created));
1459 bool is_copy = false;
1460 // Move, rename, no overwrite.
1461 context.reset(NewContext(NULL));
1462 context->set_allowed_bytes_growth(
1463 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
1464 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
1465 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
1466 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1467 FileSystemOperation::OPTION_NONE, is_copy));
1468 context.reset(NewContext(NULL));
1469 context->set_allowed_bytes_growth(
1470 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
1471 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
1472 EXPECT_EQ(base::File::FILE_OK,
1473 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1474 FileSystemOperation::OPTION_NONE, is_copy));
1476 context.reset(NewContext(NULL));
1477 ASSERT_EQ(base::File::FILE_OK,
1478 ofu()->EnsureFileExists(context.get(), src_url, &created));
1480 // Move, rename, with overwrite.
1481 context.reset(NewContext(NULL));
1482 context->set_allowed_bytes_growth(0);
1483 EXPECT_EQ(base::File::FILE_OK,
1484 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1485 FileSystemOperation::OPTION_NONE, is_copy));
1488 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
1489 FileSystemURL src_url = CreateURLFromUTF8("src path");
1490 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1491 bool created = false;
1492 ASSERT_EQ(base::File::FILE_OK,
1493 ofu()->EnsureFileExists(context.get(), src_url, &created));
1495 bool exclusive = true;
1496 bool recursive = false;
1497 FileSystemURL dir_url = CreateURLFromUTF8("directory path");
1498 context.reset(NewContext(NULL));
1499 ASSERT_EQ(base::File::FILE_OK,
1500 ofu()->CreateDirectory(context.get(), dir_url, exclusive,
1501 recursive));
1503 FileSystemURL dest_url = FileSystemURLAppend(
1504 dir_url, src_url.path().value());
1506 bool is_copy = false;
1507 int64 allowed_bytes_growth = -1000; // Over quota, this should still work.
1508 // Move, no rename, no overwrite.
1509 context.reset(NewContext(NULL));
1510 context->set_allowed_bytes_growth(allowed_bytes_growth);
1511 EXPECT_EQ(base::File::FILE_OK,
1512 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1513 FileSystemOperation::OPTION_NONE, is_copy));
1514 EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
1516 // Move, no rename, with overwrite.
1517 context.reset(NewContext(NULL));
1518 ASSERT_EQ(base::File::FILE_OK,
1519 ofu()->EnsureFileExists(context.get(), src_url, &created));
1520 context.reset(NewContext(NULL));
1521 context->set_allowed_bytes_growth(allowed_bytes_growth);
1522 EXPECT_EQ(base::File::FILE_OK,
1523 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
1524 FileSystemOperation::OPTION_NONE, is_copy));
1525 EXPECT_EQ(
1526 allowed_bytes_growth +
1527 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()),
1528 context->allowed_bytes_growth());
1531 TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) {
1532 TestCopyInForeignFileHelper(false /* overwrite */);
1533 TestCopyInForeignFileHelper(true /* overwrite */);
1536 TEST_F(ObfuscatedFileUtilTest, TestEnumerator) {
1537 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1538 FileSystemURL src_url = CreateURLFromUTF8("source dir");
1539 bool exclusive = true;
1540 bool recursive = false;
1541 ASSERT_EQ(base::File::FILE_OK,
1542 ofu()->CreateDirectory(context.get(), src_url, exclusive,
1543 recursive));
1545 std::set<base::FilePath::StringType> files;
1546 std::set<base::FilePath::StringType> directories;
1547 FillTestDirectory(src_url, &files, &directories);
1549 FileSystemURL dest_url = CreateURLFromUTF8("destination dir");
1551 EXPECT_FALSE(DirectoryExists(dest_url));
1552 ASSERT_EQ(base::File::FILE_OK,
1553 AsyncFileTestHelper::Copy(
1554 file_system_context(), src_url, dest_url));
1556 ValidateTestDirectory(dest_url, files, directories);
1557 EXPECT_TRUE(DirectoryExists(src_url));
1558 EXPECT_TRUE(DirectoryExists(dest_url));
1559 recursive = true;
1560 ASSERT_EQ(base::File::FILE_OK,
1561 AsyncFileTestHelper::Remove(
1562 file_system_context(), dest_url, recursive));
1563 EXPECT_FALSE(DirectoryExists(dest_url));
1566 TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) {
1567 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator>
1568 enumerator(ofu()->CreateOriginEnumerator());
1569 // The test helper starts out with a single filesystem.
1570 EXPECT_TRUE(enumerator.get());
1571 EXPECT_EQ(origin(), enumerator->Next());
1572 ASSERT_TRUE(type() == kFileSystemTypeTemporary);
1573 EXPECT_TRUE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
1574 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
1575 EXPECT_EQ(GURL(), enumerator->Next());
1576 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
1577 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
1579 std::set<GURL> origins_expected;
1580 origins_expected.insert(origin());
1582 for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) {
1583 SCOPED_TRACE(testing::Message() <<
1584 "Validating kOriginEnumerationTestRecords " << i);
1585 const OriginEnumerationTestRecord& record =
1586 kOriginEnumerationTestRecords[i];
1587 GURL origin_url(record.origin_url);
1588 origins_expected.insert(origin_url);
1589 if (record.has_temporary) {
1590 scoped_ptr<SandboxFileSystemTestHelper> file_system(
1591 NewFileSystem(origin_url, kFileSystemTypeTemporary));
1592 scoped_ptr<FileSystemOperationContext> context(
1593 NewContext(file_system.get()));
1594 bool created = false;
1595 ASSERT_EQ(base::File::FILE_OK,
1596 ofu()->EnsureFileExists(
1597 context.get(),
1598 file_system->CreateURLFromUTF8("file"),
1599 &created));
1600 EXPECT_TRUE(created);
1602 if (record.has_persistent) {
1603 scoped_ptr<SandboxFileSystemTestHelper> file_system(
1604 NewFileSystem(origin_url, kFileSystemTypePersistent));
1605 scoped_ptr<FileSystemOperationContext> context(
1606 NewContext(file_system.get()));
1607 bool created = false;
1608 ASSERT_EQ(base::File::FILE_OK,
1609 ofu()->EnsureFileExists(
1610 context.get(),
1611 file_system->CreateURLFromUTF8("file"),
1612 &created));
1613 EXPECT_TRUE(created);
1616 enumerator.reset(ofu()->CreateOriginEnumerator());
1617 EXPECT_TRUE(enumerator.get());
1618 std::set<GURL> origins_found;
1619 GURL origin_url;
1620 while (!(origin_url = enumerator->Next()).is_empty()) {
1621 origins_found.insert(origin_url);
1622 SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec());
1623 bool found = false;
1624 for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords);
1625 ++i) {
1626 const OriginEnumerationTestRecord& record =
1627 kOriginEnumerationTestRecords[i];
1628 if (GURL(record.origin_url) != origin_url)
1629 continue;
1630 found = true;
1631 EXPECT_EQ(record.has_temporary,
1632 HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
1633 EXPECT_EQ(record.has_persistent,
1634 HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
1636 // Deal with the default filesystem created by the test helper.
1637 if (!found && origin_url == origin()) {
1638 ASSERT_TRUE(type() == kFileSystemTypeTemporary);
1639 EXPECT_TRUE(HasFileSystemType(enumerator.get(),
1640 kFileSystemTypeTemporary));
1641 EXPECT_FALSE(HasFileSystemType(enumerator.get(),
1642 kFileSystemTypePersistent));
1643 found = true;
1645 EXPECT_TRUE(found);
1648 std::set<GURL> diff;
1649 std::set_symmetric_difference(origins_expected.begin(),
1650 origins_expected.end(), origins_found.begin(), origins_found.end(),
1651 inserter(diff, diff.begin()));
1652 EXPECT_TRUE(diff.empty());
1655 TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) {
1656 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1658 int64 expected_quota = 0;
1660 for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
1661 SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i);
1662 const FileSystemTestCaseRecord& test_case =
1663 kRegularFileSystemTestCases[i];
1664 base::FilePath file_path(test_case.path);
1665 expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path);
1666 if (test_case.is_directory) {
1667 bool exclusive = true;
1668 bool recursive = false;
1669 ASSERT_EQ(base::File::FILE_OK,
1670 ofu()->CreateDirectory(context.get(), CreateURL(file_path),
1671 exclusive, recursive));
1672 } else {
1673 bool created = false;
1674 ASSERT_EQ(base::File::FILE_OK,
1675 ofu()->EnsureFileExists(context.get(), CreateURL(file_path),
1676 &created));
1677 ASSERT_TRUE(created);
1678 ASSERT_EQ(base::File::FILE_OK,
1679 ofu()->Truncate(context.get(), CreateURL(file_path),
1680 test_case.data_file_size));
1681 expected_quota += test_case.data_file_size;
1685 // Usually raw size in usage cache and the usage returned by QuotaUtil
1686 // should be same.
1687 EXPECT_EQ(expected_quota, SizeInUsageFile());
1688 EXPECT_EQ(expected_quota, SizeByQuotaUtil());
1690 RevokeUsageCache();
1691 EXPECT_EQ(-1, SizeInUsageFile());
1692 EXPECT_EQ(expected_quota, SizeByQuotaUtil());
1694 // This should reconstruct the cache.
1695 GetUsageFromQuotaManager();
1696 EXPECT_EQ(expected_quota, SizeInUsageFile());
1697 EXPECT_EQ(expected_quota, SizeByQuotaUtil());
1698 EXPECT_EQ(expected_quota, usage());
1701 TEST_F(ObfuscatedFileUtilTest, TestInconsistency) {
1702 const FileSystemURL kPath1 = CreateURLFromUTF8("hoge");
1703 const FileSystemURL kPath2 = CreateURLFromUTF8("fuga");
1705 scoped_ptr<FileSystemOperationContext> context;
1706 base::File::Info file_info;
1707 base::FilePath data_path;
1708 bool created = false;
1710 // Create a non-empty file.
1711 context.reset(NewContext(NULL));
1712 EXPECT_EQ(base::File::FILE_OK,
1713 ofu()->EnsureFileExists(context.get(), kPath1, &created));
1714 EXPECT_TRUE(created);
1715 context.reset(NewContext(NULL));
1716 EXPECT_EQ(base::File::FILE_OK,
1717 ofu()->Truncate(context.get(), kPath1, 10));
1718 context.reset(NewContext(NULL));
1719 EXPECT_EQ(base::File::FILE_OK,
1720 ofu()->GetFileInfo(
1721 context.get(), kPath1, &file_info, &data_path));
1722 EXPECT_EQ(10, file_info.size);
1724 // Destroy database to make inconsistency between database and filesystem.
1725 ofu()->DestroyDirectoryDatabase(origin(), type_string());
1727 // Try to get file info of broken file.
1728 EXPECT_FALSE(PathExists(kPath1));
1729 context.reset(NewContext(NULL));
1730 EXPECT_EQ(base::File::FILE_OK,
1731 ofu()->EnsureFileExists(context.get(), kPath1, &created));
1732 EXPECT_TRUE(created);
1733 context.reset(NewContext(NULL));
1734 EXPECT_EQ(base::File::FILE_OK,
1735 ofu()->GetFileInfo(
1736 context.get(), kPath1, &file_info, &data_path));
1737 EXPECT_EQ(0, file_info.size);
1739 // Make another broken file to |kPath2|.
1740 context.reset(NewContext(NULL));
1741 EXPECT_EQ(base::File::FILE_OK,
1742 ofu()->EnsureFileExists(context.get(), kPath2, &created));
1743 EXPECT_TRUE(created);
1745 // Destroy again.
1746 ofu()->DestroyDirectoryDatabase(origin(), type_string());
1748 // Repair broken |kPath1|.
1749 context.reset(NewContext(NULL));
1750 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1751 ofu()->Touch(context.get(), kPath1, base::Time::Now(),
1752 base::Time::Now()));
1753 EXPECT_EQ(base::File::FILE_OK,
1754 ofu()->EnsureFileExists(context.get(), kPath1, &created));
1755 EXPECT_TRUE(created);
1757 // Copy from sound |kPath1| to broken |kPath2|.
1758 context.reset(NewContext(NULL));
1759 EXPECT_EQ(base::File::FILE_OK,
1760 ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
1761 FileSystemOperation::OPTION_NONE,
1762 true /* copy */));
1764 ofu()->DestroyDirectoryDatabase(origin(), type_string());
1765 context.reset(NewContext(NULL));
1766 base::File file =
1767 ofu()->CreateOrOpen(context.get(), kPath1,
1768 base::File::FLAG_READ | base::File::FLAG_CREATE);
1769 EXPECT_TRUE(file.IsValid());
1770 EXPECT_TRUE(file.created());
1772 EXPECT_TRUE(file.GetInfo(&file_info));
1773 EXPECT_EQ(0, file_info.size);
1776 TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
1777 const FileSystemURL kPath[] = {
1778 CreateURLFromUTF8("foo"),
1779 CreateURLFromUTF8("bar"),
1780 CreateURLFromUTF8("baz")
1782 const FileSystemURL empty_path = CreateURL(base::FilePath());
1783 scoped_ptr<FileSystemOperationContext> context;
1785 for (size_t i = 0; i < arraysize(kPath); ++i) {
1786 bool created = false;
1787 context.reset(NewContext(NULL));
1788 EXPECT_EQ(base::File::FILE_OK,
1789 ofu()->EnsureFileExists(context.get(), kPath[i], &created));
1790 EXPECT_TRUE(created);
1793 std::vector<storage::DirectoryEntry> entries;
1794 EXPECT_EQ(base::File::FILE_OK,
1795 AsyncFileTestHelper::ReadDirectory(
1796 file_system_context(), empty_path, &entries));
1797 EXPECT_EQ(3u, entries.size());
1799 base::FilePath local_path;
1800 EXPECT_EQ(base::File::FILE_OK,
1801 ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path));
1802 EXPECT_TRUE(base::DeleteFile(local_path, false));
1804 entries.clear();
1805 EXPECT_EQ(base::File::FILE_OK,
1806 AsyncFileTestHelper::ReadDirectory(
1807 file_system_context(), empty_path, &entries));
1808 EXPECT_EQ(arraysize(kPath) - 1, entries.size());
1811 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
1812 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1813 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
1815 // Create working directory.
1816 EXPECT_EQ(base::File::FILE_OK,
1817 ofu()->CreateDirectory(context.get(), dir_url, false, false));
1819 // EnsureFileExists, create case.
1820 FileSystemURL url(FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_file"));
1821 bool created = false;
1822 ClearTimestamp(dir_url);
1823 context.reset(NewContext(NULL));
1824 EXPECT_EQ(base::File::FILE_OK,
1825 ofu()->EnsureFileExists(context.get(), url, &created));
1826 EXPECT_TRUE(created);
1827 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1829 // non create case.
1830 created = true;
1831 ClearTimestamp(dir_url);
1832 context.reset(NewContext(NULL));
1833 EXPECT_EQ(base::File::FILE_OK,
1834 ofu()->EnsureFileExists(context.get(), url, &created));
1835 EXPECT_FALSE(created);
1836 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1838 // fail case.
1839 url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
1840 context.reset(NewContext(NULL));
1841 EXPECT_EQ(base::File::FILE_OK,
1842 ofu()->CreateDirectory(context.get(), url, false, false));
1844 ClearTimestamp(dir_url);
1845 context.reset(NewContext(NULL));
1846 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
1847 ofu()->EnsureFileExists(context.get(), url, &created));
1848 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1850 // CreateOrOpen, create case.
1851 url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
1852 ClearTimestamp(dir_url);
1853 context.reset(NewContext(NULL));
1854 base::File file =
1855 ofu()->CreateOrOpen(context.get(), url,
1856 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1858 EXPECT_TRUE(file.IsValid());
1859 EXPECT_TRUE(file.created());
1860 file.Close();
1861 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1863 // open case.
1864 ClearTimestamp(dir_url);
1865 context.reset(NewContext(NULL));
1866 file = ofu()->CreateOrOpen(context.get(), url,
1867 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
1868 EXPECT_TRUE(file.IsValid());
1869 EXPECT_FALSE(file.created());
1870 file.Close();
1871 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1873 // fail case
1874 ClearTimestamp(dir_url);
1875 context.reset(NewContext(NULL));
1876 file = ofu()->CreateOrOpen(context.get(), url,
1877 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
1878 EXPECT_FALSE(file.IsValid());
1879 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
1880 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1882 // CreateDirectory, create case.
1883 // Creating CreateDirectory_dir and CreateDirectory_dir/subdir.
1884 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
1885 FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
1886 ClearTimestamp(dir_url);
1887 context.reset(NewContext(NULL));
1888 EXPECT_EQ(base::File::FILE_OK,
1889 ofu()->CreateDirectory(context.get(), subdir_url,
1890 true /* exclusive */, true /* recursive */));
1891 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1893 // create subdir case.
1894 // Creating CreateDirectory_dir/subdir2.
1895 subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
1896 ClearTimestamp(dir_url);
1897 ClearTimestamp(url);
1898 context.reset(NewContext(NULL));
1899 EXPECT_EQ(base::File::FILE_OK,
1900 ofu()->CreateDirectory(context.get(), subdir_url,
1901 true /* exclusive */, true /* recursive */));
1902 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1903 EXPECT_NE(base::Time(), GetModifiedTime(url));
1905 // fail case.
1906 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
1907 ClearTimestamp(dir_url);
1908 context.reset(NewContext(NULL));
1909 EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
1910 ofu()->CreateDirectory(context.get(), url,
1911 true /* exclusive */, true /* recursive */));
1912 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1914 // CopyInForeignFile, create case.
1915 url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file");
1916 FileSystemURL src_path = FileSystemURLAppendUTF8(
1917 dir_url, "CopyInForeignFile_src_file");
1918 context.reset(NewContext(NULL));
1919 EXPECT_EQ(base::File::FILE_OK,
1920 ofu()->EnsureFileExists(context.get(), src_path, &created));
1921 EXPECT_TRUE(created);
1922 base::FilePath src_local_path;
1923 context.reset(NewContext(NULL));
1924 EXPECT_EQ(base::File::FILE_OK,
1925 ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path));
1927 ClearTimestamp(dir_url);
1928 context.reset(NewContext(NULL));
1929 EXPECT_EQ(base::File::FILE_OK,
1930 ofu()->CopyInForeignFile(context.get(),
1931 src_local_path,
1932 url));
1933 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1936 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
1937 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
1938 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
1940 // Create working directory.
1941 EXPECT_EQ(base::File::FILE_OK,
1942 ofu()->CreateDirectory(context.get(), dir_url, false, false));
1944 // DeleteFile, delete case.
1945 FileSystemURL url = FileSystemURLAppendUTF8(
1946 dir_url, "DeleteFile_file");
1947 bool created = false;
1948 context.reset(NewContext(NULL));
1949 EXPECT_EQ(base::File::FILE_OK,
1950 ofu()->EnsureFileExists(context.get(), url, &created));
1951 EXPECT_TRUE(created);
1953 ClearTimestamp(dir_url);
1954 context.reset(NewContext(NULL));
1955 EXPECT_EQ(base::File::FILE_OK,
1956 ofu()->DeleteFile(context.get(), url));
1957 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1959 // fail case.
1960 ClearTimestamp(dir_url);
1961 context.reset(NewContext(NULL));
1962 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1963 ofu()->DeleteFile(context.get(), url));
1964 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1966 // DeleteDirectory, fail case.
1967 url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
1968 FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
1969 context.reset(NewContext(NULL));
1970 EXPECT_EQ(base::File::FILE_OK,
1971 ofu()->CreateDirectory(context.get(), url, true, true));
1972 created = false;
1973 context.reset(NewContext(NULL));
1974 EXPECT_EQ(base::File::FILE_OK,
1975 ofu()->EnsureFileExists(context.get(), file_path, &created));
1976 EXPECT_TRUE(created);
1978 ClearTimestamp(dir_url);
1979 context.reset(NewContext(NULL));
1980 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
1981 ofu()->DeleteDirectory(context.get(), url));
1982 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
1984 // delete case.
1985 context.reset(NewContext(NULL));
1986 EXPECT_EQ(base::File::FILE_OK,
1987 ofu()->DeleteFile(context.get(), file_path));
1989 ClearTimestamp(dir_url);
1990 context.reset(NewContext(NULL));
1991 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
1992 EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
1995 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) {
1996 TestDirectoryTimestampHelper(
1997 CreateURLFromUTF8("copy overwrite"), true, true);
1998 TestDirectoryTimestampHelper(
1999 CreateURLFromUTF8("copy non-overwrite"), true, false);
2000 TestDirectoryTimestampHelper(
2001 CreateURLFromUTF8("move overwrite"), false, true);
2002 TestDirectoryTimestampHelper(
2003 CreateURLFromUTF8("move non-overwrite"), false, false);
2006 TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
2007 FileSystemURL dir = CreateURLFromUTF8("foo");
2008 FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar");
2009 FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz");
2011 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
2012 EXPECT_EQ(base::File::FILE_OK,
2013 ofu()->CreateDirectory(context.get(), dir, false, false));
2015 bool created = false;
2016 context.reset(NewContext(NULL));
2017 EXPECT_EQ(base::File::FILE_OK,
2018 ofu()->EnsureFileExists(context.get(), url1, &created));
2019 EXPECT_TRUE(created);
2021 context.reset(NewContext(NULL));
2022 EXPECT_EQ(base::File::FILE_OK,
2023 ofu()->CreateDirectory(context.get(), url2, false, false));
2025 base::FilePath file_path;
2026 context.reset(NewContext(NULL));
2027 EXPECT_EQ(base::File::FILE_OK,
2028 ofu()->GetLocalFilePath(context.get(), url1, &file_path));
2029 EXPECT_FALSE(file_path.empty());
2031 context.reset(NewContext(NULL));
2032 EXPECT_EQ(base::File::FILE_OK,
2033 ofu()->Touch(context.get(), url1,
2034 base::Time::Now() + base::TimeDelta::FromHours(1),
2035 base::Time()));
2037 context.reset(NewContext(NULL));
2038 scoped_ptr<storage::FileSystemFileUtil::AbstractFileEnumerator> file_enum(
2039 ofu()->CreateFileEnumerator(context.get(), dir, false));
2041 int count = 0;
2042 base::FilePath file_path_each;
2043 while (!(file_path_each = file_enum->Next()).empty()) {
2044 context.reset(NewContext(NULL));
2045 base::File::Info file_info;
2046 base::FilePath file_path;
2047 EXPECT_EQ(base::File::FILE_OK,
2048 ofu()->GetFileInfo(context.get(),
2049 FileSystemURL::CreateForTest(
2050 dir.origin(),
2051 dir.mount_type(),
2052 file_path_each),
2053 &file_info, &file_path));
2054 EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory());
2055 EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime());
2056 EXPECT_EQ(file_info.size, file_enum->Size());
2057 ++count;
2059 EXPECT_EQ(2, count);
2062 // crbug.com/176470
2063 #if defined(OS_WIN) || defined(OS_ANDROID)
2064 #define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile
2065 #else
2066 #define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile
2067 #endif
2068 TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) {
2069 FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
2070 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
2071 FileSystemURL to_file1(CreateURLFromUTF8("tofile1"));
2072 FileSystemURL to_file2(CreateURLFromUTF8("tofile2"));
2073 bool created;
2075 int64 expected_total_file_size = 0;
2076 ASSERT_EQ(base::File::FILE_OK,
2077 ofu()->EnsureFileExists(
2078 AllowUsageIncrease(PathCost(from_file))->context(),
2079 from_file, &created));
2080 ASSERT_TRUE(created);
2081 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2083 ASSERT_EQ(base::File::FILE_OK,
2084 ofu()->EnsureFileExists(
2085 AllowUsageIncrease(PathCost(obstacle_file))->context(),
2086 obstacle_file, &created));
2087 ASSERT_TRUE(created);
2088 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2090 int64 from_file_size = 1020;
2091 expected_total_file_size += from_file_size;
2092 ASSERT_EQ(base::File::FILE_OK,
2093 ofu()->Truncate(
2094 AllowUsageIncrease(from_file_size)->context(),
2095 from_file, from_file_size));
2096 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2098 int64 obstacle_file_size = 1;
2099 expected_total_file_size += obstacle_file_size;
2100 ASSERT_EQ(base::File::FILE_OK,
2101 ofu()->Truncate(
2102 AllowUsageIncrease(obstacle_file_size)->context(),
2103 obstacle_file, obstacle_file_size));
2104 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2106 int64 to_file1_size = from_file_size;
2107 expected_total_file_size += to_file1_size;
2108 ASSERT_EQ(base::File::FILE_OK,
2109 ofu()->CopyOrMoveFile(
2110 AllowUsageIncrease(
2111 PathCost(to_file1) + to_file1_size)->context(),
2112 from_file, to_file1,
2113 FileSystemOperation::OPTION_NONE,
2114 true /* copy */));
2115 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2117 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE,
2118 ofu()->CopyOrMoveFile(
2119 DisallowUsageIncrease(
2120 PathCost(to_file2) + from_file_size)->context(),
2121 from_file, to_file2, FileSystemOperation::OPTION_NONE,
2122 true /* copy */));
2123 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2125 int64 old_obstacle_file_size = obstacle_file_size;
2126 obstacle_file_size = from_file_size;
2127 expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
2128 ASSERT_EQ(base::File::FILE_OK,
2129 ofu()->CopyOrMoveFile(
2130 AllowUsageIncrease(
2131 obstacle_file_size - old_obstacle_file_size)->context(),
2132 from_file, obstacle_file,
2133 FileSystemOperation::OPTION_NONE,
2134 true /* copy */));
2135 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2137 int64 old_from_file_size = from_file_size;
2138 from_file_size = old_from_file_size - 1;
2139 expected_total_file_size += from_file_size - old_from_file_size;
2140 ASSERT_EQ(base::File::FILE_OK,
2141 ofu()->Truncate(
2142 AllowUsageIncrease(
2143 from_file_size - old_from_file_size)->context(),
2144 from_file, from_file_size));
2145 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2147 // quota exceeded
2149 old_obstacle_file_size = obstacle_file_size;
2150 obstacle_file_size = from_file_size;
2151 expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
2152 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(
2153 obstacle_file_size - old_obstacle_file_size);
2154 helper->context()->set_allowed_bytes_growth(
2155 helper->context()->allowed_bytes_growth() - 1);
2156 ASSERT_EQ(base::File::FILE_OK,
2157 ofu()->CopyOrMoveFile(
2158 helper->context(),
2159 from_file, obstacle_file,
2160 FileSystemOperation::OPTION_NONE,
2161 true /* copy */));
2162 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2166 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) {
2167 FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
2168 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
2169 FileSystemURL to_file(CreateURLFromUTF8("tofile"));
2170 bool created;
2172 int64 expected_total_file_size = 0;
2173 ASSERT_EQ(base::File::FILE_OK,
2174 ofu()->EnsureFileExists(
2175 AllowUsageIncrease(PathCost(from_file))->context(),
2176 from_file, &created));
2177 ASSERT_TRUE(created);
2178 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2180 int64 from_file_size = 1020;
2181 expected_total_file_size += from_file_size;
2182 ASSERT_EQ(base::File::FILE_OK,
2183 ofu()->Truncate(
2184 AllowUsageIncrease(from_file_size)->context(),
2185 from_file, from_file_size));
2186 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2188 from_file_size = 0;
2189 ASSERT_EQ(base::File::FILE_OK,
2190 ofu()->CopyOrMoveFile(
2191 AllowUsageIncrease(-PathCost(from_file) +
2192 PathCost(to_file))->context(),
2193 from_file, to_file,
2194 FileSystemOperation::OPTION_NONE,
2195 false /* move */));
2196 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2198 ASSERT_EQ(base::File::FILE_OK,
2199 ofu()->EnsureFileExists(
2200 AllowUsageIncrease(PathCost(from_file))->context(),
2201 from_file, &created));
2202 ASSERT_TRUE(created);
2203 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2205 ASSERT_EQ(base::File::FILE_OK,
2206 ofu()->EnsureFileExists(
2207 AllowUsageIncrease(PathCost(obstacle_file))->context(),
2208 obstacle_file, &created));
2209 ASSERT_TRUE(created);
2210 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2212 from_file_size = 1020;
2213 expected_total_file_size += from_file_size;
2214 ASSERT_EQ(base::File::FILE_OK,
2215 ofu()->Truncate(
2216 AllowUsageIncrease(from_file_size)->context(),
2217 from_file, from_file_size));
2218 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2220 int64 obstacle_file_size = 1;
2221 expected_total_file_size += obstacle_file_size;
2222 ASSERT_EQ(base::File::FILE_OK,
2223 ofu()->Truncate(
2224 AllowUsageIncrease(1)->context(),
2225 obstacle_file, obstacle_file_size));
2226 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2228 int64 old_obstacle_file_size = obstacle_file_size;
2229 obstacle_file_size = from_file_size;
2230 from_file_size = 0;
2231 expected_total_file_size -= old_obstacle_file_size;
2232 ASSERT_EQ(base::File::FILE_OK,
2233 ofu()->CopyOrMoveFile(
2234 AllowUsageIncrease(
2235 -old_obstacle_file_size - PathCost(from_file))->context(),
2236 from_file, obstacle_file,
2237 FileSystemOperation::OPTION_NONE,
2238 false /* move */));
2239 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2241 ASSERT_EQ(base::File::FILE_OK,
2242 ofu()->EnsureFileExists(
2243 AllowUsageIncrease(PathCost(from_file))->context(),
2244 from_file, &created));
2245 ASSERT_TRUE(created);
2246 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2248 from_file_size = 10;
2249 expected_total_file_size += from_file_size;
2250 ASSERT_EQ(base::File::FILE_OK,
2251 ofu()->Truncate(
2252 AllowUsageIncrease(from_file_size)->context(),
2253 from_file, from_file_size));
2254 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2256 // quota exceeded even after operation
2257 old_obstacle_file_size = obstacle_file_size;
2258 obstacle_file_size = from_file_size;
2259 from_file_size = 0;
2260 expected_total_file_size -= old_obstacle_file_size;
2261 scoped_ptr<FileSystemOperationContext> context =
2262 LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1);
2263 ASSERT_EQ(base::File::FILE_OK,
2264 ofu()->CopyOrMoveFile(
2265 context.get(), from_file, obstacle_file,
2266 FileSystemOperation::OPTION_NONE,
2267 false /* move */));
2268 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
2269 context.reset();
2272 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) {
2273 FileSystemURL dir(CreateURLFromUTF8("dir"));
2274 FileSystemURL file(CreateURLFromUTF8("file"));
2275 FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1"));
2276 FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2"));
2277 bool created;
2279 ASSERT_EQ(base::File::FILE_OK,
2280 ofu()->EnsureFileExists(
2281 AllowUsageIncrease(PathCost(file))->context(),
2282 file, &created));
2283 ASSERT_TRUE(created);
2284 ASSERT_EQ(0, ComputeTotalFileSize());
2286 ASSERT_EQ(base::File::FILE_OK,
2287 ofu()->CreateDirectory(
2288 AllowUsageIncrease(PathCost(dir))->context(),
2289 dir, false, false));
2290 ASSERT_EQ(0, ComputeTotalFileSize());
2292 ASSERT_EQ(base::File::FILE_OK,
2293 ofu()->EnsureFileExists(
2294 AllowUsageIncrease(PathCost(dfile1))->context(),
2295 dfile1, &created));
2296 ASSERT_TRUE(created);
2297 ASSERT_EQ(0, ComputeTotalFileSize());
2299 ASSERT_EQ(base::File::FILE_OK,
2300 ofu()->EnsureFileExists(
2301 AllowUsageIncrease(PathCost(dfile2))->context(),
2302 dfile2, &created));
2303 ASSERT_TRUE(created);
2304 ASSERT_EQ(0, ComputeTotalFileSize());
2306 ASSERT_EQ(base::File::FILE_OK,
2307 ofu()->Truncate(
2308 AllowUsageIncrease(340)->context(),
2309 file, 340));
2310 ASSERT_EQ(340, ComputeTotalFileSize());
2312 ASSERT_EQ(base::File::FILE_OK,
2313 ofu()->Truncate(
2314 AllowUsageIncrease(1020)->context(),
2315 dfile1, 1020));
2316 ASSERT_EQ(1360, ComputeTotalFileSize());
2318 ASSERT_EQ(base::File::FILE_OK,
2319 ofu()->Truncate(
2320 AllowUsageIncrease(120)->context(),
2321 dfile2, 120));
2322 ASSERT_EQ(1480, ComputeTotalFileSize());
2324 ASSERT_EQ(base::File::FILE_OK,
2325 ofu()->DeleteFile(
2326 AllowUsageIncrease(-PathCost(file) - 340)->context(),
2327 file));
2328 ASSERT_EQ(1140, ComputeTotalFileSize());
2330 ASSERT_EQ(base::File::FILE_OK,
2331 AsyncFileTestHelper::Remove(
2332 file_system_context(), dir, true /* recursive */));
2333 ASSERT_EQ(0, ComputeTotalFileSize());
2336 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) {
2337 FileSystemURL url(CreateURLFromUTF8("file"));
2339 bool created;
2340 // Creating a file.
2341 ASSERT_EQ(base::File::FILE_OK,
2342 ofu()->EnsureFileExists(
2343 AllowUsageIncrease(PathCost(url))->context(),
2344 url, &created));
2345 ASSERT_TRUE(created);
2346 ASSERT_EQ(0, ComputeTotalFileSize());
2348 // Opening it, which shouldn't change the usage.
2349 base::File file =
2350 ofu()->CreateOrOpen(AllowUsageIncrease(0)->context(), url,
2351 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
2352 ASSERT_TRUE(file.IsValid());
2353 ASSERT_EQ(0, ComputeTotalFileSize());
2354 file.Close();
2356 const int length = 33;
2357 ASSERT_EQ(base::File::FILE_OK,
2358 ofu()->Truncate(
2359 AllowUsageIncrease(length)->context(), url, length));
2360 ASSERT_EQ(length, ComputeTotalFileSize());
2362 // Opening it with CREATE_ALWAYS flag, which should truncate the file size.
2363 file = ofu()->CreateOrOpen(
2364 AllowUsageIncrease(-length)->context(), url,
2365 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
2366 ASSERT_TRUE(file.IsValid());
2367 ASSERT_EQ(0, ComputeTotalFileSize());
2368 file.Close();
2370 // Extending the file again.
2371 ASSERT_EQ(base::File::FILE_OK,
2372 ofu()->Truncate(
2373 AllowUsageIncrease(length)->context(), url, length));
2374 ASSERT_EQ(length, ComputeTotalFileSize());
2376 // Opening it with TRUNCATED flag, which should truncate the file size.
2377 file = ofu()->CreateOrOpen(
2378 AllowUsageIncrease(-length)->context(), url,
2379 base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_WRITE);
2380 ASSERT_TRUE(file.IsValid());
2381 ASSERT_EQ(0, ComputeTotalFileSize());
2382 file.Close();
2385 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) {
2386 MaybeDropDatabasesAliveCaseTestBody();
2389 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) {
2390 MaybeDropDatabasesAlreadyDeletedCaseTestBody();
2393 TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) {
2394 DestroyDirectoryDatabase_IsolatedTestBody();
2397 TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) {
2398 GetDirectoryDatabase_IsolatedTestBody();
2401 TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) {
2402 MigrationBackFromIsolatedTestBody();
2405 TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) {
2406 FileSystemURL url(CreateURLFromUTF8("file"));
2407 FileSystemURL path_in_file(CreateURLFromUTF8("file/file"));
2408 bool created;
2410 ASSERT_EQ(base::File::FILE_OK,
2411 ofu()->EnsureFileExists(UnlimitedContext().get(), url, &created));
2412 ASSERT_TRUE(created);
2414 int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE;
2415 base::File file =
2416 ofu()->CreateOrOpen(UnlimitedContext().get(), path_in_file, file_flags);
2417 ASSERT_FALSE(file.IsValid());
2418 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, file.error_details());
2420 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
2421 ofu()->CreateDirectory(UnlimitedContext().get(),
2422 path_in_file,
2423 false /* exclusive */,
2424 false /* recursive */));
2427 TEST_F(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) {
2428 FileSystemURL file(CreateURLFromUTF8("file"));
2429 FileSystemURL path_in_file(CreateURLFromUTF8("file/child"));
2430 FileSystemURL path_in_file_in_file(
2431 CreateURLFromUTF8("file/child/grandchild"));
2432 bool created;
2434 ASSERT_EQ(base::File::FILE_OK,
2435 ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created));
2436 ASSERT_TRUE(created);
2438 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
2439 ofu()->CreateDirectory(UnlimitedContext().get(),
2440 path_in_file,
2441 false /* exclusive */,
2442 true /* recursive */));
2443 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
2444 ofu()->CreateDirectory(UnlimitedContext().get(),
2445 path_in_file_in_file,
2446 false /* exclusive */,
2447 true /* recursive */));
2450 TEST_F(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType) {
2451 const GURL origin1("http://www.example.com:12");
2452 const GURL origin2("http://www.example.com:1234");
2454 // Create origin directories.
2455 scoped_ptr<SandboxFileSystemTestHelper> fs1(
2456 NewFileSystem(origin1, kFileSystemTypeTemporary));
2457 scoped_ptr<SandboxFileSystemTestHelper> fs2(
2458 NewFileSystem(origin1, kFileSystemTypePersistent));
2459 scoped_ptr<SandboxFileSystemTestHelper> fs3(
2460 NewFileSystem(origin2, kFileSystemTypeTemporary));
2461 scoped_ptr<SandboxFileSystemTestHelper> fs4(
2462 NewFileSystem(origin2, kFileSystemTypePersistent));
2464 // Make sure directories for origin1 exist.
2465 base::File::Error error = base::File::FILE_ERROR_FAILED;
2466 ofu()->GetDirectoryForOriginAndType(
2467 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2468 ASSERT_EQ(base::File::FILE_OK, error);
2469 error = base::File::FILE_ERROR_FAILED;
2470 ofu()->GetDirectoryForOriginAndType(
2471 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2472 ASSERT_EQ(base::File::FILE_OK, error);
2474 // Make sure directories for origin2 exist.
2475 error = base::File::FILE_ERROR_FAILED;
2476 ofu()->GetDirectoryForOriginAndType(
2477 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2478 ASSERT_EQ(base::File::FILE_OK, error);
2479 error = base::File::FILE_ERROR_FAILED;
2480 ofu()->GetDirectoryForOriginAndType(
2481 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2482 ASSERT_EQ(base::File::FILE_OK, error);
2484 // Delete a directory for origin1's persistent filesystem.
2485 ofu()->DeleteDirectoryForOriginAndType(
2486 origin1, GetTypeString(kFileSystemTypePersistent));
2488 // The directory for origin1's temporary filesystem should not be removed.
2489 error = base::File::FILE_ERROR_FAILED;
2490 ofu()->GetDirectoryForOriginAndType(
2491 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2492 ASSERT_EQ(base::File::FILE_OK, error);
2494 // The directory for origin1's persistent filesystem should be removed.
2495 error = base::File::FILE_ERROR_FAILED;
2496 ofu()->GetDirectoryForOriginAndType(
2497 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2498 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
2500 // The directories for origin2 should not be removed.
2501 error = base::File::FILE_ERROR_FAILED;
2502 ofu()->GetDirectoryForOriginAndType(
2503 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2504 ASSERT_EQ(base::File::FILE_OK, error);
2505 error = base::File::FILE_ERROR_FAILED;
2506 ofu()->GetDirectoryForOriginAndType(
2507 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2508 ASSERT_EQ(base::File::FILE_OK, error);
2511 TEST_F(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType_DeleteAll) {
2512 const GURL origin1("http://www.example.com:12");
2513 const GURL origin2("http://www.example.com:1234");
2515 // Create origin directories.
2516 scoped_ptr<SandboxFileSystemTestHelper> fs1(
2517 NewFileSystem(origin1, kFileSystemTypeTemporary));
2518 scoped_ptr<SandboxFileSystemTestHelper> fs2(
2519 NewFileSystem(origin1, kFileSystemTypePersistent));
2520 scoped_ptr<SandboxFileSystemTestHelper> fs3(
2521 NewFileSystem(origin2, kFileSystemTypeTemporary));
2522 scoped_ptr<SandboxFileSystemTestHelper> fs4(
2523 NewFileSystem(origin2, kFileSystemTypePersistent));
2525 // Make sure directories for origin1 exist.
2526 base::File::Error error = base::File::FILE_ERROR_FAILED;
2527 ofu()->GetDirectoryForOriginAndType(
2528 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2529 ASSERT_EQ(base::File::FILE_OK, error);
2530 error = base::File::FILE_ERROR_FAILED;
2531 ofu()->GetDirectoryForOriginAndType(
2532 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2533 ASSERT_EQ(base::File::FILE_OK, error);
2535 // Make sure directories for origin2 exist.
2536 error = base::File::FILE_ERROR_FAILED;
2537 ofu()->GetDirectoryForOriginAndType(
2538 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2539 ASSERT_EQ(base::File::FILE_OK, error);
2540 error = base::File::FILE_ERROR_FAILED;
2541 ofu()->GetDirectoryForOriginAndType(
2542 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2543 ASSERT_EQ(base::File::FILE_OK, error);
2545 // Delete all directories for origin1.
2546 ofu()->DeleteDirectoryForOriginAndType(origin1, std::string());
2548 // The directories for origin1 should be removed.
2549 error = base::File::FILE_ERROR_FAILED;
2550 ofu()->GetDirectoryForOriginAndType(
2551 origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
2552 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
2553 error = base::File::FILE_ERROR_FAILED;
2554 ofu()->GetDirectoryForOriginAndType(
2555 origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
2556 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
2558 // The directories for origin2 should not be removed.
2559 error = base::File::FILE_ERROR_FAILED;
2560 ofu()->GetDirectoryForOriginAndType(
2561 origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
2562 ASSERT_EQ(base::File::FILE_OK, error);
2563 error = base::File::FILE_ERROR_FAILED;
2564 ofu()->GetDirectoryForOriginAndType(
2565 origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
2566 ASSERT_EQ(base::File::FILE_OK, error);
2569 } // namespace content