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
33using content::AsyncFileTestHelper;
34using storage::FileSystemOperation;
35using storage::FileSystemOperationContext;
36using storage::FileSystemOperationRunner;
37using storage::FileSystemURL;
38using storage::QuotaManager;
39using storage::QuotaManagerProxy;
40using storage::ShareableFileReference;
41
42namespace content {
43
44// Test class for FileSystemOperationImpl.
45class FileSystemOperationImplTest
46    : public testing::Test {
47 public:
48  FileSystemOperationImplTest() : weak_factory_(this) {}
49
50 protected:
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
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
81  FileSystemOperationRunner* operation_runner() {
82    return sandbox_file_system_.operation_runner();
83  }
84
85  const base::File::Info& info() const { return info_; }
86  const base::FilePath& path() const { return path_; }
87  const std::vector<storage::DirectoryEntry>& entries() const {
88    return entries_;
89  }
90
91  const ShareableFileReference* shareable_file_ref() const {
92    return shareable_file_ref_.get();
93  }
94
95  MockQuotaManager* quota_manager() {
96    return static_cast<MockQuotaManager*>(quota_manager_.get());
97  }
98
99  MockQuotaManagerProxy* quota_manager_proxy() {
100    return static_cast<MockQuotaManagerProxy*>(
101        quota_manager_proxy_.get());
102  }
103
104  storage::FileSystemFileUtil* file_util() {
105    return sandbox_file_system_.file_util();
106  }
107
108  storage::MockFileChangeObserver* change_observer() {
109    return &change_observer_;
110  }
111
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
120  FileSystemURL URLForPath(const std::string& path) const {
121    return sandbox_file_system_.CreateURLFromUTF8(path);
122  }
123
124  base::FilePath PlatformPath(const std::string& path) {
125    return sandbox_file_system_.GetLocalPath(
126        base::FilePath::FromUTF8Unsafe(path));
127  }
128
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
135  bool DirectoryExists(const std::string& path) {
136    return AsyncFileTestHelper::DirectoryExists(
137        sandbox_file_system_.file_system_context(), URLForPath(path));
138  }
139
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
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
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.
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
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
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
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
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
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
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
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
241  int64 GetDataSizeOnDisk() {
242    return sandbox_file_system_.ComputeCurrentOriginUsage() -
243        sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
244  }
245
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
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
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
280  int64 GetUsage() {
281    int64 usage = 0;
282    GetUsageAndQuota(&usage, NULL);
283    return usage;
284  }
285
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
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
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
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
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
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
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
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
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
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
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
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
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
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
487TEST_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
495TEST_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
504TEST_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
515TEST_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
527TEST_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
538TEST_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
548TEST_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
563TEST_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
576TEST_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
593TEST_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
608TEST_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
627TEST_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
644TEST_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
651TEST_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
660TEST_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
671TEST_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
683TEST_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
693TEST_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
704TEST_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
721TEST_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
735TEST_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
749TEST_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
766TEST_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
779TEST_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
802TEST_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
819TEST_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
850TEST_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
868TEST_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
875TEST_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
885TEST_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
892TEST_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
898TEST_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
906TEST_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
913TEST_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
920TEST_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
933TEST_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
942TEST_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
954TEST_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
978TEST_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
986TEST_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
997TEST_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
1019TEST_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
1039TEST_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
1049TEST_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
1073TEST_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
1124TEST_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
1143TEST_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
1172TEST_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
1194TEST_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
1231TEST_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
1287TEST_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