Index: ppapi/tests/extensions/packaged_app/test_packaged_app.cc |
diff --git a/ppapi/tests/extensions/packaged_app/test_packaged_app.cc b/ppapi/tests/extensions/packaged_app/test_packaged_app.cc |
index 754cc61809b0b9b750a24e1d58c55dfcb2cd8c89..d375a934090d098d32f55ec497117b03b199c4fe 100644 |
--- a/ppapi/tests/extensions/packaged_app/test_packaged_app.cc |
+++ b/ppapi/tests/extensions/packaged_app/test_packaged_app.cc |
@@ -2,19 +2,128 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <pthread.h> |
+#include <unistd.h> |
+ |
+#include <sstream> |
+#include <string> |
+ |
+#include "native_client/src/untrusted/irt/irt.h" |
+ |
+#include "ppapi/cpp/completion_callback.h" |
#include "ppapi/cpp/instance.h" |
#include "ppapi/cpp/module.h" |
#include "ppapi/cpp/var.h" |
namespace { |
+std::string g_last_error; |
+pp::Instance* g_instance = NULL; |
+ |
+// This should be the same as FileDescriptorSet::kMaxDescriptorsPerMessage in |
+// ipc/file_descriptor_set_posix.h. |
+// TODO(yusukes): Once all the NaCl toolchains support C++11, Add |
+// #include "ipc/file_descriptor_set_posix.h" and remove the constant. |
+const size_t kMaxDescriptorsPerMessage = 7; |
+ |
+// Returns true if the resource file whose name is |key| exists and its content |
+// matches |content|. |
+bool LoadManifestInternal(nacl_irt_resource_open* nacl_irt_resource_open, |
+ const std::string& key, |
+ const std::string& content) { |
+ int desc; |
+ int error; |
+ error = nacl_irt_resource_open->open_resource(key.c_str(), &desc); |
+ if (0 != error) { |
+ g_last_error = "Can't open file " + key; |
+ return false; |
+ } |
+ |
+ std::string str; |
+ |
+ char buffer[4096]; |
+ int len; |
+ while ((len = read(desc, buffer, sizeof(buffer) - 1)) > 0) { |
+ // Null terminate. |
+ buffer[len] = '\0'; |
+ str += buffer; |
+ } |
+ if (close(desc)) { |
+ g_last_error = "Close failed: file=" + key; |
+ return false; |
+ } |
+ |
+ if (str != content) { |
+ g_last_error = "Wrong file content: file=" + key + ", expected=" + content + |
+ ", actual=" + str; |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+// Tests if open_resource works in a packaged app. This test is similar to |
+// NaClBrowserTest*.IrtManifestFile, but unlike the NaCl test, this one tests |
+// the "fast path" in DownloadNexe() in ppb_nacl_private_impl.cc which opens |
+// resource files without using URLLoader. |
+void LoadManifest() { |
+ if (pthread_detach(pthread_self())) { |
+ g_last_error = "pthread_detach failed"; |
+ return; |
+ } |
+ |
+ struct nacl_irt_resource_open nacl_irt_resource_open; |
+ if (sizeof(nacl_irt_resource_open) != |
+ nacl_interface_query(NACL_IRT_RESOURCE_OPEN_v0_1, |
+ &nacl_irt_resource_open, |
+ sizeof(nacl_irt_resource_open))) { |
+ g_last_error = "NACL_IRT_RESOURCE_OPEN_v0_1 not found"; |
+ return; |
+ } |
+ |
+ for (size_t i = 0; i <= kMaxDescriptorsPerMessage; ++i) { |
+ std::stringstream key; |
+ key << "test_file" << i; |
+ std::string content = "Example contents for open_resource test" + |
+ std::string(i % 2 ? "2" : ""); |
+ if (!LoadManifestInternal(&nacl_irt_resource_open, key.str(), content)) |
+ break; |
+ // Open the same resource file again to make sure each file descriptor |
+ // returned from open_resource has its own file offset. |
+ if (!LoadManifestInternal(&nacl_irt_resource_open, key.str(), content)) |
+ break; |
+ } |
+} |
+ |
+void PostReply(void* user_data, int32_t status) { |
+ if (!g_last_error.empty()) |
+ g_instance->PostMessage(g_last_error.c_str()); |
+ else |
+ g_instance->PostMessage("Test passed"); |
+} |
+ |
+void* RunTestsOnBackgroundThread(void* thread_id) { |
+ LoadManifest(); |
+ pp::Module::Get()->core()->CallOnMainThread( |
+ 0, pp::CompletionCallback(&PostReply, NULL)); |
+ return NULL; |
+} |
+ |
class MyInstance : public pp::Instance { |
public: |
- explicit MyInstance(PP_Instance instance) : pp::Instance(instance) { } |
+ explicit MyInstance(PP_Instance instance) : pp::Instance(instance) { |
+ g_instance = this; |
+ } |
virtual ~MyInstance() { } |
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
- PostMessage("hello"); |
+ pthread_t thread; |
+ // irt_open_resource() isn't allowed to be called on the main thread once |
+ // Pepper starts, so the test must happen on a background thread. |
+ if (pthread_create(&thread, NULL, &RunTestsOnBackgroundThread, NULL)) { |
+ g_last_error = "pthread_create failed"; |
+ PostReply(NULL, 0); |
+ } |
return true; |
} |
}; |