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 |