diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-06 19:21:21 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-06 19:21:21 +0000 |
commit | 9260b8f0d823ba65403bd4924bf07e7ab67b9250 (patch) | |
tree | 62a24e4217706af50c836eedb29745055780b485 /ppapi/tests | |
parent | 2391c42b05c58cd8e00a541c4b6c856f00d1a119 (diff) | |
download | chromium_src-9260b8f0d823ba65403bd4924bf07e7ab67b9250.zip chromium_src-9260b8f0d823ba65403bd4924bf07e7ab67b9250.tar.gz chromium_src-9260b8f0d823ba65403bd4924bf07e7ab67b9250.tar.bz2 |
Reland http://codereview.chromium.org/7821001/
Add test for calling PostMessage during Init. Deflakify TestPostMessage.
BUG=93260,91768
TEST=This test
TBR=dmichael
Review URL: http://codereview.chromium.org/7834049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99785 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/tests')
-rw-r--r-- | ppapi/tests/test_post_message.cc | 148 | ||||
-rw-r--r-- | ppapi/tests/test_post_message.h | 12 |
2 files changed, 111 insertions, 49 deletions
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc index f19a3b1..9d6e569 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()) { diff --git a/ppapi/tests/test_post_message.h b/ppapi/tests/test_post_message.h index f081880..af1dc36 100644 --- a/ppapi/tests/test_post_message.h +++ b/ppapi/tests/test_post_message.h @@ -12,7 +12,8 @@ class TestPostMessage : public TestCase { public: - explicit TestPostMessage(TestingInstance* instance) : TestCase(instance) {} + explicit TestPostMessage(TestingInstance* instance); + virtual ~TestPostMessage(); private: // TestCase implementation. @@ -38,6 +39,15 @@ class TestPostMessage : public TestCase { // Returns true on success, false on failure. bool ClearListeners(); + // Wait for pending messages; return the number of messages that were pending + // at the time of invocation. + int WaitForMessages(); + + // Test that we can send a message from Instance::Init. Note the actual + // message is sent in TestPostMessage::Init, and this test simply makes sure + // we got it. + std::string TestSendInInit(); + // Test some basic functionality; make sure we can send data successfully // in both directions. std::string TestSendingData(); |