| Index: ppapi/tests/test_post_message.cc
|
| diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
|
| index f19a3b1853deeebea0966576176961f956bcc325..9d6e5696762ca5605d742015c0b5544202e4a980 100644
|
| --- a/ppapi/tests/test_post_message.cc
|
| +++ b/ppapi/tests/test_post_message.cc
|
| @@ -28,8 +28,8 @@ const char kTestString[] = "Hello world!";
|
| const bool kTestBool = true;
|
| const int32_t kTestInt = 42;
|
| const double kTestDouble = 42.0;
|
| -const int32_t kThreadsToRun = 10;
|
| -const int32_t kMessagesToSendPerThread = 50;
|
| +const int32_t kThreadsToRun = 4;
|
| +const int32_t kMessagesToSendPerThread = 10;
|
|
|
| // 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
|
| @@ -49,13 +49,67 @@ void InvokePostMessageThreadFunc(void* user_data) {
|
| delete arg;
|
| }
|
|
|
| +#define FINISHED_WAITING_MESSAGE "TEST_POST_MESSAGE_FINISHED_WAITING"
|
| +
|
| } // namespace
|
|
|
| +TestPostMessage::TestPostMessage(TestingInstance* instance)
|
| + : TestCase(instance) {
|
| +}
|
| +
|
| +TestPostMessage::~TestPostMessage() {
|
| + // Remove the special listener that only responds to a FINISHED_WAITING
|
| + // string. See Init for where it gets added.
|
| + std::string js_code;
|
| + js_code += "var plugin = document.getElementById('plugin');"
|
| + "plugin.removeEventListener('message',"
|
| + " plugin.wait_for_messages_handler);"
|
| + "delete plugin.wait_for_messages_handler;";
|
| + pp::Var exception;
|
| + instance_->ExecuteScript(js_code, &exception);
|
| +}
|
| +
|
| bool TestPostMessage::Init() {
|
| - return InitTestingInterface();
|
| + bool success = InitTestingInterface();
|
| +
|
| + // Set up a special listener that only responds to a FINISHED_WAITING string.
|
| + // This is for use by WaitForMessages.
|
| + std::string js_code;
|
| + // Note the following code is dependent on some features of test_case.html.
|
| + // E.g., it is assumed that the DOM element where the plugin is embedded has
|
| + // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
|
| + // us to ignore the messages that are intended for use by the testing
|
| + // framework itself.
|
| + js_code += "var plugin = document.getElementById('plugin');"
|
| + "var wait_for_messages_handler = function(message_event) {"
|
| + " if (!IsTestingMessage(message_event.data) &&"
|
| + " message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
|
| + " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
|
| + " }"
|
| + "};"
|
| + "plugin.addEventListener('message', wait_for_messages_handler);"
|
| + // Stash it on the plugin so we can remove it in the destructor.
|
| + "plugin.wait_for_messages_handler = wait_for_messages_handler;";
|
| + pp::Var exception;
|
| + instance_->ExecuteScript(js_code, &exception);
|
| + success = success && exception.is_undefined();
|
| +
|
| + // Set up the JavaScript message event listener to echo the data part of the
|
| + // message event back to us.
|
| + success = success && AddEchoingListener("message_event.data");
|
| + message_data_.clear();
|
| + // Send a message that the first test will expect to receive. This is to
|
| + // verify that we can send messages when the 'Instance::Init' function is on
|
| + // the stack.
|
| + instance_->PostMessage(pp::Var(kTestString));
|
| +
|
| + return success;
|
| }
|
|
|
| void TestPostMessage::RunTest() {
|
| + // Note: SendInInit must be first, because it expects to receive a message
|
| + // that was sent in Init above.
|
| + RUN_TEST(SendInInit);
|
| RUN_TEST(SendingData);
|
| RUN_TEST(MessageEvent);
|
| RUN_TEST(NoHandler);
|
| @@ -65,8 +119,11 @@ void TestPostMessage::RunTest() {
|
| }
|
|
|
| void TestPostMessage::HandleMessage(const pp::Var& message_data) {
|
| - message_data_.push_back(message_data);
|
| - testing_interface_->QuitMessageLoop(instance_->pp_instance());
|
| + if (message_data.is_string() &&
|
| + (message_data.AsString() == FINISHED_WAITING_MESSAGE))
|
| + testing_interface_->QuitMessageLoop(instance_->pp_instance());
|
| + else
|
| + message_data_.push_back(message_data);
|
| }
|
|
|
| bool TestPostMessage::AddEchoingListener(const std::string& expression) {
|
| @@ -78,7 +135,8 @@ bool TestPostMessage::AddEchoingListener(const std::string& expression) {
|
| // framework itself.
|
| js_code += "var plugin = document.getElementById('plugin');"
|
| "var message_handler = function(message_event) {"
|
| - " if (!IsTestingMessage(message_event.data)) {"
|
| + " if (!IsTestingMessage(message_event.data) &&"
|
| + " !(message_event.data === '" FINISHED_WAITING_MESSAGE "')) {"
|
| " plugin.postMessage(";
|
| js_code += expression;
|
| js_code += " );"
|
| @@ -106,9 +164,31 @@ bool TestPostMessage::ClearListeners() {
|
| return(exception.is_undefined());
|
| }
|
|
|
| +int TestPostMessage::WaitForMessages() {
|
| + size_t message_size_before = message_data_.size();
|
| + // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to
|
| + // come back _after_ any other incoming messages that were already pending.
|
| + instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
|
| + testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| + // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know
|
| + // that all pending messages have been slurped up. Return the number we
|
| + // received (which may be zero).
|
| + return message_data_.size() - message_size_before;
|
| +}
|
| +
|
| +std::string TestPostMessage::TestSendInInit() {
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| + // This test assumes Init already sent a message.
|
| + ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_TRUE(message_data_.back().is_string());
|
| + ASSERT_EQ(message_data_.back().AsString(), kTestString);
|
| + PASS();
|
| +}
|
| +
|
| std::string TestPostMessage::TestSendingData() {
|
| // Set up the JavaScript message event listener to echo the data part of the
|
| // message event back to us.
|
| + ASSERT_TRUE(ClearListeners());
|
| ASSERT_TRUE(AddEchoingListener("message_event.data"));
|
|
|
| // Test sending a message to JavaScript for each supported type. The JS sends
|
| @@ -117,25 +197,21 @@ std::string TestPostMessage::TestSendingData() {
|
| instance_->PostMessage(pp::Var(kTestString));
|
| // PostMessage is asynchronous, so we should not receive a response yet.
|
| ASSERT_EQ(message_data_.size(), 0);
|
| -
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_string());
|
| ASSERT_EQ(message_data_.back().AsString(), kTestString);
|
|
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var(kTestBool));
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_bool());
|
| ASSERT_EQ(message_data_.back().AsBool(), kTestBool);
|
|
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var(kTestInt));
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_number());
|
| ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(),
|
| static_cast<double>(kTestInt));
|
| @@ -143,23 +219,20 @@ std::string TestPostMessage::TestSendingData() {
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var(kTestDouble));
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_number());
|
| ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(), kTestDouble);
|
|
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var());
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_undefined());
|
|
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var(pp::Var::Null()));
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_null());
|
|
|
| ASSERT_TRUE(ClearListeners());
|
| @@ -173,12 +246,12 @@ std::string TestPostMessage::TestMessageEvent() {
|
|
|
| // Have the listener pass back the type of message_event and make sure it's
|
| // "object".
|
| + ASSERT_TRUE(ClearListeners());
|
| ASSERT_TRUE(AddEchoingListener("typeof(message_event)"));
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var(kTestInt));
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_string());
|
| ASSERT_EQ(message_data_.back().AsString(), "object");
|
| ASSERT_TRUE(ClearListeners());
|
| @@ -195,8 +268,7 @@ std::string TestPostMessage::TestMessageEvent() {
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var(kTestInt));
|
| ASSERT_EQ(message_data_.size(), 0);
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 1);
|
| + ASSERT_EQ(WaitForMessages(), 1);
|
| ASSERT_TRUE(message_data_.back().is_bool());
|
| ASSERT_TRUE(message_data_.back().AsBool());
|
| ASSERT_TRUE(ClearListeners());
|
| @@ -211,10 +283,7 @@ std::string TestPostMessage::TestMessageEvent() {
|
| // Make sure we don't get a response in a re-entrant fashion.
|
| ASSERT_EQ(message_data_.size(), 0);
|
| // We should get 3 messages.
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - testing_interface_->RunMessageLoop(instance_->pp_instance());
|
| - ASSERT_EQ(message_data_.size(), 3);
|
| + ASSERT_EQ(WaitForMessages(), 3);
|
| // Copy to a vector of doubles and sort; w3c does not specify the order for
|
| // event listeners. (Copying is easier than writing an operator< for pp::Var.)
|
| //
|
| @@ -242,13 +311,7 @@ std::string TestPostMessage::TestNoHandler() {
|
| // Now send a message. We shouldn't get a response.
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var());
|
| - // Note that at this point, if we call RunMessageLoop, we should hang, because
|
| - // there should be no call to our HandleMessage function to quit the loop.
|
| - // Therefore, we will do CallOnMainThread to yield control. That event should
|
| - // fire, but we should see no messages when we return.
|
| - TestCompletionCallback callback(instance_->pp_instance());
|
| - pp::Module::Get()->core()->CallOnMainThread(0, callback);
|
| - callback.WaitForResult();
|
| + ASSERT_EQ(WaitForMessages(), 0);
|
| ASSERT_TRUE(message_data_.empty());
|
|
|
| PASS();
|
| @@ -264,13 +327,7 @@ std::string TestPostMessage::TestExtraParam() {
|
| // Now send a message. We shouldn't get a response.
|
| message_data_.clear();
|
| instance_->PostMessage(pp::Var());
|
| - // Note that at this point, if we call RunMessageLoop, we should hang, because
|
| - // there should be no call to our HandleMessage function to quit the loop.
|
| - // Therefore, we will do CallOnMainThread to yield control. That event should
|
| - // fire, but we should see no messages when we return.
|
| - TestCompletionCallback callback(instance_->pp_instance());
|
| - pp::Module::Get()->core()->CallOnMainThread(0, callback);
|
| - callback.WaitForResult();
|
| + ASSERT_EQ(WaitForMessages(), 0);
|
| ASSERT_TRUE(message_data_.empty());
|
|
|
| PASS();
|
| @@ -312,14 +369,9 @@ std::string TestPostMessage::TestNonMainThread() {
|
| std::vector<int32_t> expected_counts(kThreadsToRun + 1,
|
| kMessagesToSendPerThread);
|
| std::vector<int32_t> received_counts(kThreadsToRun + 1, 0);
|
| + ASSERT_EQ(WaitForMessages(), expected_num);
|
| 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();
|
| -
|
| + const pp::Var& latest_var(message_data_[i]);
|
| ASSERT_TRUE(latest_var.is_int() || latest_var.is_double());
|
| int32_t received_value = -1;
|
| if (latest_var.is_int()) {
|
|
|