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()) { |