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

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

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

Powered by Google App Engine
This is Rietveld 408576698