Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/tests/test_file_ref.h" | 5 #include "ppapi/tests/test_file_ref.h" |
| 6 | 6 |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "ppapi/c/pp_errors.h" | 10 #include "ppapi/c/pp_errors.h" |
| 11 #include "ppapi/c/ppb_file_io.h" | 11 #include "ppapi/c/ppb_file_io.h" |
| 12 #include "ppapi/c/dev/ppb_testing_dev.h" | 12 #include "ppapi/c/dev/ppb_testing_dev.h" |
| 13 #include "ppapi/cpp/dev/directory_entry_dev.h" | 13 #include "ppapi/cpp/directory_entry.h" |
| 14 #include "ppapi/cpp/dev/directory_reader_dev.h" | |
| 15 #include "ppapi/cpp/file_io.h" | 14 #include "ppapi/cpp/file_io.h" |
| 16 #include "ppapi/cpp/file_ref.h" | 15 #include "ppapi/cpp/file_ref.h" |
| 17 #include "ppapi/cpp/file_system.h" | 16 #include "ppapi/cpp/file_system.h" |
| 18 #include "ppapi/cpp/instance.h" | 17 #include "ppapi/cpp/instance.h" |
| 19 #include "ppapi/cpp/module.h" | 18 #include "ppapi/cpp/module.h" |
| 20 #include "ppapi/cpp/url_loader.h" | 19 #include "ppapi/cpp/url_loader.h" |
| 21 #include "ppapi/cpp/url_request_info.h" | 20 #include "ppapi/cpp/url_request_info.h" |
| 22 #include "ppapi/cpp/url_response_info.h" | 21 #include "ppapi/cpp/url_response_info.h" |
| 23 #include "ppapi/tests/test_utils.h" | 22 #include "ppapi/tests/test_utils.h" |
| 24 #include "ppapi/tests/testing_instance.h" | 23 #include "ppapi/tests/testing_instance.h" |
| 25 | 24 |
| 26 REGISTER_TEST_CASE(FileRef); | 25 REGISTER_TEST_CASE(FileRef); |
| 27 | 26 |
| 28 namespace { | 27 namespace { |
| 29 | 28 |
| 30 const char* kPersFileName = "persistent"; | 29 const char* kPersFileName = "persistent"; |
| 31 const char* kTempFileName = "temporary"; | 30 const char* kTempFileName = "temporary"; |
| 32 const char* kParentPath = "/foo/bar"; | 31 const char* kParentPath = "/foo/bar"; |
| 33 const char* kPersFilePath = "/foo/bar/persistent"; | 32 const char* kPersFilePath = "/foo/bar/persistent"; |
| 34 const char* kTempFilePath = "/foo/bar/temporary"; | 33 const char* kTempFilePath = "/foo/bar/temporary"; |
| 35 const char* kTerribleName = "!@#$%^&*()-_=+{}[] ;:'\"|`~\t\n\r\b?"; | 34 const char* kTerribleName = "!@#$%^&*()-_=+{}[] ;:'\"|`~\t\n\r\b?"; |
| 36 | 35 |
| 36 typedef std::vector<pp::DirectoryEntry> DirEntries; | |
| 37 | |
| 37 std::string ReportMismatch(const std::string& method_name, | 38 std::string ReportMismatch(const std::string& method_name, |
| 38 const std::string& returned_result, | 39 const std::string& returned_result, |
| 39 const std::string& expected_result) { | 40 const std::string& expected_result) { |
| 40 return method_name + " returned '" + returned_result + "'; '" + | 41 return method_name + " returned '" + returned_result + "'; '" + |
| 41 expected_result + "' expected."; | 42 expected_result + "' expected."; |
| 42 } | 43 } |
| 43 | 44 |
| 45 std::string IntegerToString(int value) { | |
| 46 char result[12]; | |
| 47 sprintf(result, "%d", value); | |
|
dmichael (off chromium)
2013/05/02 19:43:54
nit: please use snprintf (or just delete this func
hamaji
2013/05/02 20:14:49
Removed
| |
| 48 return result; | |
| 49 } | |
| 50 | |
| 44 } // namespace | 51 } // namespace |
| 45 | 52 |
| 46 bool TestFileRef::Init() { | 53 bool TestFileRef::Init() { |
| 47 return CheckTestingInterface() && EnsureRunningOverHTTP(); | 54 return CheckTestingInterface() && EnsureRunningOverHTTP(); |
| 48 } | 55 } |
| 49 | 56 |
| 50 std::string TestFileRef::MakeExternalFileRef(pp::FileRef* file_ref_ext) { | 57 std::string TestFileRef::MakeExternalFileRef(pp::FileRef* file_ref_ext) { |
| 51 pp::URLRequestInfo request(instance_); | 58 pp::URLRequestInfo request(instance_); |
| 52 request.SetURL("test_url_loader_data/hello.txt"); | 59 request.SetURL("test_url_loader_data/hello.txt"); |
| 53 request.SetStreamToFile(true); | 60 request.SetStreamToFile(true); |
| 54 | 61 |
| 55 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | 62 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); |
| 56 | 63 |
| 57 pp::URLLoader loader(instance_); | 64 pp::URLLoader loader(instance_); |
| 58 callback.WaitForResult(loader.Open(request, callback.GetCallback())); | 65 callback.WaitForResult(loader.Open(request, callback.GetCallback())); |
| 59 CHECK_CALLBACK_BEHAVIOR(callback); | 66 CHECK_CALLBACK_BEHAVIOR(callback); |
| 60 ASSERT_EQ(PP_OK, callback.result()); | 67 ASSERT_EQ(PP_OK, callback.result()); |
| 61 | 68 |
| 62 pp::URLResponseInfo response_info(loader.GetResponseInfo()); | 69 pp::URLResponseInfo response_info(loader.GetResponseInfo()); |
| 63 ASSERT_FALSE(response_info.is_null()); | 70 ASSERT_FALSE(response_info.is_null()); |
| 64 ASSERT_EQ(200, response_info.GetStatusCode()); | 71 ASSERT_EQ(200, response_info.GetStatusCode()); |
| 65 | 72 |
| 66 *file_ref_ext = pp::FileRef(response_info.GetBodyAsFileRef()); | 73 *file_ref_ext = pp::FileRef(response_info.GetBodyAsFileRef()); |
| 67 ASSERT_EQ(PP_FILESYSTEMTYPE_EXTERNAL, file_ref_ext->GetFileSystemType()); | 74 ASSERT_EQ(PP_FILESYSTEMTYPE_EXTERNAL, file_ref_ext->GetFileSystemType()); |
| 68 PASS(); | 75 PASS(); |
| 69 } | 76 } |
| 70 | 77 |
| 78 int32_t TestFileRef::DeleteDirectoryRecursively(pp::FileRef* dir) { | |
| 79 if (!dir) | |
| 80 return PP_ERROR_BADARGUMENT; | |
| 81 | |
| 82 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | |
| 83 TestCompletionCallbackWithOutput<DirEntries> output_callback( | |
| 84 instance_->pp_instance(), callback_type()); | |
| 85 | |
| 86 output_callback.WaitForResult( | |
| 87 dir->ReadEntries(output_callback.GetCallback())); | |
| 88 int32_t rv = output_callback.result(); | |
| 89 if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) | |
| 90 return rv; | |
| 91 | |
| 92 DirEntries entries = output_callback.output(); | |
| 93 for (DirEntries::const_iterator it = entries.begin(); | |
| 94 it != entries.end(); ++it) { | |
|
dmichael (off chromium)
2013/05/02 19:43:54
nit: I prefer each statement in the loop have its
hamaji
2013/05/02 20:14:49
Yeah, I actually have the same preference :) (as y
| |
| 95 pp::FileRef file_ref = it->file_ref(); | |
| 96 if (it->file_type() == PP_FILETYPE_DIRECTORY) { | |
| 97 rv = DeleteDirectoryRecursively(&file_ref); | |
| 98 if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) | |
| 99 return rv; | |
| 100 } else { | |
| 101 callback.WaitForResult(file_ref.Delete(callback.GetCallback())); | |
| 102 rv = callback.result(); | |
| 103 if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) | |
| 104 return rv; | |
| 105 } | |
| 106 } | |
| 107 callback.WaitForResult(dir->Delete(callback.GetCallback())); | |
| 108 return callback.result(); | |
| 109 } | |
| 110 | |
| 71 void TestFileRef::RunTests(const std::string& filter) { | 111 void TestFileRef::RunTests(const std::string& filter) { |
| 72 RUN_CALLBACK_TEST(TestFileRef, Create, filter); | 112 RUN_CALLBACK_TEST(TestFileRef, Create, filter); |
| 73 RUN_CALLBACK_TEST(TestFileRef, GetFileSystemType, filter); | 113 RUN_CALLBACK_TEST(TestFileRef, GetFileSystemType, filter); |
| 74 RUN_CALLBACK_TEST(TestFileRef, GetName, filter); | 114 RUN_CALLBACK_TEST(TestFileRef, GetName, filter); |
| 75 RUN_CALLBACK_TEST(TestFileRef, GetPath, filter); | 115 RUN_CALLBACK_TEST(TestFileRef, GetPath, filter); |
| 76 RUN_CALLBACK_TEST(TestFileRef, GetParent, filter); | 116 RUN_CALLBACK_TEST(TestFileRef, GetParent, filter); |
| 77 RUN_CALLBACK_TEST(TestFileRef, MakeDirectory, filter); | 117 RUN_CALLBACK_TEST(TestFileRef, MakeDirectory, filter); |
| 78 RUN_CALLBACK_TEST(TestFileRef, QueryAndTouchFile, filter); | 118 RUN_CALLBACK_TEST(TestFileRef, QueryAndTouchFile, filter); |
| 79 RUN_CALLBACK_TEST(TestFileRef, DeleteFileAndDirectory, filter); | 119 RUN_CALLBACK_TEST(TestFileRef, DeleteFileAndDirectory, filter); |
| 80 RUN_CALLBACK_TEST(TestFileRef, RenameFileAndDirectory, filter); | 120 RUN_CALLBACK_TEST(TestFileRef, RenameFileAndDirectory, filter); |
| 81 RUN_CALLBACK_TEST(TestFileRef, Query, filter); | 121 RUN_CALLBACK_TEST(TestFileRef, Query, filter); |
| 82 RUN_CALLBACK_TEST(TestFileRef, FileNameEscaping, filter); | 122 RUN_CALLBACK_TEST(TestFileRef, FileNameEscaping, filter); |
| 123 // FileRef::ReadEntries is in-process only. | |
| 124 if (testing_interface_->IsOutOfProcess()) | |
| 125 RUN_CALLBACK_TEST(TestFileRef, ReadEntries, filter); | |
| 83 } | 126 } |
| 84 | 127 |
| 85 std::string TestFileRef::TestCreate() { | 128 std::string TestFileRef::TestCreate() { |
| 86 std::vector<std::string> invalid_paths; | 129 std::vector<std::string> invalid_paths; |
| 87 invalid_paths.push_back("invalid_path"); // no '/' at the first character | 130 invalid_paths.push_back("invalid_path"); // no '/' at the first character |
| 88 invalid_paths.push_back(std::string()); // empty path | 131 invalid_paths.push_back(std::string()); // empty path |
| 89 // The following are directory traversal checks | 132 // The following are directory traversal checks |
| 90 invalid_paths.push_back(".."); | 133 invalid_paths.push_back(".."); |
| 91 invalid_paths.push_back("/../invalid_path"); | 134 invalid_paths.push_back("/../invalid_path"); |
| 92 invalid_paths.push_back("/../../invalid_path"); | 135 invalid_paths.push_back("/../../invalid_path"); |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 | 624 |
| 582 // Create the file with the terrible name. | 625 // Create the file with the terrible name. |
| 583 std::string full_file_path = test_dir_path + "/" + kTerribleName; | 626 std::string full_file_path = test_dir_path + "/" + kTerribleName; |
| 584 pp::FileRef file_ref(file_system, full_file_path.c_str()); | 627 pp::FileRef file_ref(file_system, full_file_path.c_str()); |
| 585 pp::FileIO file_io(instance_); | 628 pp::FileIO file_io(instance_); |
| 586 callback.WaitForResult( | 629 callback.WaitForResult( |
| 587 file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, callback.GetCallback())); | 630 file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, callback.GetCallback())); |
| 588 CHECK_CALLBACK_BEHAVIOR(callback); | 631 CHECK_CALLBACK_BEHAVIOR(callback); |
| 589 ASSERT_EQ(PP_OK, callback.result()); | 632 ASSERT_EQ(PP_OK, callback.result()); |
| 590 | 633 |
| 591 // DirectoryReader only works out-of-process. | 634 // FileRef::ReadEntries only works out-of-process. |
| 592 if (testing_interface_->IsOutOfProcess()) { | 635 if (testing_interface_->IsOutOfProcess()) { |
| 593 TestCompletionCallbackWithOutput< std::vector<pp::DirectoryEntry_Dev> > | 636 TestCompletionCallbackWithOutput<DirEntries> |
| 594 output_callback(instance_->pp_instance(), callback_type()); | 637 output_callback(instance_->pp_instance(), callback_type()); |
| 595 pp::DirectoryReader_Dev directory_reader(test_dir_ref); | |
| 596 | 638 |
| 597 output_callback.WaitForResult( | 639 output_callback.WaitForResult( |
| 598 directory_reader.ReadEntries(output_callback.GetCallback())); | 640 test_dir_ref.ReadEntries(output_callback.GetCallback())); |
| 599 CHECK_CALLBACK_BEHAVIOR(output_callback); | 641 CHECK_CALLBACK_BEHAVIOR(output_callback); |
| 600 ASSERT_EQ(PP_OK, output_callback.result()); | 642 ASSERT_EQ(PP_OK, output_callback.result()); |
| 601 | 643 |
| 602 std::vector<pp::DirectoryEntry_Dev> entries = output_callback.output(); | 644 DirEntries entries = output_callback.output(); |
| 603 ASSERT_EQ(1, entries.size()); | 645 ASSERT_EQ(1, entries.size()); |
| 604 ASSERT_EQ(kTerribleName, entries.front().file_ref().GetName().AsString()); | 646 ASSERT_EQ(kTerribleName, entries.front().file_ref().GetName().AsString()); |
| 605 } | 647 } |
| 606 | 648 |
| 607 PASS(); | 649 PASS(); |
| 608 } | 650 } |
| 651 | |
| 652 std::string TestFileRef::TestReadEntries() { | |
| 653 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | |
| 654 pp::FileSystem file_system( | |
| 655 instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); | |
| 656 callback.WaitForResult(file_system.Open(1024, callback.GetCallback())); | |
| 657 CHECK_CALLBACK_BEHAVIOR(callback); | |
| 658 ASSERT_EQ(PP_OK, callback.result()); | |
| 659 | |
| 660 // Setup testing directories and files. | |
| 661 const char* test_dir_name = "/test_get_next_file"; | |
| 662 const char* file_prefix = "file_"; | |
| 663 const char* dir_prefix = "dir_"; | |
| 664 | |
| 665 pp::FileRef test_dir(file_system, test_dir_name); | |
| 666 int32_t rv = DeleteDirectoryRecursively(&test_dir); | |
| 667 if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) | |
| 668 return ReportError("DeleteDirectoryRecursively", rv); | |
|
dmichael (off chromium)
2013/05/02 19:43:54
nit: I'd prefer just:
ASSERT_TRUE(rv == PP_OK || r
hamaji
2013/05/02 20:14:49
Done.
| |
| 669 | |
| 670 callback.WaitForResult(test_dir.MakeDirectory(callback.GetCallback())); | |
| 671 CHECK_CALLBACK_BEHAVIOR(callback); | |
| 672 ASSERT_EQ(PP_OK, callback.result()); | |
| 673 | |
| 674 std::set<std::string> expected_file_names; | |
| 675 for (int i = 1; i < 4; ++i) { | |
| 676 char buffer[40]; | |
| 677 sprintf(buffer, "%s/%s%d", test_dir_name, file_prefix, i); | |
|
dmichael (off chromium)
2013/05/02 19:43:54
snprintf
hamaji
2013/05/02 20:14:49
Done.
| |
| 678 pp::FileRef file_ref(file_system, buffer); | |
| 679 | |
| 680 pp::FileIO file_io(instance_); | |
| 681 callback.WaitForResult( | |
| 682 file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, callback.GetCallback())); | |
| 683 CHECK_CALLBACK_BEHAVIOR(callback); | |
| 684 ASSERT_EQ(PP_OK, callback.result()); | |
| 685 | |
| 686 expected_file_names.insert(buffer); | |
| 687 } | |
| 688 | |
| 689 std::set<std::string> expected_dir_names; | |
| 690 for (int i = 1; i < 4; ++i) { | |
|
dmichael (off chromium)
2013/05/02 19:43:54
suggestion: May make sense to use a constant like:
hamaji
2013/05/02 20:14:49
It seems this loop creates directories but the loo
| |
| 691 char buffer[40]; | |
| 692 sprintf(buffer, "%s/%s%d", test_dir_name, dir_prefix, i); | |
|
dmichael (off chromium)
2013/05/02 19:43:54
snprintf
hamaji
2013/05/02 20:14:49
Done.
| |
| 693 pp::FileRef file_ref(file_system, buffer); | |
| 694 | |
| 695 callback.WaitForResult(file_ref.MakeDirectory(callback.GetCallback())); | |
| 696 CHECK_CALLBACK_BEHAVIOR(callback); | |
| 697 ASSERT_EQ(PP_OK, callback.result()); | |
| 698 | |
| 699 expected_dir_names.insert(buffer); | |
| 700 } | |
| 701 | |
| 702 // Test that |ReadEntries()| is able to fetch all directories and files that | |
| 703 // we created. | |
| 704 { | |
| 705 TestCompletionCallbackWithOutput<DirEntries> output_callback( | |
| 706 instance_->pp_instance(), callback_type()); | |
| 707 | |
| 708 output_callback.WaitForResult( | |
| 709 test_dir.ReadEntries(output_callback.GetCallback())); | |
| 710 CHECK_CALLBACK_BEHAVIOR(output_callback); | |
| 711 ASSERT_EQ(PP_OK, output_callback.result()); | |
| 712 | |
| 713 DirEntries entries = output_callback.output(); | |
| 714 size_t sum = expected_file_names.size() + expected_dir_names.size(); | |
| 715 if (entries.size() != sum) | |
| 716 return "Expected " + IntegerToString(sum) + " entries, got " + | |
| 717 IntegerToString(entries.size()); | |
|
dmichael (off chromium)
2013/05/02 19:43:54
How about just ASSERT_EQ(entries.size(), sum);
The
hamaji
2013/05/02 20:14:49
Done.
| |
| 718 | |
| 719 for (DirEntries::const_iterator it = entries.begin(); | |
| 720 it != entries.end(); ++it) { | |
| 721 pp::FileRef file_ref = it->file_ref(); | |
| 722 std::string file_path = file_ref.GetPath().AsString(); | |
| 723 std::set<std::string>::iterator found = | |
| 724 expected_file_names.find(file_path); | |
| 725 if (found != expected_file_names.end()) { | |
| 726 if (it->file_type() != PP_FILETYPE_REGULAR) | |
| 727 return file_path + " should have been a regular file."; | |
| 728 expected_file_names.erase(found); | |
| 729 } else { | |
| 730 found = expected_dir_names.find(file_path); | |
| 731 if (found == expected_dir_names.end()) | |
| 732 return "Unexpected file path: " + file_path; | |
| 733 if (it->file_type() != PP_FILETYPE_DIRECTORY) | |
| 734 return file_path + " should have been a directory."; | |
| 735 expected_dir_names.erase(found); | |
| 736 } | |
| 737 } | |
| 738 if (!expected_file_names.empty() || !expected_dir_names.empty()) | |
| 739 return "Expected more file paths."; | |
|
dmichael (off chromium)
2013/05/02 19:43:54
ASSERT_TRUE(expected_file_names.empty());
ASSERT_T
hamaji
2013/05/02 20:14:49
Done.
| |
| 740 } | |
| 741 | |
| 742 // Test cancellation of asynchronous |ReadEntries()|. | |
| 743 TestCompletionCallbackWithOutput<DirEntries> output_callback( | |
| 744 instance_->pp_instance(), callback_type()); | |
| 745 { | |
| 746 rv = pp::FileRef(file_system, test_dir_name) | |
| 747 .ReadEntries(output_callback.GetCallback()); | |
| 748 } | |
| 749 output_callback.WaitForAbortResult(rv); | |
| 750 CHECK_CALLBACK_BEHAVIOR(output_callback); | |
| 751 | |
| 752 | |
| 753 PASS(); | |
| 754 } | |
| OLD | NEW |