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