Chromium Code Reviews| 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..f18771f3c1dc23dc1d3713c29ce316a392b38e38 100644 |
| --- a/ppapi/tests/test_post_message.cc |
| +++ b/ppapi/tests/test_post_message.cc |
| @@ -49,13 +49,68 @@ void InvokePostMessageThreadFunc(void* user_data) { |
| delete arg; |
| } |
| +#define FINISHED_WAITING_MESSAGE "TEST_POST_MESSAGE_FINISHED_WAITING" |
| + |
| } // namespace |
| +TestPostMessage::TestPostMessage(TestingInstance* instance) |
| + : TestCase(instance), |
| + finished_waiting_(false) { |
| +} |
| + |
| +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,7 +120,11 @@ void TestPostMessage::RunTest() { |
| } |
| void TestPostMessage::HandleMessage(const pp::Var& message_data) { |
| - message_data_.push_back(message_data); |
| + if (message_data.is_string() && |
| + (message_data.AsString() == FINISHED_WAITING_MESSAGE)) |
| + finished_waiting_ = true; |
| + else |
| + message_data_.push_back(message_data); |
| testing_interface_->QuitMessageLoop(instance_->pp_instance()); |
| } |
| @@ -78,7 +137,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 +166,33 @@ bool TestPostMessage::ClearListeners() { |
| return(exception.is_undefined()); |
| } |
| +int TestPostMessage::WaitForMessages() { |
| + size_t message_size_before = message_data_.size(); |
| + finished_waiting_ = false; |
| + // 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)); |
| + while (!finished_waiting_) |
| + testing_interface_->RunMessageLoop(instance_->pp_instance()); |
|
Paweł Hajdan Jr.
2011/09/01 18:54:43
Could you run the message loop only once please? W
|
| + // 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 +201,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 +223,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 +250,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 +272,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 +287,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 +315,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 +331,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 +373,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()) { |