Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc

Issue 2368913003: Populate storage_unittests target. (Closed)
Patch Set: Removed unnecessary include from storage/browser/blob/blob_storage_context_unittest.cc. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 <stddef.h>
6 #include <stdint.h>
7 #include <map>
8 #include <queue>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/location.h"
15 #include "base/macros.h"
16 #include "base/run_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/stl_util.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "content/browser/quota/mock_quota_manager.h"
21 #include "content/browser/quota/mock_quota_manager_proxy.h"
22 #include "content/public/test/async_file_test_helper.h"
23 #include "content/public/test/test_file_system_backend.h"
24 #include "content/public/test/test_file_system_context.h"
25 #include "content/test/fileapi_test_file_set.h"
26 #include "storage/browser/fileapi/copy_or_move_file_validator.h"
27 #include "storage/browser/fileapi/copy_or_move_operation_delegate.h"
28 #include "storage/browser/fileapi/file_stream_reader.h"
29 #include "storage/browser/fileapi/file_stream_writer.h"
30 #include "storage/browser/fileapi/file_system_backend.h"
31 #include "storage/browser/fileapi/file_system_context.h"
32 #include "storage/browser/fileapi/file_system_operation.h"
33 #include "storage/browser/fileapi/file_system_url.h"
34 #include "storage/browser/quota/quota_manager.h"
35 #include "storage/common/fileapi/file_system_mount_option.h"
36 #include "storage/common/fileapi/file_system_util.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 using content::AsyncFileTestHelper;
40 using storage::CopyOrMoveOperationDelegate;
41 using storage::FileStreamWriter;
42 using storage::FileSystemOperation;
43 using storage::FileSystemURL;
44
45 namespace content {
46
47 typedef storage::FileSystemOperation::FileEntryList FileEntryList;
48
49 namespace {
50
51 void ExpectOk(const GURL& origin_url,
52 const std::string& name,
53 base::File::Error error) {
54 ASSERT_EQ(base::File::FILE_OK, error);
55 }
56
57 class TestValidatorFactory : public storage::CopyOrMoveFileValidatorFactory {
58 public:
59 // A factory that creates validators that accept everything or nothing.
60 TestValidatorFactory() {}
61 ~TestValidatorFactory() override {}
62
63 storage::CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
64 const FileSystemURL& /*src_url*/,
65 const base::FilePath& /*platform_path*/) override {
66 // Move arg management to TestValidator?
67 return new TestValidator(true, true, std::string("2"));
68 }
69
70 private:
71 class TestValidator : public storage::CopyOrMoveFileValidator {
72 public:
73 explicit TestValidator(bool pre_copy_valid,
74 bool post_copy_valid,
75 const std::string& reject_string)
76 : result_(pre_copy_valid ? base::File::FILE_OK :
77 base::File::FILE_ERROR_SECURITY),
78 write_result_(post_copy_valid ? base::File::FILE_OK :
79 base::File::FILE_ERROR_SECURITY),
80 reject_string_(reject_string) {
81 }
82 ~TestValidator() override {}
83
84 void StartPreWriteValidation(
85 const ResultCallback& result_callback) override {
86 // Post the result since a real validator must do work asynchronously.
87 base::ThreadTaskRunnerHandle::Get()->PostTask(
88 FROM_HERE, base::Bind(result_callback, result_));
89 }
90
91 void StartPostWriteValidation(
92 const base::FilePath& dest_platform_path,
93 const ResultCallback& result_callback) override {
94 base::File::Error result = write_result_;
95 std::string unsafe = dest_platform_path.BaseName().AsUTF8Unsafe();
96 if (unsafe.find(reject_string_) != std::string::npos) {
97 result = base::File::FILE_ERROR_SECURITY;
98 }
99 // Post the result since a real validator must do work asynchronously.
100 base::ThreadTaskRunnerHandle::Get()->PostTask(
101 FROM_HERE, base::Bind(result_callback, result));
102 }
103
104 private:
105 base::File::Error result_;
106 base::File::Error write_result_;
107 std::string reject_string_;
108
109 DISALLOW_COPY_AND_ASSIGN(TestValidator);
110 };
111 };
112
113 // Records CopyProgressCallback invocations.
114 struct ProgressRecord {
115 storage::FileSystemOperation::CopyProgressType type;
116 FileSystemURL source_url;
117 FileSystemURL dest_url;
118 int64_t size;
119 };
120
121 void RecordProgressCallback(std::vector<ProgressRecord>* records,
122 storage::FileSystemOperation::CopyProgressType type,
123 const FileSystemURL& source_url,
124 const FileSystemURL& dest_url,
125 int64_t size) {
126 ProgressRecord record;
127 record.type = type;
128 record.source_url = source_url;
129 record.dest_url = dest_url;
130 record.size = size;
131 records->push_back(record);
132 }
133
134 void RecordFileProgressCallback(std::vector<int64_t>* records,
135 int64_t progress) {
136 records->push_back(progress);
137 }
138
139 void AssignAndQuit(base::RunLoop* run_loop,
140 base::File::Error* result_out,
141 base::File::Error result) {
142 *result_out = result;
143 run_loop->Quit();
144 }
145
146 class ScopedThreadStopper {
147 public:
148 ScopedThreadStopper(base::Thread* thread) : thread_(thread) {
149 }
150
151 ~ScopedThreadStopper() {
152 if (thread_) {
153 // Give another chance for deleted streams to perform Close.
154 base::RunLoop run_loop;
155 thread_->task_runner()->PostTaskAndReply(
156 FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure());
157 run_loop.Run();
158 thread_->Stop();
159 }
160 }
161
162 bool is_valid() const { return thread_; }
163
164 private:
165 base::Thread* thread_;
166 DISALLOW_COPY_AND_ASSIGN(ScopedThreadStopper);
167 };
168
169 } // namespace
170
171 class CopyOrMoveOperationTestHelper {
172 public:
173 CopyOrMoveOperationTestHelper(const GURL& origin,
174 storage::FileSystemType src_type,
175 storage::FileSystemType dest_type)
176 : origin_(origin), src_type_(src_type), dest_type_(dest_type) {}
177
178 ~CopyOrMoveOperationTestHelper() {
179 file_system_context_ = NULL;
180 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
181 quota_manager_ = NULL;
182 quota_manager_proxy_ = NULL;
183 base::RunLoop().RunUntilIdle();
184 }
185
186 void SetUp() {
187 SetUp(true, true);
188 }
189
190 void SetUpNoValidator() {
191 SetUp(true, false);
192 }
193
194 void SetUp(bool require_copy_or_move_validator,
195 bool init_copy_or_move_validator) {
196 ASSERT_TRUE(base_.CreateUniqueTempDir());
197 base::FilePath base_dir = base_.GetPath();
198 quota_manager_ =
199 new MockQuotaManager(false /* is_incognito */, base_dir,
200 base::ThreadTaskRunnerHandle::Get().get(),
201 base::ThreadTaskRunnerHandle::Get().get(),
202 NULL /* special storage policy */);
203 quota_manager_proxy_ = new MockQuotaManagerProxy(
204 quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
205 file_system_context_ =
206 CreateFileSystemContextForTesting(quota_manager_proxy_.get(), base_dir);
207
208 // Prepare the origin's root directory.
209 storage::FileSystemBackend* backend =
210 file_system_context_->GetFileSystemBackend(src_type_);
211 backend->ResolveURL(
212 FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()),
213 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
214 base::Bind(&ExpectOk));
215 backend = file_system_context_->GetFileSystemBackend(dest_type_);
216 if (dest_type_ == storage::kFileSystemTypeTest) {
217 TestFileSystemBackend* test_backend =
218 static_cast<TestFileSystemBackend*>(backend);
219 std::unique_ptr<storage::CopyOrMoveFileValidatorFactory> factory(
220 new TestValidatorFactory);
221 test_backend->set_require_copy_or_move_validator(
222 require_copy_or_move_validator);
223 if (init_copy_or_move_validator)
224 test_backend->InitializeCopyOrMoveFileValidatorFactory(
225 std::move(factory));
226 }
227 backend->ResolveURL(
228 FileSystemURL::CreateForTest(origin_, dest_type_, base::FilePath()),
229 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
230 base::Bind(&ExpectOk));
231 base::RunLoop().RunUntilIdle();
232
233 // Grant relatively big quota initially.
234 quota_manager_->SetQuota(
235 origin_,
236 storage::FileSystemTypeToQuotaStorageType(src_type_),
237 1024 * 1024);
238 quota_manager_->SetQuota(
239 origin_,
240 storage::FileSystemTypeToQuotaStorageType(dest_type_),
241 1024 * 1024);
242 }
243
244 int64_t GetSourceUsage() {
245 int64_t usage = 0;
246 GetUsageAndQuota(src_type_, &usage, NULL);
247 return usage;
248 }
249
250 int64_t GetDestUsage() {
251 int64_t usage = 0;
252 GetUsageAndQuota(dest_type_, &usage, NULL);
253 return usage;
254 }
255
256 FileSystemURL SourceURL(const std::string& path) {
257 return file_system_context_->CreateCrackedFileSystemURL(
258 origin_, src_type_, base::FilePath::FromUTF8Unsafe(path));
259 }
260
261 FileSystemURL DestURL(const std::string& path) {
262 return file_system_context_->CreateCrackedFileSystemURL(
263 origin_, dest_type_, base::FilePath::FromUTF8Unsafe(path));
264 }
265
266 base::File::Error Copy(const FileSystemURL& src,
267 const FileSystemURL& dest) {
268 return AsyncFileTestHelper::Copy(file_system_context_.get(), src, dest);
269 }
270
271 base::File::Error CopyWithProgress(
272 const FileSystemURL& src,
273 const FileSystemURL& dest,
274 const AsyncFileTestHelper::CopyProgressCallback& progress_callback) {
275 return AsyncFileTestHelper::CopyWithProgress(
276 file_system_context_.get(), src, dest, progress_callback);
277 }
278
279 base::File::Error Move(const FileSystemURL& src,
280 const FileSystemURL& dest) {
281 return AsyncFileTestHelper::Move(file_system_context_.get(), src, dest);
282 }
283
284 base::File::Error SetUpTestCaseFiles(
285 const FileSystemURL& root,
286 const FileSystemTestCaseRecord* const test_cases,
287 size_t test_case_size) {
288 base::File::Error result = base::File::FILE_ERROR_FAILED;
289 for (size_t i = 0; i < test_case_size; ++i) {
290 const FileSystemTestCaseRecord& test_case = test_cases[i];
291 FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
292 root.origin(),
293 root.mount_type(),
294 root.virtual_path().Append(test_case.path));
295 if (test_case.is_directory)
296 result = CreateDirectory(url);
297 else
298 result = CreateFile(url, test_case.data_file_size);
299 EXPECT_EQ(base::File::FILE_OK, result) << url.DebugString();
300 if (result != base::File::FILE_OK)
301 return result;
302 }
303 return result;
304 }
305
306 void VerifyTestCaseFiles(
307 const FileSystemURL& root,
308 const FileSystemTestCaseRecord* const test_cases,
309 size_t test_case_size) {
310 std::map<base::FilePath, const FileSystemTestCaseRecord*> test_case_map;
311 for (size_t i = 0; i < test_case_size; ++i) {
312 test_case_map[
313 base::FilePath(test_cases[i].path).NormalizePathSeparators()] =
314 &test_cases[i];
315 }
316
317 std::queue<FileSystemURL> directories;
318 FileEntryList entries;
319 directories.push(root);
320 while (!directories.empty()) {
321 FileSystemURL dir = directories.front();
322 directories.pop();
323 ASSERT_EQ(base::File::FILE_OK, ReadDirectory(dir, &entries));
324 for (size_t i = 0; i < entries.size(); ++i) {
325 FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
326 dir.origin(),
327 dir.mount_type(),
328 dir.virtual_path().Append(entries[i].name));
329 base::FilePath relative;
330 root.virtual_path().AppendRelativePath(url.virtual_path(), &relative);
331 relative = relative.NormalizePathSeparators();
332 ASSERT_TRUE(base::ContainsKey(test_case_map, relative));
333 if (entries[i].is_directory) {
334 EXPECT_TRUE(test_case_map[relative]->is_directory);
335 directories.push(url);
336 } else {
337 EXPECT_FALSE(test_case_map[relative]->is_directory);
338 EXPECT_TRUE(FileExists(url, test_case_map[relative]->data_file_size));
339 }
340 test_case_map.erase(relative);
341 }
342 }
343 EXPECT_TRUE(test_case_map.empty());
344 std::map<base::FilePath,
345 const FileSystemTestCaseRecord*>::const_iterator it;
346 for (it = test_case_map.begin(); it != test_case_map.end(); ++it) {
347 LOG(ERROR) << "Extra entry: " << it->first.LossyDisplayName();
348 }
349 }
350
351 base::File::Error ReadDirectory(const FileSystemURL& url,
352 FileEntryList* entries) {
353 return AsyncFileTestHelper::ReadDirectory(
354 file_system_context_.get(), url, entries);
355 }
356
357 base::File::Error CreateDirectory(const FileSystemURL& url) {
358 return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
359 url);
360 }
361
362 base::File::Error CreateFile(const FileSystemURL& url, size_t size) {
363 base::File::Error result =
364 AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
365 if (result != base::File::FILE_OK)
366 return result;
367 return AsyncFileTestHelper::TruncateFile(
368 file_system_context_.get(), url, size);
369 }
370
371 bool FileExists(const FileSystemURL& url, int64_t expected_size) {
372 return AsyncFileTestHelper::FileExists(
373 file_system_context_.get(), url, expected_size);
374 }
375
376 bool DirectoryExists(const FileSystemURL& url) {
377 return AsyncFileTestHelper::DirectoryExists(file_system_context_.get(),
378 url);
379 }
380
381 private:
382 void GetUsageAndQuota(storage::FileSystemType type,
383 int64_t* usage,
384 int64_t* quota) {
385 storage::QuotaStatusCode status = AsyncFileTestHelper::GetUsageAndQuota(
386 quota_manager_.get(), origin_, type, usage, quota);
387 ASSERT_EQ(storage::kQuotaStatusOk, status);
388 }
389
390 private:
391 base::ScopedTempDir base_;
392
393 const GURL origin_;
394 const storage::FileSystemType src_type_;
395 const storage::FileSystemType dest_type_;
396
397 base::MessageLoopForIO message_loop_;
398 scoped_refptr<storage::FileSystemContext> file_system_context_;
399 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
400 scoped_refptr<MockQuotaManager> quota_manager_;
401
402 DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationTestHelper);
403 };
404
405 TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFile) {
406 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
407 storage::kFileSystemTypeTemporary,
408 storage::kFileSystemTypePersistent);
409 helper.SetUp();
410
411 FileSystemURL src = helper.SourceURL("a");
412 FileSystemURL dest = helper.DestURL("b");
413 int64_t src_initial_usage = helper.GetSourceUsage();
414 int64_t dest_initial_usage = helper.GetDestUsage();
415
416 // Set up a source file.
417 ASSERT_EQ(base::File::FILE_OK, helper.CreateFile(src, 10));
418 int64_t src_increase = helper.GetSourceUsage() - src_initial_usage;
419
420 // Copy it.
421 ASSERT_EQ(base::File::FILE_OK, helper.Copy(src, dest));
422
423 // Verify.
424 ASSERT_TRUE(helper.FileExists(src, 10));
425 ASSERT_TRUE(helper.FileExists(dest, 10));
426
427 int64_t src_new_usage = helper.GetSourceUsage();
428 ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
429
430 int64_t dest_increase = helper.GetDestUsage() - dest_initial_usage;
431 ASSERT_EQ(src_increase, dest_increase);
432 }
433
434 TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleFile) {
435 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
436 storage::kFileSystemTypeTemporary,
437 storage::kFileSystemTypePersistent);
438 helper.SetUp();
439
440 FileSystemURL src = helper.SourceURL("a");
441 FileSystemURL dest = helper.DestURL("b");
442 int64_t src_initial_usage = helper.GetSourceUsage();
443 int64_t dest_initial_usage = helper.GetDestUsage();
444
445 // Set up a source file.
446 ASSERT_EQ(base::File::FILE_OK, helper.CreateFile(src, 10));
447 int64_t src_increase = helper.GetSourceUsage() - src_initial_usage;
448
449 // Move it.
450 ASSERT_EQ(base::File::FILE_OK, helper.Move(src, dest));
451
452 // Verify.
453 ASSERT_FALSE(helper.FileExists(src, AsyncFileTestHelper::kDontCheckSize));
454 ASSERT_TRUE(helper.FileExists(dest, 10));
455
456 int64_t src_new_usage = helper.GetSourceUsage();
457 ASSERT_EQ(src_initial_usage, src_new_usage);
458
459 int64_t dest_increase = helper.GetDestUsage() - dest_initial_usage;
460 ASSERT_EQ(src_increase, dest_increase);
461 }
462
463 TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleDirectory) {
464 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
465 storage::kFileSystemTypeTemporary,
466 storage::kFileSystemTypePersistent);
467 helper.SetUp();
468
469 FileSystemURL src = helper.SourceURL("a");
470 FileSystemURL dest = helper.DestURL("b");
471 int64_t src_initial_usage = helper.GetSourceUsage();
472 int64_t dest_initial_usage = helper.GetDestUsage();
473
474 // Set up a source directory.
475 ASSERT_EQ(base::File::FILE_OK, helper.CreateDirectory(src));
476 int64_t src_increase = helper.GetSourceUsage() - src_initial_usage;
477
478 // Copy it.
479 ASSERT_EQ(base::File::FILE_OK, helper.Copy(src, dest));
480
481 // Verify.
482 ASSERT_TRUE(helper.DirectoryExists(src));
483 ASSERT_TRUE(helper.DirectoryExists(dest));
484
485 int64_t src_new_usage = helper.GetSourceUsage();
486 ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
487
488 int64_t dest_increase = helper.GetDestUsage() - dest_initial_usage;
489 ASSERT_EQ(src_increase, dest_increase);
490 }
491
492 TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleDirectory) {
493 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
494 storage::kFileSystemTypeTemporary,
495 storage::kFileSystemTypePersistent);
496 helper.SetUp();
497
498 FileSystemURL src = helper.SourceURL("a");
499 FileSystemURL dest = helper.DestURL("b");
500 int64_t src_initial_usage = helper.GetSourceUsage();
501 int64_t dest_initial_usage = helper.GetDestUsage();
502
503 // Set up a source directory.
504 ASSERT_EQ(base::File::FILE_OK, helper.CreateDirectory(src));
505 int64_t src_increase = helper.GetSourceUsage() - src_initial_usage;
506
507 // Move it.
508 ASSERT_EQ(base::File::FILE_OK, helper.Move(src, dest));
509
510 // Verify.
511 ASSERT_FALSE(helper.DirectoryExists(src));
512 ASSERT_TRUE(helper.DirectoryExists(dest));
513
514 int64_t src_new_usage = helper.GetSourceUsage();
515 ASSERT_EQ(src_initial_usage, src_new_usage);
516
517 int64_t dest_increase = helper.GetDestUsage() - dest_initial_usage;
518 ASSERT_EQ(src_increase, dest_increase);
519 }
520
521 TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) {
522 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
523 storage::kFileSystemTypeTemporary,
524 storage::kFileSystemTypePersistent);
525 helper.SetUp();
526
527 FileSystemURL src = helper.SourceURL("a");
528 FileSystemURL dest = helper.DestURL("b");
529 int64_t src_initial_usage = helper.GetSourceUsage();
530 int64_t dest_initial_usage = helper.GetDestUsage();
531
532 // Set up a source directory.
533 ASSERT_EQ(base::File::FILE_OK, helper.CreateDirectory(src));
534 ASSERT_EQ(base::File::FILE_OK,
535 helper.SetUpTestCaseFiles(src,
536 kRegularFileSystemTestCases,
537 kRegularFileSystemTestCaseSize));
538 int64_t src_increase = helper.GetSourceUsage() - src_initial_usage;
539
540 // Copy it.
541 ASSERT_EQ(base::File::FILE_OK,
542 helper.CopyWithProgress(
543 src, dest,
544 AsyncFileTestHelper::CopyProgressCallback()));
545
546 // Verify.
547 ASSERT_TRUE(helper.DirectoryExists(src));
548 ASSERT_TRUE(helper.DirectoryExists(dest));
549
550 helper.VerifyTestCaseFiles(dest,
551 kRegularFileSystemTestCases,
552 kRegularFileSystemTestCaseSize);
553
554 int64_t src_new_usage = helper.GetSourceUsage();
555 ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
556
557 int64_t dest_increase = helper.GetDestUsage() - dest_initial_usage;
558 ASSERT_EQ(src_increase, dest_increase);
559 }
560
561 TEST(LocalFileSystemCopyOrMoveOperationTest, MoveDirectory) {
562 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
563 storage::kFileSystemTypeTemporary,
564 storage::kFileSystemTypePersistent);
565 helper.SetUp();
566
567 FileSystemURL src = helper.SourceURL("a");
568 FileSystemURL dest = helper.DestURL("b");
569 int64_t src_initial_usage = helper.GetSourceUsage();
570 int64_t dest_initial_usage = helper.GetDestUsage();
571
572 // Set up a source directory.
573 ASSERT_EQ(base::File::FILE_OK, helper.CreateDirectory(src));
574 ASSERT_EQ(base::File::FILE_OK,
575 helper.SetUpTestCaseFiles(src,
576 kRegularFileSystemTestCases,
577 kRegularFileSystemTestCaseSize));
578 int64_t src_increase = helper.GetSourceUsage() - src_initial_usage;
579
580 // Move it.
581 ASSERT_EQ(base::File::FILE_OK, helper.Move(src, dest));
582
583 // Verify.
584 ASSERT_FALSE(helper.DirectoryExists(src));
585 ASSERT_TRUE(helper.DirectoryExists(dest));
586
587 helper.VerifyTestCaseFiles(dest,
588 kRegularFileSystemTestCases,
589 kRegularFileSystemTestCaseSize);
590
591 int64_t src_new_usage = helper.GetSourceUsage();
592 ASSERT_EQ(src_initial_usage, src_new_usage);
593
594 int64_t dest_increase = helper.GetDestUsage() - dest_initial_usage;
595 ASSERT_EQ(src_increase, dest_increase);
596 }
597
598 TEST(LocalFileSystemCopyOrMoveOperationTest,
599 MoveDirectoryFailPostWriteValidation) {
600 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
601 storage::kFileSystemTypeTemporary,
602 storage::kFileSystemTypeTest);
603 helper.SetUp();
604
605 FileSystemURL src = helper.SourceURL("a");
606 FileSystemURL dest = helper.DestURL("b");
607
608 // Set up a source directory.
609 ASSERT_EQ(base::File::FILE_OK, helper.CreateDirectory(src));
610 ASSERT_EQ(base::File::FILE_OK,
611 helper.SetUpTestCaseFiles(src,
612 kRegularFileSystemTestCases,
613 kRegularFileSystemTestCaseSize));
614
615 // Move it.
616 helper.Move(src, dest);
617
618 // Verify.
619 ASSERT_TRUE(helper.DirectoryExists(src));
620 ASSERT_TRUE(helper.DirectoryExists(dest));
621
622 // In the move operation, [file 0, file 2, file 3] are processed as LIFO.
623 // After file 3 is processed, file 2 is rejected by the validator and the
624 // operation fails. That is, only file 3 should be in dest.
625 FileSystemTestCaseRecord kMoveDirResultCases[] = {
626 {false, FILE_PATH_LITERAL("file 3"), 0},
627 };
628
629 helper.VerifyTestCaseFiles(dest,
630 kMoveDirResultCases,
631 arraysize(kMoveDirResultCases));
632 }
633
634 TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) {
635 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
636 storage::kFileSystemTypeTemporary,
637 storage::kFileSystemTypeTest);
638 helper.SetUpNoValidator();
639
640 FileSystemURL src = helper.SourceURL("a");
641 FileSystemURL dest = helper.DestURL("b");
642
643 // Set up a source file.
644 ASSERT_EQ(base::File::FILE_OK, helper.CreateFile(src, 10));
645
646 // The copy attempt should fail with a security error -- getting
647 // the factory returns a security error, and the copy operation must
648 // respect that.
649 ASSERT_EQ(base::File::FILE_ERROR_SECURITY, helper.Copy(src, dest));
650 }
651
652 TEST(LocalFileSystemCopyOrMoveOperationTest, ProgressCallback) {
653 CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
654 storage::kFileSystemTypeTemporary,
655 storage::kFileSystemTypePersistent);
656 helper.SetUp();
657
658 FileSystemURL src = helper.SourceURL("a");
659 FileSystemURL dest = helper.DestURL("b");
660
661 // Set up a source directory.
662 ASSERT_EQ(base::File::FILE_OK, helper.CreateDirectory(src));
663 ASSERT_EQ(base::File::FILE_OK,
664 helper.SetUpTestCaseFiles(src,
665 kRegularFileSystemTestCases,
666 kRegularFileSystemTestCaseSize));
667
668 std::vector<ProgressRecord> records;
669 ASSERT_EQ(base::File::FILE_OK,
670 helper.CopyWithProgress(src, dest,
671 base::Bind(&RecordProgressCallback,
672 base::Unretained(&records))));
673
674 // Verify progress callback.
675 for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
676 const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
677
678 FileSystemURL src_url = helper.SourceURL(
679 std::string("a/") + base::FilePath(test_case.path).AsUTF8Unsafe());
680 FileSystemURL dest_url = helper.DestURL(
681 std::string("b/") + base::FilePath(test_case.path).AsUTF8Unsafe());
682
683 // Find the first and last progress record.
684 size_t begin_index = records.size();
685 size_t end_index = records.size();
686 for (size_t j = 0; j < records.size(); ++j) {
687 if (records[j].source_url == src_url) {
688 if (begin_index == records.size())
689 begin_index = j;
690 end_index = j;
691 }
692 }
693
694 // The record should be found.
695 ASSERT_NE(begin_index, records.size());
696 ASSERT_NE(end_index, records.size());
697 ASSERT_NE(begin_index, end_index);
698
699 EXPECT_EQ(FileSystemOperation::BEGIN_COPY_ENTRY,
700 records[begin_index].type);
701 EXPECT_FALSE(records[begin_index].dest_url.is_valid());
702 EXPECT_EQ(FileSystemOperation::END_COPY_ENTRY, records[end_index].type);
703 EXPECT_EQ(dest_url, records[end_index].dest_url);
704
705 if (test_case.is_directory) {
706 // For directory copy, the progress shouldn't be interlaced.
707 EXPECT_EQ(begin_index + 1, end_index);
708 } else {
709 // PROGRESS event's size should be assending order.
710 int64_t current_size = 0;
711 for (size_t j = begin_index + 1; j < end_index; ++j) {
712 if (records[j].source_url == src_url) {
713 EXPECT_EQ(FileSystemOperation::PROGRESS, records[j].type);
714 EXPECT_FALSE(records[j].dest_url.is_valid());
715 EXPECT_GE(records[j].size, current_size);
716 current_size = records[j].size;
717 }
718 }
719 }
720 }
721 }
722
723 TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelper) {
724 base::ScopedTempDir temp_dir;
725 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
726 base::FilePath source_path = temp_dir.GetPath().AppendASCII("source");
727 base::FilePath dest_path = temp_dir.GetPath().AppendASCII("dest");
728 const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
729 base::WriteFile(source_path, kTestData,
730 arraysize(kTestData) - 1); // Exclude trailing '\0'.
731
732 base::MessageLoopForIO message_loop;
733 base::Thread file_thread("file_thread");
734 ASSERT_TRUE(file_thread.Start());
735 ScopedThreadStopper thread_stopper(&file_thread);
736 ASSERT_TRUE(thread_stopper.is_valid());
737
738 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
739 file_thread.task_runner();
740
741 std::unique_ptr<storage::FileStreamReader> reader(
742 storage::FileStreamReader::CreateForLocalFile(
743 task_runner.get(), source_path, 0, base::Time()));
744
745 std::unique_ptr<FileStreamWriter> writer(FileStreamWriter::CreateForLocalFile(
746 task_runner.get(), dest_path, 0, FileStreamWriter::CREATE_NEW_FILE));
747
748 std::vector<int64_t> progress;
749 CopyOrMoveOperationDelegate::StreamCopyHelper helper(
750 std::move(reader), std::move(writer),
751 storage::FlushPolicy::NO_FLUSH_ON_COMPLETION,
752 10, // buffer size
753 base::Bind(&RecordFileProgressCallback, base::Unretained(&progress)),
754 base::TimeDelta()); // For testing, we need all the progress.
755
756 base::File::Error error = base::File::FILE_ERROR_FAILED;
757 base::RunLoop run_loop;
758 helper.Run(base::Bind(&AssignAndQuit, &run_loop, &error));
759 run_loop.Run();
760
761 EXPECT_EQ(base::File::FILE_OK, error);
762 ASSERT_EQ(5U, progress.size());
763 EXPECT_EQ(0, progress[0]);
764 EXPECT_EQ(10, progress[1]);
765 EXPECT_EQ(20, progress[2]);
766 EXPECT_EQ(30, progress[3]);
767 EXPECT_EQ(36, progress[4]);
768
769 std::string content;
770 ASSERT_TRUE(base::ReadFileToString(dest_path, &content));
771 EXPECT_EQ(kTestData, content);
772 }
773
774 TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelperWithFlush) {
775 // Testing the same configuration as StreamCopyHelper, but with |need_flush|
776 // parameter set to true. Since it is hard to test that the flush is indeed
777 // taking place, this test just only verifies that the file is correctly
778 // written with or without the flag.
779 base::ScopedTempDir temp_dir;
780 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
781 base::FilePath source_path = temp_dir.GetPath().AppendASCII("source");
782 base::FilePath dest_path = temp_dir.GetPath().AppendASCII("dest");
783 const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
784 base::WriteFile(source_path, kTestData,
785 arraysize(kTestData) - 1); // Exclude trailing '\0'.
786
787
788 base::MessageLoopForIO message_loop;
789 base::Thread file_thread("file_thread");
790 ASSERT_TRUE(file_thread.Start());
791 ScopedThreadStopper thread_stopper(&file_thread);
792 ASSERT_TRUE(thread_stopper.is_valid());
793
794 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
795 file_thread.task_runner();
796
797 std::unique_ptr<storage::FileStreamReader> reader(
798 storage::FileStreamReader::CreateForLocalFile(
799 task_runner.get(), source_path, 0, base::Time()));
800
801 std::unique_ptr<FileStreamWriter> writer(FileStreamWriter::CreateForLocalFile(
802 task_runner.get(), dest_path, 0, FileStreamWriter::CREATE_NEW_FILE));
803
804 std::vector<int64_t> progress;
805 CopyOrMoveOperationDelegate::StreamCopyHelper helper(
806 std::move(reader), std::move(writer),
807 storage::FlushPolicy::NO_FLUSH_ON_COMPLETION,
808 10, // buffer size
809 base::Bind(&RecordFileProgressCallback, base::Unretained(&progress)),
810 base::TimeDelta()); // For testing, we need all the progress.
811
812 base::File::Error error = base::File::FILE_ERROR_FAILED;
813 base::RunLoop run_loop;
814 helper.Run(base::Bind(&AssignAndQuit, &run_loop, &error));
815 run_loop.Run();
816
817 EXPECT_EQ(base::File::FILE_OK, error);
818 ASSERT_EQ(5U, progress.size());
819 EXPECT_EQ(0, progress[0]);
820 EXPECT_EQ(10, progress[1]);
821 EXPECT_EQ(20, progress[2]);
822 EXPECT_EQ(30, progress[3]);
823 EXPECT_EQ(36, progress[4]);
824
825 std::string content;
826 ASSERT_TRUE(base::ReadFileToString(dest_path, &content));
827 EXPECT_EQ(kTestData, content);
828 }
829
830 TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelper_Cancel) {
831 base::ScopedTempDir temp_dir;
832 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
833 base::FilePath source_path = temp_dir.GetPath().AppendASCII("source");
834 base::FilePath dest_path = temp_dir.GetPath().AppendASCII("dest");
835 const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
836 base::WriteFile(source_path, kTestData,
837 arraysize(kTestData) - 1); // Exclude trailing '\0'.
838
839 base::MessageLoopForIO message_loop;
840 base::Thread file_thread("file_thread");
841 ASSERT_TRUE(file_thread.Start());
842 ScopedThreadStopper thread_stopper(&file_thread);
843 ASSERT_TRUE(thread_stopper.is_valid());
844
845 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
846 file_thread.task_runner();
847
848 std::unique_ptr<storage::FileStreamReader> reader(
849 storage::FileStreamReader::CreateForLocalFile(
850 task_runner.get(), source_path, 0, base::Time()));
851
852 std::unique_ptr<FileStreamWriter> writer(FileStreamWriter::CreateForLocalFile(
853 task_runner.get(), dest_path, 0, FileStreamWriter::CREATE_NEW_FILE));
854
855 std::vector<int64_t> progress;
856 CopyOrMoveOperationDelegate::StreamCopyHelper helper(
857 std::move(reader), std::move(writer),
858 storage::FlushPolicy::NO_FLUSH_ON_COMPLETION,
859 10, // buffer size
860 base::Bind(&RecordFileProgressCallback, base::Unretained(&progress)),
861 base::TimeDelta()); // For testing, we need all the progress.
862
863 // Call Cancel() later.
864 base::ThreadTaskRunnerHandle::Get()->PostTask(
865 FROM_HERE,
866 base::Bind(&CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel,
867 base::Unretained(&helper)));
868
869 base::File::Error error = base::File::FILE_ERROR_FAILED;
870 base::RunLoop run_loop;
871 helper.Run(base::Bind(&AssignAndQuit, &run_loop, &error));
872 run_loop.Run();
873
874 EXPECT_EQ(base::File::FILE_ERROR_ABORT, error);
875 }
876
877 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/fileapi/copy_or_move_file_validator_unittest.cc ('k') | content/browser/fileapi/dragged_file_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698