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

Side by Side Diff: content/browser/fileapi/obfuscated_file_util_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698