summaryrefslogtreecommitdiffstats
path: root/ppapi/tests
diff options
context:
space:
mode:
authordmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-06 19:21:21 +0000
committerdmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-06 19:21:21 +0000
commit9260b8f0d823ba65403bd4924bf07e7ab67b9250 (patch)
tree62a24e4217706af50c836eedb29745055780b485 /ppapi/tests
parent2391c42b05c58cd8e00a541c4b6c856f00d1a119 (diff)
downloadchromium_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.cc148
-rw-r--r--ppapi/tests/test_post_message.h12
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();