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