• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "storage/browser/fileapi/file_system_operation_impl.h"
6 
7 #include "base/bind.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/strings/stringprintf.h"
15 #include "content/browser/fileapi/mock_file_change_observer.h"
16 #include "content/browser/fileapi/mock_file_update_observer.h"
17 #include "content/browser/quota/mock_quota_manager.h"
18 #include "content/browser/quota/mock_quota_manager_proxy.h"
19 #include "content/public/test/async_file_test_helper.h"
20 #include "content/public/test/sandbox_file_system_test_helper.h"
21 #include "storage/browser/fileapi/file_system_context.h"
22 #include "storage/browser/fileapi/file_system_file_util.h"
23 #include "storage/browser/fileapi/file_system_operation_context.h"
24 #include "storage/browser/fileapi/file_system_operation_runner.h"
25 #include "storage/browser/fileapi/sandbox_file_system_backend.h"
26 #include "storage/browser/quota/quota_manager.h"
27 #include "storage/browser/quota/quota_manager_proxy.h"
28 #include "storage/common/blob/shareable_file_reference.h"
29 #include "storage/common/fileapi/file_system_util.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "url/gurl.h"
32 
33 using content::AsyncFileTestHelper;
34 using storage::FileSystemOperation;
35 using storage::FileSystemOperationContext;
36 using storage::FileSystemOperationRunner;
37 using storage::FileSystemURL;
38 using storage::QuotaManager;
39 using storage::QuotaManagerProxy;
40 using storage::ShareableFileReference;
41 
42 namespace content {
43 
44 // Test class for FileSystemOperationImpl.
45 class FileSystemOperationImplTest
46     : public testing::Test {
47  public:
FileSystemOperationImplTest()48   FileSystemOperationImplTest() : weak_factory_(this) {}
49 
50  protected:
SetUp()51   virtual void SetUp() OVERRIDE {
52     EXPECT_TRUE(base_.CreateUniqueTempDir());
53     change_observers_ =
54         storage::MockFileChangeObserver::CreateList(&change_observer_);
55     update_observers_ =
56         storage::MockFileUpdateObserver::CreateList(&update_observer_);
57 
58     base::FilePath base_dir = base_.path().AppendASCII("filesystem");
59     quota_manager_ =
60         new MockQuotaManager(false /* is_incognito */,
61                                     base_dir,
62                                     base::MessageLoopProxy::current().get(),
63                                     base::MessageLoopProxy::current().get(),
64                                     NULL /* special storage policy */);
65     quota_manager_proxy_ = new MockQuotaManagerProxy(
66         quota_manager(), base::MessageLoopProxy::current().get());
67     sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get());
68     sandbox_file_system_.AddFileChangeObserver(&change_observer_);
69     sandbox_file_system_.AddFileUpdateObserver(&update_observer_);
70     update_observer_.Disable();
71   }
72 
TearDown()73   virtual void TearDown() OVERRIDE {
74     // Let the client go away before dropping a ref of the quota manager proxy.
75     quota_manager_proxy()->SimulateQuotaManagerDestroyed();
76     quota_manager_ = NULL;
77     quota_manager_proxy_ = NULL;
78     sandbox_file_system_.TearDown();
79   }
80 
operation_runner()81   FileSystemOperationRunner* operation_runner() {
82     return sandbox_file_system_.operation_runner();
83   }
84 
info() const85   const base::File::Info& info() const { return info_; }
path() const86   const base::FilePath& path() const { return path_; }
entries() const87   const std::vector<storage::DirectoryEntry>& entries() const {
88     return entries_;
89   }
90 
shareable_file_ref() const91   const ShareableFileReference* shareable_file_ref() const {
92     return shareable_file_ref_.get();
93   }
94 
quota_manager()95   MockQuotaManager* quota_manager() {
96     return static_cast<MockQuotaManager*>(quota_manager_.get());
97   }
98 
quota_manager_proxy()99   MockQuotaManagerProxy* quota_manager_proxy() {
100     return static_cast<MockQuotaManagerProxy*>(
101         quota_manager_proxy_.get());
102   }
103 
file_util()104   storage::FileSystemFileUtil* file_util() {
105     return sandbox_file_system_.file_util();
106   }
107 
change_observer()108   storage::MockFileChangeObserver* change_observer() {
109     return &change_observer_;
110   }
111 
NewContext()112   scoped_ptr<FileSystemOperationContext> NewContext() {
113     FileSystemOperationContext* context =
114         sandbox_file_system_.NewOperationContext();
115     // Grant enough quota for all test cases.
116     context->set_allowed_bytes_growth(1000000);
117     return make_scoped_ptr(context);
118   }
119 
URLForPath(const std::string & path) const120   FileSystemURL URLForPath(const std::string& path) const {
121     return sandbox_file_system_.CreateURLFromUTF8(path);
122   }
123 
PlatformPath(const std::string & path)124   base::FilePath PlatformPath(const std::string& path) {
125     return sandbox_file_system_.GetLocalPath(
126         base::FilePath::FromUTF8Unsafe(path));
127   }
128 
FileExists(const std::string & path)129   bool FileExists(const std::string& path) {
130     return AsyncFileTestHelper::FileExists(
131         sandbox_file_system_.file_system_context(), URLForPath(path),
132         AsyncFileTestHelper::kDontCheckSize);
133   }
134 
DirectoryExists(const std::string & path)135   bool DirectoryExists(const std::string& path) {
136     return AsyncFileTestHelper::DirectoryExists(
137         sandbox_file_system_.file_system_context(), URLForPath(path));
138   }
139 
CreateFile(const std::string & path)140   FileSystemURL CreateFile(const std::string& path) {
141     FileSystemURL url = URLForPath(path);
142     bool created = false;
143     EXPECT_EQ(base::File::FILE_OK,
144               file_util()->EnsureFileExists(NewContext().get(),
145                                             url, &created));
146     EXPECT_TRUE(created);
147     return url;
148   }
149 
CreateDirectory(const std::string & path)150   FileSystemURL CreateDirectory(const std::string& path) {
151     FileSystemURL url = URLForPath(path);
152     EXPECT_EQ(base::File::FILE_OK,
153               file_util()->CreateDirectory(NewContext().get(), url,
154                                            false /* exclusive */, true));
155     return url;
156   }
157 
GetFileSize(const std::string & path)158   int64 GetFileSize(const std::string& path) {
159     base::File::Info info;
160     EXPECT_TRUE(base::GetFileInfo(PlatformPath(path), &info));
161     return info.size;
162   }
163 
164   // Callbacks for recording test results.
RecordStatusCallback(const base::Closure & closure,base::File::Error * status)165   FileSystemOperation::StatusCallback RecordStatusCallback(
166       const base::Closure& closure,
167       base::File::Error* status) {
168     return base::Bind(&FileSystemOperationImplTest::DidFinish,
169                       weak_factory_.GetWeakPtr(),
170                       closure,
171                       status);
172   }
173 
RecordReadDirectoryCallback(const base::Closure & closure,base::File::Error * status)174   FileSystemOperation::ReadDirectoryCallback RecordReadDirectoryCallback(
175       const base::Closure& closure,
176       base::File::Error* status) {
177     return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
178                       weak_factory_.GetWeakPtr(),
179                       closure,
180                       status);
181   }
182 
RecordMetadataCallback(const base::Closure & closure,base::File::Error * status)183   FileSystemOperation::GetMetadataCallback RecordMetadataCallback(
184       const base::Closure& closure,
185       base::File::Error* status) {
186     return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
187                       weak_factory_.GetWeakPtr(),
188                       closure,
189                       status);
190   }
191 
RecordSnapshotFileCallback(const base::Closure & closure,base::File::Error * status)192   FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback(
193       const base::Closure& closure,
194       base::File::Error* status) {
195     return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
196                       weak_factory_.GetWeakPtr(),
197                       closure,
198                       status);
199   }
200 
DidFinish(const base::Closure & closure,base::File::Error * status,base::File::Error actual)201   void DidFinish(const base::Closure& closure,
202                  base::File::Error* status,
203                  base::File::Error actual) {
204     *status = actual;
205     closure.Run();
206   }
207 
DidReadDirectory(const base::Closure & closure,base::File::Error * status,base::File::Error actual,const std::vector<storage::DirectoryEntry> & entries,bool)208   void DidReadDirectory(const base::Closure& closure,
209                         base::File::Error* status,
210                         base::File::Error actual,
211                         const std::vector<storage::DirectoryEntry>& entries,
212                         bool /* has_more */) {
213     entries_ = entries;
214     *status = actual;
215     closure.Run();
216   }
217 
DidGetMetadata(const base::Closure & closure,base::File::Error * status,base::File::Error actual,const base::File::Info & info)218   void DidGetMetadata(const base::Closure& closure,
219                       base::File::Error* status,
220                       base::File::Error actual,
221                       const base::File::Info& info) {
222     info_ = info;
223     *status = actual;
224     closure.Run();
225   }
226 
DidCreateSnapshotFile(const base::Closure & closure,base::File::Error * status,base::File::Error actual,const base::File::Info & info,const base::FilePath & platform_path,const scoped_refptr<ShareableFileReference> & shareable_file_ref)227   void DidCreateSnapshotFile(
228       const base::Closure& closure,
229       base::File::Error* status,
230       base::File::Error actual,
231       const base::File::Info& info,
232       const base::FilePath& platform_path,
233       const scoped_refptr<ShareableFileReference>& shareable_file_ref) {
234     info_ = info;
235     path_ = platform_path;
236     *status = actual;
237     shareable_file_ref_ = shareable_file_ref;
238     closure.Run();
239   }
240 
GetDataSizeOnDisk()241   int64 GetDataSizeOnDisk() {
242     return sandbox_file_system_.ComputeCurrentOriginUsage() -
243         sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
244   }
245 
GetUsageAndQuota(int64 * usage,int64 * quota)246   void GetUsageAndQuota(int64* usage, int64* quota) {
247     storage::QuotaStatusCode status =
248         AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
249                                               sandbox_file_system_.origin(),
250                                               sandbox_file_system_.type(),
251                                               usage,
252                                               quota);
253     base::RunLoop().RunUntilIdle();
254     ASSERT_EQ(storage::kQuotaStatusOk, status);
255   }
256 
ComputePathCost(const FileSystemURL & url)257   int64 ComputePathCost(const FileSystemURL& url) {
258     int64 base_usage;
259     GetUsageAndQuota(&base_usage, NULL);
260 
261     AsyncFileTestHelper::CreateFile(
262         sandbox_file_system_.file_system_context(), url);
263     EXPECT_EQ(base::File::FILE_OK, Remove(url, false /* recursive */));
264 
265     change_observer()->ResetCount();
266 
267     int64 total_usage;
268     GetUsageAndQuota(&total_usage, NULL);
269     return total_usage - base_usage;
270   }
271 
GrantQuotaForCurrentUsage()272   void GrantQuotaForCurrentUsage() {
273     int64 usage;
274     GetUsageAndQuota(&usage, NULL);
275     quota_manager()->SetQuota(sandbox_file_system_.origin(),
276                               sandbox_file_system_.storage_type(),
277                               usage);
278   }
279 
GetUsage()280   int64 GetUsage() {
281     int64 usage = 0;
282     GetUsageAndQuota(&usage, NULL);
283     return usage;
284   }
285 
AddQuota(int64 quota_delta)286   void AddQuota(int64 quota_delta) {
287     int64 quota;
288     GetUsageAndQuota(NULL, &quota);
289     quota_manager()->SetQuota(sandbox_file_system_.origin(),
290                               sandbox_file_system_.storage_type(),
291                               quota + quota_delta);
292   }
293 
Move(const FileSystemURL & src,const FileSystemURL & dest,storage::FileSystemOperation::CopyOrMoveOption option)294   base::File::Error Move(
295       const FileSystemURL& src,
296       const FileSystemURL& dest,
297       storage::FileSystemOperation::CopyOrMoveOption option) {
298     base::File::Error status;
299     base::RunLoop run_loop;
300     update_observer_.Enable();
301     operation_runner()->Move(
302         src,
303         dest,
304         option,
305         RecordStatusCallback(run_loop.QuitClosure(), &status));
306     run_loop.Run();
307     update_observer_.Disable();
308     return status;
309   }
310 
Copy(const FileSystemURL & src,const FileSystemURL & dest,storage::FileSystemOperation::CopyOrMoveOption option)311   base::File::Error Copy(
312       const FileSystemURL& src,
313       const FileSystemURL& dest,
314       storage::FileSystemOperation::CopyOrMoveOption option) {
315     base::File::Error status;
316     base::RunLoop run_loop;
317     update_observer_.Enable();
318     operation_runner()->Copy(
319         src,
320         dest,
321         option,
322         FileSystemOperationRunner::CopyProgressCallback(),
323         RecordStatusCallback(run_loop.QuitClosure(), &status));
324     run_loop.Run();
325     update_observer_.Disable();
326     return status;
327   }
328 
CopyInForeignFile(const base::FilePath & src,const FileSystemURL & dest)329   base::File::Error CopyInForeignFile(const base::FilePath& src,
330                                       const FileSystemURL& dest) {
331     base::File::Error status;
332     base::RunLoop run_loop;
333     update_observer_.Enable();
334     operation_runner()->CopyInForeignFile(
335         src, dest, RecordStatusCallback(run_loop.QuitClosure(), &status));
336     run_loop.Run();
337     update_observer_.Disable();
338     return status;
339   }
340 
Truncate(const FileSystemURL & url,int size)341   base::File::Error Truncate(const FileSystemURL& url, int size) {
342     base::File::Error status;
343     base::RunLoop run_loop;
344     update_observer_.Enable();
345     operation_runner()->Truncate(
346         url, size, RecordStatusCallback(run_loop.QuitClosure(), &status));
347     run_loop.Run();
348     update_observer_.Disable();
349     return status;
350   }
351 
CreateFile(const FileSystemURL & url,bool exclusive)352   base::File::Error CreateFile(const FileSystemURL& url, bool exclusive) {
353     base::File::Error status;
354     base::RunLoop run_loop;
355     update_observer_.Enable();
356     operation_runner()->CreateFile(
357         url, exclusive, RecordStatusCallback(run_loop.QuitClosure(), &status));
358     run_loop.Run();
359     update_observer_.Disable();
360     return status;
361   }
362 
Remove(const FileSystemURL & url,bool recursive)363   base::File::Error Remove(const FileSystemURL& url, bool recursive) {
364     base::File::Error status;
365     base::RunLoop run_loop;
366     update_observer_.Enable();
367     operation_runner()->Remove(
368         url, recursive, RecordStatusCallback(run_loop.QuitClosure(), &status));
369     run_loop.Run();
370     update_observer_.Disable();
371     return status;
372   }
373 
CreateDirectory(const FileSystemURL & url,bool exclusive,bool recursive)374   base::File::Error CreateDirectory(const FileSystemURL& url,
375                                     bool exclusive,
376                                     bool recursive) {
377     base::File::Error status;
378     base::RunLoop run_loop;
379     update_observer_.Enable();
380     operation_runner()->CreateDirectory(
381         url,
382         exclusive,
383         recursive,
384         RecordStatusCallback(run_loop.QuitClosure(), &status));
385     run_loop.Run();
386     update_observer_.Disable();
387     return status;
388   }
389 
GetMetadata(const FileSystemURL & url)390   base::File::Error GetMetadata(const FileSystemURL& url) {
391     base::File::Error status;
392     base::RunLoop run_loop;
393     update_observer_.Enable();
394     operation_runner()->GetMetadata(
395         url, RecordMetadataCallback(run_loop.QuitClosure(), &status));
396     run_loop.Run();
397     update_observer_.Disable();
398     return status;
399   }
400 
ReadDirectory(const FileSystemURL & url)401   base::File::Error ReadDirectory(const FileSystemURL& url) {
402     base::File::Error status;
403     base::RunLoop run_loop;
404     update_observer_.Enable();
405     operation_runner()->ReadDirectory(
406         url, RecordReadDirectoryCallback(run_loop.QuitClosure(), &status));
407     run_loop.Run();
408     update_observer_.Disable();
409     return status;
410   }
411 
CreateSnapshotFile(const FileSystemURL & url)412   base::File::Error CreateSnapshotFile(const FileSystemURL& url) {
413     base::File::Error status;
414     base::RunLoop run_loop;
415     update_observer_.Enable();
416     operation_runner()->CreateSnapshotFile(
417         url, RecordSnapshotFileCallback(run_loop.QuitClosure(), &status));
418     run_loop.Run();
419     update_observer_.Disable();
420     return status;
421   }
422 
FileExists(const FileSystemURL & url)423   base::File::Error FileExists(const FileSystemURL& url) {
424     base::File::Error status;
425     base::RunLoop run_loop;
426     update_observer_.Enable();
427     operation_runner()->FileExists(
428         url, RecordStatusCallback(run_loop.QuitClosure(), &status));
429     run_loop.Run();
430     update_observer_.Disable();
431     return status;
432   }
433 
DirectoryExists(const FileSystemURL & url)434   base::File::Error DirectoryExists(const FileSystemURL& url) {
435     base::File::Error status;
436     base::RunLoop run_loop;
437     update_observer_.Enable();
438     operation_runner()->DirectoryExists(
439         url, RecordStatusCallback(run_loop.QuitClosure(), &status));
440     run_loop.Run();
441     update_observer_.Disable();
442     return status;
443   }
444 
TouchFile(const FileSystemURL & url,const base::Time & last_access_time,const base::Time & last_modified_time)445   base::File::Error TouchFile(const FileSystemURL& url,
446                               const base::Time& last_access_time,
447                               const base::Time& last_modified_time) {
448     base::File::Error status;
449     base::RunLoop run_loop;
450     update_observer_.Enable();
451     operation_runner()->TouchFile(
452         url,
453         last_access_time,
454         last_modified_time,
455         RecordStatusCallback(run_loop.QuitClosure(), &status));
456     run_loop.Run();
457     update_observer_.Disable();
458     return status;
459   }
460 
461  private:
462   base::MessageLoopForIO message_loop_;
463   scoped_refptr<QuotaManager> quota_manager_;
464   scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
465 
466   // Common temp base for nondestructive uses.
467   base::ScopedTempDir base_;
468 
469   SandboxFileSystemTestHelper sandbox_file_system_;
470 
471   // For post-operation status.
472   base::File::Info info_;
473   base::FilePath path_;
474   std::vector<storage::DirectoryEntry> entries_;
475   scoped_refptr<ShareableFileReference> shareable_file_ref_;
476 
477   storage::MockFileChangeObserver change_observer_;
478   storage::ChangeObserverList change_observers_;
479   storage::MockFileUpdateObserver update_observer_;
480   storage::UpdateObserverList update_observers_;
481 
482   base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
483 
484   DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest);
485 };
486 
TEST_F(FileSystemOperationImplTest,TestMoveFailureSrcDoesntExist)487 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) {
488   change_observer()->ResetCount();
489   EXPECT_EQ(
490       base::File::FILE_ERROR_NOT_FOUND,
491       Move(URLForPath("a"), URLForPath("b"), FileSystemOperation::OPTION_NONE));
492   EXPECT_TRUE(change_observer()->HasNoChange());
493 }
494 
TEST_F(FileSystemOperationImplTest,TestMoveFailureContainsPath)495 TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) {
496   FileSystemURL src_dir(CreateDirectory("src"));
497   FileSystemURL dest_dir(CreateDirectory("src/dest"));
498 
499   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
500             Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
501   EXPECT_TRUE(change_observer()->HasNoChange());
502 }
503 
TEST_F(FileSystemOperationImplTest,TestMoveFailureSrcDirExistsDestFile)504 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) {
505   // Src exists and is dir. Dest is a file.
506   FileSystemURL src_dir(CreateDirectory("src"));
507   FileSystemURL dest_dir(CreateDirectory("dest"));
508   FileSystemURL dest_file(CreateFile("dest/file"));
509 
510   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
511             Move(src_dir, dest_file, FileSystemOperation::OPTION_NONE));
512   EXPECT_TRUE(change_observer()->HasNoChange());
513 }
514 
TEST_F(FileSystemOperationImplTest,TestMoveFailureSrcFileExistsDestNonEmptyDir)515 TEST_F(FileSystemOperationImplTest,
516        TestMoveFailureSrcFileExistsDestNonEmptyDir) {
517   // Src exists and is a directory. Dest is a non-empty directory.
518   FileSystemURL src_dir(CreateDirectory("src"));
519   FileSystemURL dest_dir(CreateDirectory("dest"));
520   FileSystemURL dest_file(CreateFile("dest/file"));
521 
522   EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
523             Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
524   EXPECT_TRUE(change_observer()->HasNoChange());
525 }
526 
TEST_F(FileSystemOperationImplTest,TestMoveFailureSrcFileExistsDestDir)527 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) {
528   // Src exists and is a file. Dest is a directory.
529   FileSystemURL src_dir(CreateDirectory("src"));
530   FileSystemURL src_file(CreateFile("src/file"));
531   FileSystemURL dest_dir(CreateDirectory("dest"));
532 
533   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
534             Move(src_file, dest_dir, FileSystemOperation::OPTION_NONE));
535   EXPECT_TRUE(change_observer()->HasNoChange());
536 }
537 
TEST_F(FileSystemOperationImplTest,TestMoveFailureDestParentDoesntExist)538 TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) {
539   // Dest. parent path does not exist.
540   FileSystemURL src_dir(CreateDirectory("src"));
541   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
542             Move(src_dir,
543                  URLForPath("nonexistent/deset"),
544                  FileSystemOperation::OPTION_NONE));
545   EXPECT_TRUE(change_observer()->HasNoChange());
546 }
547 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSrcFileAndOverwrite)548 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) {
549   FileSystemURL src_file(CreateFile("src"));
550   FileSystemURL dest_file(CreateFile("dest"));
551 
552   EXPECT_EQ(base::File::FILE_OK,
553             Move(src_file, dest_file, FileSystemOperation::OPTION_NONE));
554   EXPECT_TRUE(FileExists("dest"));
555 
556   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
557   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
558   EXPECT_TRUE(change_observer()->HasNoChange());
559 
560   EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
561 }
562 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSrcFileAndNew)563 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) {
564   FileSystemURL src_file(CreateFile("src"));
565 
566   EXPECT_EQ(
567       base::File::FILE_OK,
568       Move(src_file, URLForPath("new"), FileSystemOperation::OPTION_NONE));
569   EXPECT_TRUE(FileExists("new"));
570 
571   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
572   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
573   EXPECT_TRUE(change_observer()->HasNoChange());
574 }
575 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSrcDirAndOverwrite)576 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) {
577   FileSystemURL src_dir(CreateDirectory("src"));
578   FileSystemURL dest_dir(CreateDirectory("dest"));
579 
580   EXPECT_EQ(base::File::FILE_OK,
581             Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
582   EXPECT_FALSE(DirectoryExists("src"));
583 
584   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
585   EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
586   EXPECT_TRUE(change_observer()->HasNoChange());
587 
588   // Make sure we've overwritten but not moved the source under the |dest_dir|.
589   EXPECT_TRUE(DirectoryExists("dest"));
590   EXPECT_FALSE(DirectoryExists("dest/src"));
591 }
592 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSrcDirAndNew)593 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) {
594   FileSystemURL src_dir(CreateDirectory("src"));
595   FileSystemURL dest_dir(CreateDirectory("dest"));
596 
597   EXPECT_EQ(
598       base::File::FILE_OK,
599       Move(src_dir, URLForPath("dest/new"), FileSystemOperation::OPTION_NONE));
600   EXPECT_FALSE(DirectoryExists("src"));
601   EXPECT_TRUE(DirectoryExists("dest/new"));
602 
603   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
604   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
605   EXPECT_TRUE(change_observer()->HasNoChange());
606 }
607 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSrcDirRecursive)608 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) {
609   FileSystemURL src_dir(CreateDirectory("src"));
610   CreateDirectory("src/dir");
611   CreateFile("src/dir/sub");
612 
613   FileSystemURL dest_dir(CreateDirectory("dest"));
614 
615   EXPECT_EQ(base::File::FILE_OK,
616             Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
617   EXPECT_TRUE(DirectoryExists("dest/dir"));
618   EXPECT_TRUE(FileExists("dest/dir/sub"));
619 
620   EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count());
621   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
622   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
623   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
624   EXPECT_TRUE(change_observer()->HasNoChange());
625 }
626 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSamePath)627 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSamePath) {
628   FileSystemURL src_dir(CreateDirectory("src"));
629   CreateDirectory("src/dir");
630   CreateFile("src/dir/sub");
631 
632   EXPECT_EQ(base::File::FILE_OK,
633             Move(src_dir, src_dir, FileSystemOperation::OPTION_NONE));
634   EXPECT_TRUE(DirectoryExists("src/dir"));
635   EXPECT_TRUE(FileExists("src/dir/sub"));
636 
637   EXPECT_EQ(0, change_observer()->get_and_reset_remove_directory_count());
638   EXPECT_EQ(0, change_observer()->get_and_reset_create_directory_count());
639   EXPECT_EQ(0, change_observer()->get_and_reset_remove_file_count());
640   EXPECT_EQ(0, change_observer()->get_and_reset_create_file_from_count());
641   EXPECT_TRUE(change_observer()->HasNoChange());
642 }
643 
TEST_F(FileSystemOperationImplTest,TestCopyFailureSrcDoesntExist)644 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) {
645   EXPECT_EQ(
646       base::File::FILE_ERROR_NOT_FOUND,
647       Copy(URLForPath("a"), URLForPath("b"), FileSystemOperation::OPTION_NONE));
648   EXPECT_TRUE(change_observer()->HasNoChange());
649 }
650 
TEST_F(FileSystemOperationImplTest,TestCopyFailureContainsPath)651 TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) {
652   FileSystemURL src_dir(CreateDirectory("src"));
653   FileSystemURL dest_dir(CreateDirectory("src/dir"));
654 
655   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
656             Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
657   EXPECT_TRUE(change_observer()->HasNoChange());
658 }
659 
TEST_F(FileSystemOperationImplTest,TestCopyFailureSrcDirExistsDestFile)660 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) {
661   // Src exists and is dir. Dest is a file.
662   FileSystemURL src_dir(CreateDirectory("src"));
663   FileSystemURL dest_dir(CreateDirectory("dest"));
664   FileSystemURL dest_file(CreateFile("dest/file"));
665 
666   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
667             Copy(src_dir, dest_file, FileSystemOperation::OPTION_NONE));
668   EXPECT_TRUE(change_observer()->HasNoChange());
669 }
670 
TEST_F(FileSystemOperationImplTest,TestCopyFailureSrcFileExistsDestNonEmptyDir)671 TEST_F(FileSystemOperationImplTest,
672        TestCopyFailureSrcFileExistsDestNonEmptyDir) {
673   // Src exists and is a directory. Dest is a non-empty directory.
674   FileSystemURL src_dir(CreateDirectory("src"));
675   FileSystemURL dest_dir(CreateDirectory("dest"));
676   FileSystemURL dest_file(CreateFile("dest/file"));
677 
678   EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
679             Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
680   EXPECT_TRUE(change_observer()->HasNoChange());
681 }
682 
TEST_F(FileSystemOperationImplTest,TestCopyFailureSrcFileExistsDestDir)683 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) {
684   // Src exists and is a file. Dest is a directory.
685   FileSystemURL src_file(CreateFile("src"));
686   FileSystemURL dest_dir(CreateDirectory("dest"));
687 
688   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
689             Copy(src_file, dest_dir, FileSystemOperation::OPTION_NONE));
690   EXPECT_TRUE(change_observer()->HasNoChange());
691 }
692 
TEST_F(FileSystemOperationImplTest,TestCopyFailureDestParentDoesntExist)693 TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) {
694   // Dest. parent path does not exist.
695   FileSystemURL src_dir(CreateDirectory("src"));
696 
697   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
698             Copy(src_dir,
699                  URLForPath("nonexistent/dest"),
700                  FileSystemOperation::OPTION_NONE));
701   EXPECT_TRUE(change_observer()->HasNoChange());
702 }
703 
TEST_F(FileSystemOperationImplTest,TestCopyFailureByQuota)704 TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) {
705   FileSystemURL src_dir(CreateDirectory("src"));
706   FileSystemURL src_file(CreateFile("src/file"));
707   FileSystemURL dest_dir(CreateDirectory("dest"));
708   EXPECT_EQ(base::File::FILE_OK, Truncate(src_file, 6));
709   EXPECT_EQ(6, GetFileSize("src/file"));
710 
711   FileSystemURL dest_file(URLForPath("dest/file"));
712   int64 dest_path_cost = ComputePathCost(dest_file);
713   GrantQuotaForCurrentUsage();
714   AddQuota(6 + dest_path_cost - 1);
715 
716   EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
717             Copy(src_file, dest_file, FileSystemOperation::OPTION_NONE));
718   EXPECT_FALSE(FileExists("dest/file"));
719 }
720 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcFileAndOverwrite)721 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) {
722   FileSystemURL src_file(CreateFile("src"));
723   FileSystemURL dest_file(CreateFile("dest"));
724 
725   EXPECT_EQ(base::File::FILE_OK,
726             Copy(src_file, dest_file, FileSystemOperation::OPTION_NONE));
727 
728   EXPECT_TRUE(FileExists("dest"));
729   EXPECT_EQ(4, quota_manager_proxy()->notify_storage_accessed_count());
730   EXPECT_EQ(2, change_observer()->get_and_reset_modify_file_count());
731 
732   EXPECT_TRUE(change_observer()->HasNoChange());
733 }
734 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcFileAndNew)735 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) {
736   FileSystemURL src_file(CreateFile("src"));
737 
738   EXPECT_EQ(
739       base::File::FILE_OK,
740       Copy(src_file, URLForPath("new"), FileSystemOperation::OPTION_NONE));
741   EXPECT_TRUE(FileExists("new"));
742   EXPECT_EQ(4, quota_manager_proxy()->notify_storage_accessed_count());
743 
744   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
745   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
746   EXPECT_TRUE(change_observer()->HasNoChange());
747 }
748 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcDirAndOverwrite)749 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) {
750   FileSystemURL src_dir(CreateDirectory("src"));
751   FileSystemURL dest_dir(CreateDirectory("dest"));
752 
753   EXPECT_EQ(base::File::FILE_OK,
754             Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
755 
756   // Make sure we've overwritten but not copied the source under the |dest_dir|.
757   EXPECT_TRUE(DirectoryExists("dest"));
758   EXPECT_FALSE(DirectoryExists("dest/src"));
759   EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 3);
760 
761   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
762   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
763   EXPECT_TRUE(change_observer()->HasNoChange());
764 }
765 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcDirAndNew)766 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) {
767   FileSystemURL src_dir(CreateDirectory("src"));
768   FileSystemURL dest_dir_new(URLForPath("dest"));
769 
770   EXPECT_EQ(base::File::FILE_OK,
771             Copy(src_dir, dest_dir_new, FileSystemOperation::OPTION_NONE));
772   EXPECT_TRUE(DirectoryExists("dest"));
773   EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2);
774 
775   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
776   EXPECT_TRUE(change_observer()->HasNoChange());
777 }
778 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcDirRecursive)779 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) {
780   FileSystemURL src_dir(CreateDirectory("src"));
781   CreateDirectory("src/dir");
782   CreateFile("src/dir/sub");
783 
784   FileSystemURL dest_dir(CreateDirectory("dest"));
785 
786   EXPECT_EQ(base::File::FILE_OK,
787             Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
788 
789   EXPECT_TRUE(DirectoryExists("dest/dir"));
790   EXPECT_TRUE(FileExists("dest/dir/sub"));
791 
792   // For recursive copy we may record multiple read access.
793   EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 1);
794 
795   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
796   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
797   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
798   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
799   EXPECT_TRUE(change_observer()->HasNoChange());
800 }
801 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSamePath)802 TEST_F(FileSystemOperationImplTest, TestCopySuccessSamePath) {
803   FileSystemURL src_dir(CreateDirectory("src"));
804   CreateDirectory("src/dir");
805   CreateFile("src/dir/sub");
806 
807   EXPECT_EQ(base::File::FILE_OK,
808             Copy(src_dir, src_dir, FileSystemOperation::OPTION_NONE));
809 
810   EXPECT_TRUE(DirectoryExists("src/dir"));
811   EXPECT_TRUE(FileExists("src/dir/sub"));
812 
813   EXPECT_EQ(0, change_observer()->get_and_reset_create_directory_count());
814   EXPECT_EQ(0, change_observer()->get_and_reset_remove_file_count());
815   EXPECT_EQ(0, change_observer()->get_and_reset_create_file_from_count());
816   EXPECT_TRUE(change_observer()->HasNoChange());
817 }
818 
TEST_F(FileSystemOperationImplTest,TestCopyInForeignFileSuccess)819 TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) {
820   base::FilePath src_local_disk_file_path;
821   base::CreateTemporaryFile(&src_local_disk_file_path);
822   const char test_data[] = "foo";
823   int data_size = ARRAYSIZE_UNSAFE(test_data);
824   base::WriteFile(src_local_disk_file_path, test_data, data_size);
825 
826   FileSystemURL dest_dir(CreateDirectory("dest"));
827 
828   int64 before_usage;
829   GetUsageAndQuota(&before_usage, NULL);
830 
831   // Check that the file copied and corresponding usage increased.
832   EXPECT_EQ(
833       base::File::FILE_OK,
834       CopyInForeignFile(src_local_disk_file_path, URLForPath("dest/file")));
835 
836   EXPECT_EQ(1, change_observer()->create_file_count());
837   EXPECT_TRUE(FileExists("dest/file"));
838   int64 after_usage;
839   GetUsageAndQuota(&after_usage, NULL);
840   EXPECT_GT(after_usage, before_usage);
841 
842   // Compare contents of src and copied file.
843   char buffer[100];
844   EXPECT_EQ(data_size, base::ReadFile(PlatformPath("dest/file"),
845                                       buffer, data_size));
846   for (int i = 0; i < data_size; ++i)
847     EXPECT_EQ(test_data[i], buffer[i]);
848 }
849 
TEST_F(FileSystemOperationImplTest,TestCopyInForeignFileFailureByQuota)850 TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) {
851   base::FilePath src_local_disk_file_path;
852   base::CreateTemporaryFile(&src_local_disk_file_path);
853   const char test_data[] = "foo";
854   base::WriteFile(src_local_disk_file_path, test_data,
855                        ARRAYSIZE_UNSAFE(test_data));
856 
857   FileSystemURL dest_dir(CreateDirectory("dest"));
858 
859   GrantQuotaForCurrentUsage();
860   EXPECT_EQ(
861       base::File::FILE_ERROR_NO_SPACE,
862       CopyInForeignFile(src_local_disk_file_path, URLForPath("dest/file")));
863 
864   EXPECT_FALSE(FileExists("dest/file"));
865   EXPECT_EQ(0, change_observer()->create_file_count());
866 }
867 
TEST_F(FileSystemOperationImplTest,TestCreateFileFailure)868 TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) {
869   // Already existing file and exclusive true.
870   FileSystemURL file(CreateFile("file"));
871   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, CreateFile(file, true));
872   EXPECT_TRUE(change_observer()->HasNoChange());
873 }
874 
TEST_F(FileSystemOperationImplTest,TestCreateFileSuccessFileExists)875 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) {
876   // Already existing file and exclusive false.
877   FileSystemURL file(CreateFile("file"));
878   EXPECT_EQ(base::File::FILE_OK, CreateFile(file, false));
879   EXPECT_TRUE(FileExists("file"));
880 
881   // The file was already there; did nothing.
882   EXPECT_TRUE(change_observer()->HasNoChange());
883 }
884 
TEST_F(FileSystemOperationImplTest,TestCreateFileSuccessExclusive)885 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) {
886   // File doesn't exist but exclusive is true.
887   EXPECT_EQ(base::File::FILE_OK, CreateFile(URLForPath("new"), true));
888   EXPECT_TRUE(FileExists("new"));
889   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
890 }
891 
TEST_F(FileSystemOperationImplTest,TestCreateFileSuccessFileDoesntExist)892 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) {
893   // Non existing file.
894   EXPECT_EQ(base::File::FILE_OK, CreateFile(URLForPath("nonexistent"), false));
895   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
896 }
897 
TEST_F(FileSystemOperationImplTest,TestCreateDirFailureDestParentDoesntExist)898 TEST_F(FileSystemOperationImplTest,
899        TestCreateDirFailureDestParentDoesntExist) {
900   // Dest. parent path does not exist.
901   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
902             CreateDirectory(URLForPath("nonexistent/dir"), false, false));
903   EXPECT_TRUE(change_observer()->HasNoChange());
904 }
905 
TEST_F(FileSystemOperationImplTest,TestCreateDirFailureDirExists)906 TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) {
907   // Exclusive and dir existing at path.
908   FileSystemURL dir(CreateDirectory("dir"));
909   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, CreateDirectory(dir, true, false));
910   EXPECT_TRUE(change_observer()->HasNoChange());
911 }
912 
TEST_F(FileSystemOperationImplTest,TestCreateDirFailureFileExists)913 TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) {
914   // Exclusive true and file existing at path.
915   FileSystemURL file(CreateFile("file"));
916   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, CreateDirectory(file, true, false));
917   EXPECT_TRUE(change_observer()->HasNoChange());
918 }
919 
TEST_F(FileSystemOperationImplTest,TestCreateDirSuccess)920 TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) {
921   // Dir exists and exclusive is false.
922   FileSystemURL dir(CreateDirectory("dir"));
923   EXPECT_EQ(base::File::FILE_OK, CreateDirectory(dir, false, false));
924   EXPECT_TRUE(change_observer()->HasNoChange());
925 
926   // Dir doesn't exist.
927   EXPECT_EQ(base::File::FILE_OK,
928             CreateDirectory(URLForPath("new"), false, false));
929   EXPECT_TRUE(DirectoryExists("new"));
930   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
931 }
932 
TEST_F(FileSystemOperationImplTest,TestCreateDirSuccessExclusive)933 TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) {
934   // Dir doesn't exist.
935   EXPECT_EQ(base::File::FILE_OK,
936             CreateDirectory(URLForPath("new"), true, false));
937   EXPECT_TRUE(DirectoryExists("new"));
938   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
939   EXPECT_TRUE(change_observer()->HasNoChange());
940 }
941 
TEST_F(FileSystemOperationImplTest,TestExistsAndMetadataFailure)942 TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) {
943   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
944             GetMetadata(URLForPath("nonexistent")));
945 
946   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
947             FileExists(URLForPath("nonexistent")));
948 
949   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
950             DirectoryExists(URLForPath("nonexistent")));
951   EXPECT_TRUE(change_observer()->HasNoChange());
952 }
953 
TEST_F(FileSystemOperationImplTest,TestExistsAndMetadataSuccess)954 TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) {
955   FileSystemURL dir(CreateDirectory("dir"));
956   FileSystemURL file(CreateFile("dir/file"));
957   int read_access = 0;
958 
959   EXPECT_EQ(base::File::FILE_OK, DirectoryExists(dir));
960   ++read_access;
961 
962   EXPECT_EQ(base::File::FILE_OK, GetMetadata(dir));
963   EXPECT_TRUE(info().is_directory);
964   ++read_access;
965 
966   EXPECT_EQ(base::File::FILE_OK, FileExists(file));
967   ++read_access;
968 
969   EXPECT_EQ(base::File::FILE_OK, GetMetadata(file));
970   EXPECT_FALSE(info().is_directory);
971   ++read_access;
972 
973   EXPECT_EQ(read_access,
974             quota_manager_proxy()->notify_storage_accessed_count());
975   EXPECT_TRUE(change_observer()->HasNoChange());
976 }
977 
TEST_F(FileSystemOperationImplTest,TestTypeMismatchErrors)978 TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) {
979   FileSystemURL dir(CreateDirectory("dir"));
980   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, FileExists(dir));
981 
982   FileSystemURL file(CreateFile("file"));
983   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, DirectoryExists(file));
984 }
985 
TEST_F(FileSystemOperationImplTest,TestReadDirFailure)986 TEST_F(FileSystemOperationImplTest, TestReadDirFailure) {
987   // Path doesn't exist
988   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
989             ReadDirectory(URLForPath("nonexistent")));
990 
991   // File exists.
992   FileSystemURL file(CreateFile("file"));
993   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, ReadDirectory(file));
994   EXPECT_TRUE(change_observer()->HasNoChange());
995 }
996 
TEST_F(FileSystemOperationImplTest,TestReadDirSuccess)997 TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) {
998   //      parent_dir
999   //       |       |
1000   //  child_dir  child_file
1001   // Verify reading parent_dir.
1002   FileSystemURL parent_dir(CreateDirectory("dir"));
1003   FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
1004   FileSystemURL child_file(CreateFile("dir/child_file"));
1005 
1006   EXPECT_EQ(base::File::FILE_OK, ReadDirectory(parent_dir));
1007   EXPECT_EQ(2u, entries().size());
1008 
1009   for (size_t i = 0; i < entries().size(); ++i) {
1010     if (entries()[i].is_directory)
1011       EXPECT_EQ(FILE_PATH_LITERAL("child_dir"), entries()[i].name);
1012     else
1013       EXPECT_EQ(FILE_PATH_LITERAL("child_file"), entries()[i].name);
1014   }
1015   EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
1016   EXPECT_TRUE(change_observer()->HasNoChange());
1017 }
1018 
TEST_F(FileSystemOperationImplTest,TestRemoveFailure)1019 TEST_F(FileSystemOperationImplTest, TestRemoveFailure) {
1020   // Path doesn't exist.
1021   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
1022             Remove(URLForPath("nonexistent"), false /* recursive */));
1023 
1024   // It's an error to try to remove a non-empty directory if recursive flag
1025   // is false.
1026   //      parent_dir
1027   //       |       |
1028   //  child_dir  child_file
1029   // Verify deleting parent_dir.
1030   FileSystemURL parent_dir(CreateDirectory("dir"));
1031   FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
1032   FileSystemURL child_file(CreateFile("dir/child_file"));
1033 
1034   EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
1035             Remove(parent_dir, false /* recursive */));
1036   EXPECT_TRUE(change_observer()->HasNoChange());
1037 }
1038 
TEST_F(FileSystemOperationImplTest,TestRemoveSuccess)1039 TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) {
1040   FileSystemURL empty_dir(CreateDirectory("empty_dir"));
1041   EXPECT_TRUE(DirectoryExists("empty_dir"));
1042   EXPECT_EQ(base::File::FILE_OK, Remove(empty_dir, false /* recursive */));
1043   EXPECT_FALSE(DirectoryExists("empty_dir"));
1044 
1045   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
1046   EXPECT_TRUE(change_observer()->HasNoChange());
1047 }
1048 
TEST_F(FileSystemOperationImplTest,TestRemoveSuccessRecursive)1049 TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) {
1050   // Removing a non-empty directory with recursive flag == true should be ok.
1051   //      parent_dir
1052   //       |       |
1053   //  child_dir  child_files
1054   //       |
1055   //  child_files
1056   //
1057   // Verify deleting parent_dir.
1058   FileSystemURL parent_dir(CreateDirectory("dir"));
1059   for (int i = 0; i < 8; ++i)
1060     CreateFile(base::StringPrintf("dir/file-%d", i));
1061   FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
1062   for (int i = 0; i < 8; ++i)
1063     CreateFile(base::StringPrintf("dir/child_dir/file-%d", i));
1064 
1065   EXPECT_EQ(base::File::FILE_OK, Remove(parent_dir, true /* recursive */));
1066   EXPECT_FALSE(DirectoryExists("parent_dir"));
1067 
1068   EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
1069   EXPECT_EQ(16, change_observer()->get_and_reset_remove_file_count());
1070   EXPECT_TRUE(change_observer()->HasNoChange());
1071 }
1072 
TEST_F(FileSystemOperationImplTest,TestTruncate)1073 TEST_F(FileSystemOperationImplTest, TestTruncate) {
1074   FileSystemURL file(CreateFile("file"));
1075   base::FilePath platform_path = PlatformPath("file");
1076 
1077   char test_data[] = "test data";
1078   int data_size = static_cast<int>(sizeof(test_data));
1079   EXPECT_EQ(data_size,
1080             base::WriteFile(platform_path, test_data, data_size));
1081 
1082   // Check that its length is the size of the data written.
1083   EXPECT_EQ(base::File::FILE_OK, GetMetadata(file));
1084   EXPECT_FALSE(info().is_directory);
1085   EXPECT_EQ(data_size, info().size);
1086 
1087   // Extend the file by truncating it.
1088   int length = 17;
1089   EXPECT_EQ(base::File::FILE_OK, Truncate(file, length));
1090 
1091   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
1092   EXPECT_TRUE(change_observer()->HasNoChange());
1093 
1094   // Check that its length is now 17 and that it's all zeroes after the test
1095   // data.
1096   EXPECT_EQ(length, GetFileSize("file"));
1097   char data[100];
1098   EXPECT_EQ(length, base::ReadFile(platform_path, data, length));
1099   for (int i = 0; i < length; ++i) {
1100     if (i < static_cast<int>(sizeof(test_data)))
1101       EXPECT_EQ(test_data[i], data[i]);
1102     else
1103       EXPECT_EQ(0, data[i]);
1104   }
1105 
1106   // Shorten the file by truncating it.
1107   length = 3;
1108   EXPECT_EQ(base::File::FILE_OK, Truncate(file, length));
1109 
1110   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
1111   EXPECT_TRUE(change_observer()->HasNoChange());
1112 
1113   // Check that its length is now 3 and that it contains only bits of test data.
1114   EXPECT_EQ(length, GetFileSize("file"));
1115   EXPECT_EQ(length, base::ReadFile(platform_path, data, length));
1116   for (int i = 0; i < length; ++i)
1117     EXPECT_EQ(test_data[i], data[i]);
1118 
1119   // Truncate is not a 'read' access.  (Here expected access count is 1
1120   // since we made 1 read access for GetMetadata.)
1121   EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
1122 }
1123 
TEST_F(FileSystemOperationImplTest,TestTruncateFailureByQuota)1124 TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) {
1125   FileSystemURL dir(CreateDirectory("dir"));
1126   FileSystemURL file(CreateFile("dir/file"));
1127 
1128   GrantQuotaForCurrentUsage();
1129   AddQuota(10);
1130 
1131   EXPECT_EQ(base::File::FILE_OK, Truncate(file, 10));
1132   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
1133   EXPECT_TRUE(change_observer()->HasNoChange());
1134 
1135   EXPECT_EQ(10, GetFileSize("dir/file"));
1136 
1137   EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, Truncate(file, 11));
1138   EXPECT_TRUE(change_observer()->HasNoChange());
1139 
1140   EXPECT_EQ(10, GetFileSize("dir/file"));
1141 }
1142 
TEST_F(FileSystemOperationImplTest,TestTouchFile)1143 TEST_F(FileSystemOperationImplTest, TestTouchFile) {
1144   FileSystemURL file(CreateFile("file"));
1145   base::FilePath platform_path = PlatformPath("file");
1146 
1147   base::File::Info info;
1148   EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
1149   EXPECT_FALSE(info.is_directory);
1150   EXPECT_EQ(0, info.size);
1151   const base::Time last_modified = info.last_modified;
1152   const base::Time last_accessed = info.last_accessed;
1153 
1154   const base::Time new_modified_time = base::Time::UnixEpoch();
1155   const base::Time new_accessed_time = new_modified_time +
1156       base::TimeDelta::FromHours(77);
1157   ASSERT_NE(last_modified, new_modified_time);
1158   ASSERT_NE(last_accessed, new_accessed_time);
1159 
1160   EXPECT_EQ(base::File::FILE_OK,
1161             TouchFile(file, new_accessed_time, new_modified_time));
1162   EXPECT_TRUE(change_observer()->HasNoChange());
1163 
1164   EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
1165   // We compare as time_t here to lower our resolution, to avoid false
1166   // negatives caused by conversion to the local filesystem's native
1167   // representation and back.
1168   EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT());
1169   EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT());
1170 }
1171 
TEST_F(FileSystemOperationImplTest,TestCreateSnapshotFile)1172 TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) {
1173   FileSystemURL dir(CreateDirectory("dir"));
1174 
1175   // Create a file for the testing.
1176   EXPECT_EQ(base::File::FILE_OK, DirectoryExists(dir));
1177   FileSystemURL file(CreateFile("dir/file"));
1178   EXPECT_EQ(base::File::FILE_OK, FileExists(file));
1179 
1180   // See if we can get a 'snapshot' file info for the file.
1181   // Since FileSystemOperationImpl assumes the file exists in the local
1182   // directory it should just returns the same metadata and platform_path
1183   // as the file itself.
1184   EXPECT_EQ(base::File::FILE_OK, CreateSnapshotFile(file));
1185   EXPECT_FALSE(info().is_directory);
1186   EXPECT_EQ(PlatformPath("dir/file"), path());
1187   EXPECT_TRUE(change_observer()->HasNoChange());
1188 
1189   // The FileSystemOpration implementation does not create a
1190   // shareable file reference.
1191   EXPECT_EQ(NULL, shareable_file_ref());
1192 }
1193 
TEST_F(FileSystemOperationImplTest,TestMoveSuccessSrcDirRecursiveWithQuota)1194 TEST_F(FileSystemOperationImplTest,
1195        TestMoveSuccessSrcDirRecursiveWithQuota) {
1196   FileSystemURL src(CreateDirectory("src"));
1197   int src_path_cost = GetUsage();
1198 
1199   FileSystemURL dest(CreateDirectory("dest"));
1200   FileSystemURL child_file1(CreateFile("src/file1"));
1201   FileSystemURL child_file2(CreateFile("src/file2"));
1202   FileSystemURL child_dir(CreateDirectory("src/dir"));
1203   FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
1204   FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
1205 
1206   int total_path_cost = GetUsage();
1207   EXPECT_EQ(0, GetDataSizeOnDisk());
1208 
1209   EXPECT_EQ(base::File::FILE_OK, Truncate(child_file1, 5000));
1210   EXPECT_EQ(base::File::FILE_OK, Truncate(child_file2, 400));
1211   EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file1, 30));
1212   EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file2, 2));
1213 
1214   const int64 all_file_size = 5000 + 400 + 30 + 2;
1215   EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
1216   EXPECT_EQ(all_file_size + total_path_cost, GetUsage());
1217 
1218   EXPECT_EQ(base::File::FILE_OK,
1219             Move(src, dest, FileSystemOperation::OPTION_NONE));
1220 
1221   EXPECT_FALSE(DirectoryExists("src/dir"));
1222   EXPECT_FALSE(FileExists("src/dir/file2"));
1223   EXPECT_TRUE(DirectoryExists("dest/dir"));
1224   EXPECT_TRUE(FileExists("dest/dir/file2"));
1225 
1226   EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
1227   EXPECT_EQ(all_file_size + total_path_cost - src_path_cost,
1228             GetUsage());
1229 }
1230 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcDirRecursiveWithQuota)1231 TEST_F(FileSystemOperationImplTest,
1232        TestCopySuccessSrcDirRecursiveWithQuota) {
1233   FileSystemURL src(CreateDirectory("src"));
1234   FileSystemURL dest1(CreateDirectory("dest1"));
1235   FileSystemURL dest2(CreateDirectory("dest2"));
1236 
1237   int64 usage = GetUsage();
1238   FileSystemURL child_file1(CreateFile("src/file1"));
1239   FileSystemURL child_file2(CreateFile("src/file2"));
1240   FileSystemURL child_dir(CreateDirectory("src/dir"));
1241   int64 child_path_cost = GetUsage() - usage;
1242   usage += child_path_cost;
1243 
1244   FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
1245   FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
1246   int64 total_path_cost = GetUsage();
1247   int64 grandchild_path_cost = total_path_cost - usage;
1248 
1249   EXPECT_EQ(0, GetDataSizeOnDisk());
1250 
1251   EXPECT_EQ(base::File::FILE_OK, Truncate(child_file1, 8000));
1252   EXPECT_EQ(base::File::FILE_OK, Truncate(child_file2, 700));
1253   EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file1, 60));
1254   EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file2, 5));
1255 
1256   const int64 child_file_size = 8000 + 700;
1257   const int64 grandchild_file_size = 60 + 5;
1258   const int64 all_file_size = child_file_size + grandchild_file_size;
1259   int64 expected_usage = all_file_size + total_path_cost;
1260 
1261   usage = GetUsage();
1262   EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
1263   EXPECT_EQ(expected_usage, usage);
1264 
1265   EXPECT_EQ(base::File::FILE_OK,
1266             Copy(src, dest1, FileSystemOperation::OPTION_NONE));
1267 
1268   expected_usage += all_file_size + child_path_cost + grandchild_path_cost;
1269   EXPECT_TRUE(DirectoryExists("src/dir"));
1270   EXPECT_TRUE(FileExists("src/dir/file2"));
1271   EXPECT_TRUE(DirectoryExists("dest1/dir"));
1272   EXPECT_TRUE(FileExists("dest1/dir/file2"));
1273 
1274   EXPECT_EQ(2 * all_file_size, GetDataSizeOnDisk());
1275   EXPECT_EQ(expected_usage, GetUsage());
1276 
1277   EXPECT_EQ(base::File::FILE_OK,
1278             Copy(child_dir, dest2, FileSystemOperation::OPTION_NONE));
1279 
1280   expected_usage += grandchild_file_size + grandchild_path_cost;
1281   usage = GetUsage();
1282   EXPECT_EQ(2 * child_file_size + 3 * grandchild_file_size,
1283             GetDataSizeOnDisk());
1284   EXPECT_EQ(expected_usage, usage);
1285 }
1286 
TEST_F(FileSystemOperationImplTest,TestCopySuccessSrcFileWithDifferentFileSize)1287 TEST_F(FileSystemOperationImplTest,
1288        TestCopySuccessSrcFileWithDifferentFileSize) {
1289   FileSystemURL src_file(CreateFile("src"));
1290   FileSystemURL dest_file(CreateFile("dest"));
1291 
1292   EXPECT_EQ(base::File::FILE_OK, Truncate(dest_file, 6));
1293   EXPECT_EQ(base::File::FILE_OK,
1294             Copy(src_file, dest_file, FileSystemOperation::OPTION_NONE));
1295   EXPECT_EQ(0, GetFileSize("dest"));
1296 }
1297 
1298 }  // namespace content
1299