summaryrefslogtreecommitdiffstats
path: root/ppapi/tests
diff options
context:
space:
mode:
authordmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-30 19:38:31 +0000
committerdmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-30 19:38:31 +0000
commit5d904b9e9557916894feced1d0bad88e240f1b64 (patch)
tree7ae32210e7defe9ac590a14dec4e2cf02a127c33 /ppapi/tests
parent96e989bf9f8e335c1d08008f06253baeb9ba4f66 (diff)
downloadchromium_src-5d904b9e9557916894feced1d0bad88e240f1b64.zip
chromium_src-5d904b9e9557916894feced1d0bad88e240f1b64.tar.gz
chromium_src-5d904b9e9557916894feced1d0bad88e240f1b64.tar.bz2
Reland http://codereview.chromium.org/7648033
Add means for running some tests only o-o-p, add messaging o-o-p test. BUG=None TEST=included TBR=dmichael@chromium.org Review URL: http://codereview.chromium.org/7799031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98861 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/tests')
-rw-r--r--ppapi/tests/pp_thread.h117
-rw-r--r--ppapi/tests/test_case.h18
-rw-r--r--ppapi/tests/test_post_message.cc82
-rw-r--r--ppapi/tests/test_post_message.h3
4 files changed, 214 insertions, 6 deletions
diff --git a/ppapi/tests/pp_thread.h b/ppapi/tests/pp_thread.h
new file mode 100644
index 0000000..f168d8c
--- /dev/null
+++ b/ppapi/tests/pp_thread.h
@@ -0,0 +1,117 @@
+/* Copyright (c) 2011 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef PPAPI_TESTS_PP_THREAD_H_
+#define PPAPI_TESTS_PP_THREAD_H_
+
+#include "ppapi/c/pp_macros.h"
+
+/* These precompiler names were copied from chromium's build_config.h. */
+#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || defined(__sun) || defined(__native_client__)
+#define PPAPI_HAS_POSIX_THREADS 1
+#elif defined (_MSC_VER)
+#define PPAPI_HAS_WINDOWS_THREADS 1
+#endif
+
+#if defined(PPAPI_HAS_POSIX_THREADS)
+#include <pthread.h>
+#elif defined(PPAPI_HAS_WINDOWS_THREADS)
+#include <process.h>
+#include <windows.h>
+#endif
+
+/**
+ * @file
+ * This file provides platform-independent wrappers around threads. This is for
+ * use by PPAPI wrappers and tests which need to run on multiple platforms to
+ * support both trusted platforms (Windows, Mac, Linux) and untrusted (Native
+ * Client). Apps that use PPAPI only with Native Client should generally use the
+ * Native Client POSIX implementation instead.
+ *
+ * TODO(dmichael): Move this file to ppapi/c and delete this comment, if we end
+ * up needing platform independent threads in PPAPI C or C++. This file was
+ * written using inline functions and PPAPI naming conventions with the intent
+ * of making it possible to put it in to ppapi/c. Currently, however, it's only
+ * used in ppapi/tests, so is not part of the published API.
+ */
+
+#if defined(PPAPI_HAS_POSIX_THREADS)
+typedef pthread_t PP_ThreadType;
+#elif defined(PPAPI_HAS_WINDOWS_THREADS)
+typedef uintptr_t PP_ThreadType;
+#endif
+
+typedef void (PP_ThreadFunction)(void* data);
+
+PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
+ PP_ThreadFunction function,
+ void* thread_arg);
+PP_INLINE void PP_JoinThread(PP_ThreadType thread);
+
+#if defined(PPAPI_HAS_POSIX_THREADS)
+/* Because POSIX thread functions return void* and Windows thread functions do
+ * not, we make PPAPI thread functions have the least capability (no returns).
+ * This struct wraps the user data & function so that we can use the correct
+ * function type on POSIX platforms.
+ */
+struct PP_ThreadFunctionArgWrapper {
+ void* user_data;
+ PP_ThreadFunction* user_function;
+};
+
+PP_INLINE void* PP_POSIXThreadFunctionThunk(void* posix_thread_arg) {
+ PP_ThreadFunctionArgWrapper* arg_wrapper =
+ (PP_ThreadFunctionArgWrapper*)posix_thread_arg;
+ arg_wrapper->user_function(arg_wrapper->user_data);
+ free(posix_thread_arg);
+ return NULL;
+}
+
+PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
+ PP_ThreadFunction function,
+ void* thread_arg) {
+ PP_ThreadFunctionArgWrapper* arg_wrapper =
+ (PP_ThreadFunctionArgWrapper*)malloc(sizeof(PP_ThreadFunctionArgWrapper));
+ arg_wrapper->user_function = function;
+ arg_wrapper->user_data = thread_arg;
+ return (pthread_create(thread,
+ NULL,
+ PP_POSIXThreadFunctionThunk,
+ arg_wrapper) == 0);
+}
+
+PP_INLINE void PP_JoinThread(PP_ThreadType thread) {
+ void* exit_status;
+ pthread_join(thread, &exit_status);
+}
+
+#elif defined(PPAPI_HAS_WINDOWS_THREADS)
+typedef DWORD (PP_WindowsThreadFunction)(void* data);
+
+PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
+ PP_ThreadFunction function,
+ void* thread_arg) {
+ if (!thread)
+ return false;
+ *thread = ::_beginthread(function,
+ 0, /* Use default stack size. */
+ thread_arg);
+ return (*thread != NULL);
+}
+
+PP_INLINE void PP_JoinThread(PP_ThreadType thread) {
+ ::WaitForSingleObject((HANDLE)thread, INFINITE);
+}
+
+#endif
+
+
+/**
+ * @}
+ */
+
+#endif /* PPAPI_TESTS_PP_THREAD_H_ */
+
diff --git a/ppapi/tests/test_case.h b/ppapi/tests/test_case.h
index 0a3cdc6..06ebcb1 100644
--- a/ppapi/tests/test_case.h
+++ b/ppapi/tests/test_case.h
@@ -130,18 +130,24 @@ class TestCaseFactory {
// RunTest function. This assumes the function name is TestFoo where Foo is the
// test |name|.
#define RUN_TEST(name) \
- force_async_ = false; \
- instance_->LogTest(#name, Test##name());
+ do { \
+ force_async_ = false; \
+ instance_->LogTest(#name, Test##name()); \
+ } while (false)
// Like RUN_TEST above but forces functions taking callbacks to complete
// asynchronously on success or error.
#define RUN_TEST_FORCEASYNC(name) \
- force_async_ = true; \
- instance_->LogTest(#name"ForceAsync", Test##name());
+ do { \
+ force_async_ = true; \
+ instance_->LogTest(#name"ForceAsync", Test##name()); \
+ } while (false)
#define RUN_TEST_FORCEASYNC_AND_NOT(name) \
- RUN_TEST_FORCEASYNC(name); \
- RUN_TEST(name);
+ do { \
+ RUN_TEST_FORCEASYNC(name); \
+ RUN_TEST(name); \
+ } while (false)
// Helper macros for checking values in tests, and returning a location
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
index 10bc7a0..f19a3b1 100644
--- a/ppapi/tests/test_post_message.cc
+++ b/ppapi/tests/test_post_message.cc
@@ -11,6 +11,7 @@
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/var.h"
+#include "ppapi/tests/pp_thread.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"
@@ -28,6 +29,25 @@ const bool kTestBool = true;
const int32_t kTestInt = 42;
const double kTestDouble = 42.0;
const int32_t kThreadsToRun = 10;
+const int32_t kMessagesToSendPerThread = 50;
+
+// The struct that invoke_post_message_thread_func expects for its argument.
+// It includes the instance on which to invoke PostMessage, and the value to
+// pass to PostMessage.
+struct InvokePostMessageThreadArg {
+ InvokePostMessageThreadArg(pp::Instance* i, const pp::Var& v)
+ : instance(i), value_to_send(v) {}
+ pp::Instance* instance;
+ pp::Var value_to_send;
+};
+
+void InvokePostMessageThreadFunc(void* user_data) {
+ InvokePostMessageThreadArg* arg =
+ static_cast<InvokePostMessageThreadArg*>(user_data);
+ for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
+ arg->instance->PostMessage(arg->value_to_send);
+ delete arg;
+}
} // namespace
@@ -40,6 +60,8 @@ void TestPostMessage::RunTest() {
RUN_TEST(MessageEvent);
RUN_TEST(NoHandler);
RUN_TEST(ExtraParam);
+ if (testing_interface_->IsOutOfProcess())
+ RUN_TEST(NonMainThread);
}
void TestPostMessage::HandleMessage(const pp::Var& message_data) {
@@ -254,3 +276,63 @@ std::string TestPostMessage::TestExtraParam() {
PASS();
}
+std::string TestPostMessage::TestNonMainThread() {
+ ASSERT_TRUE(ClearListeners());
+ ASSERT_TRUE(AddEchoingListener("message_event.data"));
+ message_data_.clear();
+
+ // Set up a thread for each integer from 0 to (kThreadsToRun - 1). Make each
+ // thread send the number that matches its index kMessagesToSendPerThread
+ // times. For good measure, call postMessage from the main thread
+ // kMessagesToSendPerThread times. At the end, we make sure we got all the
+ // values we expected.
+ PP_ThreadType threads[kThreadsToRun];
+ for (int32_t i = 0; i < kThreadsToRun; ++i) {
+ // Set up a thread to send a value of i.
+ void* arg = new InvokePostMessageThreadArg(instance_, pp::Var(i));
+ PP_CreateThread(&threads[i], &InvokePostMessageThreadFunc, arg);
+ }
+ // Invoke PostMessage right now to send a value of (kThreadsToRun).
+ for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
+ instance_->PostMessage(pp::Var(kThreadsToRun));
+
+ // Now join all threads.
+ for (int32_t i = 0; i < kThreadsToRun; ++i)
+ PP_JoinThread(threads[i]);
+
+ // PostMessage is asynchronous, so we should not receive a response yet.
+ ASSERT_EQ(message_data_.size(), 0);
+
+ // Make sure we got all values that we expected. Note that because it's legal
+ // for the JavaScript engine to treat our integers as floating points, we
+ // can't just use std::find or equality comparison. So we instead, we convert
+ // each incoming value to an integer, and count them in received_counts.
+ int32_t expected_num = (kThreadsToRun + 1) * kMessagesToSendPerThread;
+ // Count how many we receive per-index.
+ std::vector<int32_t> expected_counts(kThreadsToRun + 1,
+ kMessagesToSendPerThread);
+ std::vector<int32_t> received_counts(kThreadsToRun + 1, 0);
+ for (int32_t i = 0; i < expected_num; ++i) {
+ // Run the message loop to get the next expected message.
+ testing_interface_->RunMessageLoop(instance_->pp_instance());
+ // Make sure we got another message in.
+ ASSERT_EQ(message_data_.size(), 1);
+ pp::Var latest_var(message_data_.back());
+ message_data_.clear();
+
+ ASSERT_TRUE(latest_var.is_int() || latest_var.is_double());
+ int32_t received_value = -1;
+ if (latest_var.is_int()) {
+ received_value = latest_var.AsInt();
+ } else if (latest_var.is_double()) {
+ received_value = static_cast<int32_t>(latest_var.AsDouble() + 0.5);
+ }
+ ASSERT_TRUE(received_value >= 0);
+ ASSERT_TRUE(received_value <= kThreadsToRun);
+ ++received_counts[received_value];
+ }
+ ASSERT_EQ(received_counts, expected_counts);
+
+ PASS();
+}
+
diff --git a/ppapi/tests/test_post_message.h b/ppapi/tests/test_post_message.h
index df7256b..f081880 100644
--- a/ppapi/tests/test_post_message.h
+++ b/ppapi/tests/test_post_message.h
@@ -53,6 +53,9 @@ class TestPostMessage : public TestCase {
// nothing happens.
std::string TestExtraParam();
+ // Test sending messages off of the main thread.
+ std::string TestNonMainThread();
+
typedef std::vector<pp::Var> VarVector;
// This is used to store pp::Var objects we receive via a call to