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, "a);
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