summaryrefslogtreecommitdiffstats
path: root/ppapi/tests/test_post_message.cc
diff options
context:
space:
mode:
authorraymes@chromium.org <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-17 20:54:00 +0000
committerraymes@chromium.org <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-17 20:54:00 +0000
commitffd49dfc0729301c77dcf5026d29fa9cbedaecc1 (patch)
tree24bf475f55603bc61de7a7a9ff8c425cd16b120d /ppapi/tests/test_post_message.cc
parent30dca89c84bec4276bf9ad89b9fdbd18b8cf56a5 (diff)
downloadchromium_src-ffd49dfc0729301c77dcf5026d29fa9cbedaecc1.zip
chromium_src-ffd49dfc0729301c77dcf5026d29fa9cbedaecc1.tar.gz
chromium_src-ffd49dfc0729301c77dcf5026d29fa9cbedaecc1.tar.bz2
Hook up V8<->Var conversion in the pepper message channel
This hooks up V8<->Var conversion in the pepper message channel so that Array/Dictionaries can be transmitted to and from the plugin using Post/HandleMessage. This CL also adds integration tests for transmitting Arrays/Dictionaries. BUG=236958 Review URL: https://chromiumcodereview.appspot.com/14636009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200880 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/tests/test_post_message.cc')
-rw-r--r--ppapi/tests/test_post_message.cc241
1 files changed, 227 insertions, 14 deletions
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
index 39102e1..8c67ee5 100644
--- a/ppapi/tests/test_post_message.cc
+++ b/ppapi/tests/test_post_message.cc
@@ -5,6 +5,7 @@
#include "ppapi/tests/test_post_message.h"
#include <algorithm>
+#include <map>
#include <sstream>
#include "ppapi/c/dev/ppb_testing_dev.h"
@@ -58,6 +59,64 @@ void InvokePostMessageThreadFunc(void* user_data) {
delete arg;
}
+// TODO(raymes): Consider putting something like this into pp::Var.
+bool VarsEqual(const pp::Var& expected,
+ const pp::Var& actual,
+ std::map<int64_t, int64_t>* visited_ids) {
+ if (expected.pp_var().type != actual.pp_var().type) {
+ if (!expected.is_number() && !actual.is_number())
+ return false;
+ }
+ // TODO(raymes): Implement a pp::Var::IsRefCounted() function.
+ if (expected.pp_var().type > PP_VARTYPE_DOUBLE) {
+ std::map<int64_t, int64_t>::const_iterator it =
+ visited_ids->find(expected.pp_var().value.as_id);
+ if (it != visited_ids->end()) {
+ if (it->second == actual.pp_var().value.as_id)
+ return true;
+ return false;
+ }
+ (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id;
+ }
+
+ if (expected.is_number()) {
+ return fabs(expected.AsDouble() - actual.AsDouble()) < 1.0e-4;
+ } else if (expected.is_array()) {
+ pp::VarArray_Dev expected_array(expected);
+ pp::VarArray_Dev actual_array(actual);
+ if (expected_array.GetLength() != actual_array.GetLength())
+ return false;
+ for (uint32_t i = 0; i < expected_array.GetLength(); ++i) {
+ if (!VarsEqual(expected_array.Get(i), actual_array.Get(i), visited_ids))
+ return false;
+ }
+ return true;
+ } else if (expected.is_dictionary()) {
+ pp::VarDictionary_Dev expected_dict(expected);
+ pp::VarDictionary_Dev actual_dict(actual);
+ if (expected_dict.GetKeys().GetLength() !=
+ actual_dict.GetKeys().GetLength()) {
+ return false;
+ }
+ for (uint32_t i = 0; i < expected_dict.GetKeys().GetLength(); ++i) {
+ pp::Var key = expected_dict.GetKeys().Get(i);
+ if (actual_dict.HasKey(key) == PP_FALSE)
+ return false;
+ if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids))
+ return false;
+ }
+ return true;
+ } else {
+ return expected == actual;
+ }
+}
+
+bool VarsEqual(const pp::Var& expected,
+ const pp::Var& actual) {
+ std::map<int64_t, int64_t> visited_ids;
+ return VarsEqual(expected, actual, &visited_ids);
+}
+
class ScopedArrayBufferSizeSetter {
public:
ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface,
@@ -135,6 +194,9 @@ void TestPostMessage::RunTests(const std::string& filter) {
RUN_TEST(SendInInit, filter);
RUN_TEST(SendingData, filter);
RUN_TEST(SendingArrayBuffer, filter);
+ RUN_TEST(SendingArray, filter);
+ RUN_TEST(SendingDictionary, filter);
+ RUN_TEST(SendingComplexVar, filter);
RUN_TEST(MessageEvent, filter);
RUN_TEST(NoHandler, filter);
RUN_TEST(ExtraParam, filter);
@@ -199,6 +261,27 @@ int TestPostMessage::WaitForMessages() {
return message_data_.size() - message_size_before;
}
+std::string TestPostMessage::CheckMessageProperties(
+ const pp::Var& test_data,
+ const std::vector<std::string>& properties_to_check) {
+ typedef std::vector<std::string>::const_iterator Iterator;
+ for (Iterator iter = properties_to_check.begin();
+ iter != properties_to_check.end();
+ ++iter) {
+ ASSERT_TRUE(AddEchoingListener(*iter));
+ message_data_.clear();
+ instance_->PostMessage(test_data);
+ ASSERT_EQ(message_data_.size(), 0);
+ ASSERT_EQ(WaitForMessages(), 1);
+ ASSERT_TRUE(message_data_.back().is_bool());
+ if (!message_data_.back().AsBool())
+ return std::string("Failed: ") + *iter;
+ ASSERT_TRUE(message_data_.back().AsBool());
+ ASSERT_TRUE(ClearListeners());
+ }
+ PASS();
+}
+
std::string TestPostMessage::TestSendInInit() {
ASSERT_EQ(WaitForMessages(), 1);
// This test assumes Init already sent a message.
@@ -317,20 +400,8 @@ std::string TestPostMessage::TestSendingArrayBuffer() {
std::string expected_byte("(message_event.data.byteLength-1)%256");
properties_to_check.push_back(received_byte + " == " + expected_byte);
}
- for (std::vector<std::string>::iterator iter = properties_to_check.begin();
- iter != properties_to_check.end();
- ++iter) {
- ASSERT_TRUE(AddEchoingListener(*iter));
- message_data_.clear();
- instance_->PostMessage(test_data);
- ASSERT_EQ(message_data_.size(), 0);
- ASSERT_EQ(WaitForMessages(), 1);
- ASSERT_TRUE(message_data_.back().is_bool());
- if (!message_data_.back().AsBool())
- return std::string("Failed: ") + *iter + ", size: " + kSizeAsString;
- ASSERT_TRUE(message_data_.back().AsBool());
- ASSERT_TRUE(ClearListeners());
- }
+ ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(test_data,
+ properties_to_check));
// Set up the JavaScript message event listener to echo the data part of the
// message event back to us.
@@ -360,6 +431,148 @@ std::string TestPostMessage::TestSendingArrayBuffer() {
PASS();
}
+std::string TestPostMessage::TestSendingArray() {
+ // Clean up after previous tests. This also swallows the message sent by Init
+ // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
+ // should start with these.
+ WaitForMessages();
+ ASSERT_TRUE(ClearListeners());
+
+ pp::VarArray_Dev array;
+ array.Set(0, pp::Var(kTestBool));
+ array.Set(1, pp::Var(kTestString));
+ // Purposely leave index 2 empty.
+ array.Set(3, pp::Var(kTestInt));
+ array.Set(4, pp::Var(kTestDouble));
+
+ std::stringstream ss;
+ ss << array.GetLength();
+ std::string length_as_string(ss.str());
+
+ // Have the listener test some properties of the Array.
+ std::vector<std::string> properties_to_check;
+ properties_to_check.push_back(
+ "message_event.data.constructor.name === 'Array'");
+ properties_to_check.push_back(
+ std::string("message_event.data.length === ") + length_as_string);
+ ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(array, properties_to_check));
+
+ // Set up the JavaScript message event listener to echo the data part of the
+ // message event back to us.
+ ASSERT_TRUE(AddEchoingListener("message_event.data"));
+ message_data_.clear();
+ instance_->PostMessage(array);
+ // PostMessage is asynchronous, so we should not receive a response yet.
+ ASSERT_EQ(message_data_.size(), 0);
+ ASSERT_EQ(WaitForMessages(), 1);
+ ASSERT_TRUE(message_data_.back().is_array());
+ ASSERT_TRUE(VarsEqual(array, message_data_.back()));
+
+ message_data_.clear();
+ ASSERT_TRUE(ClearListeners());
+
+ PASS();
+}
+
+std::string TestPostMessage::TestSendingDictionary() {
+ // Clean up after previous tests. This also swallows the message sent by Init
+ // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
+ // should start with these.
+ WaitForMessages();
+ ASSERT_TRUE(ClearListeners());
+
+ pp::VarDictionary_Dev dictionary;
+ dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
+ dictionary.Set(pp::Var("bar"), pp::Var(kTestString));
+ dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
+ dictionary.Set(pp::Var("def"), pp::Var());
+
+ std::stringstream ss;
+ ss << dictionary.GetKeys().GetLength();
+ std::string length_as_string(ss.str());
+
+ // Have the listener test some properties of the Dictionary.
+ std::vector<std::string> properties_to_check;
+ properties_to_check.push_back(
+ "message_event.data.constructor.name === 'Object'");
+ properties_to_check.push_back(
+ std::string("Object.keys(message_event.data).length === ") +
+ length_as_string);
+ ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary,
+ properties_to_check));
+
+ // Set up the JavaScript message event listener to echo the data part of the
+ // message event back to us.
+ ASSERT_TRUE(AddEchoingListener("message_event.data"));
+ message_data_.clear();
+ instance_->PostMessage(dictionary);
+ // PostMessage is asynchronous, so we should not receive a response yet.
+ ASSERT_EQ(message_data_.size(), 0);
+ ASSERT_EQ(WaitForMessages(), 1);
+ ASSERT_TRUE(message_data_.back().is_dictionary());
+ ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
+
+ message_data_.clear();
+ ASSERT_TRUE(ClearListeners());
+
+ PASS();
+}
+
+std::string TestPostMessage::TestSendingComplexVar() {
+ // Clean up after previous tests. This also swallows the message sent by Init
+ // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
+ // should start with these.
+ WaitForMessages();
+ ASSERT_TRUE(ClearListeners());
+
+ pp::Var string(kTestString);
+ pp::VarDictionary_Dev dictionary;
+ dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
+ dictionary.Set(pp::Var("bar"), string);
+ dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
+ dictionary.Set(pp::Var("def"), pp::Var());
+ dictionary.Set(pp::Var("dictionary"), dictionary); // Self-reference.
+
+ // Reference to array.
+ pp::VarArray_Dev array;
+ array.Set(0, pp::Var(kTestBool));
+ array.Set(1, string);
+ // Purposely leave index 2 empty (which will place an undefined var there).
+ array.Set(3, pp::Var(kTestInt));
+ array.Set(4, pp::Var(kTestDouble));
+
+ dictionary.Set(pp::Var("array-ref1"), array);
+ dictionary.Set(pp::Var("array-ref2"), array);
+
+ // Set up a (dictionary -> array -> dictionary) cycle.
+ pp::VarArray_Dev array2;
+ array2.Set(0, dictionary);
+ dictionary.Set(pp::Var("array2"), array2);
+
+ // Set up the JavaScript message event listener to echo the data part of the
+ // message event back to us.
+ ASSERT_TRUE(AddEchoingListener("message_event.data"));
+ message_data_.clear();
+ instance_->PostMessage(dictionary);
+ // PostMessage is asynchronous, so we should not receive a response yet.
+ ASSERT_EQ(message_data_.size(), 0);
+ ASSERT_EQ(WaitForMessages(), 1);
+ ASSERT_TRUE(message_data_.back().is_dictionary());
+ pp::VarDictionary_Dev result(message_data_.back());
+ ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
+
+ // Break the cycles.
+ dictionary.Delete(pp::Var("dictionary"));
+ dictionary.Delete(pp::Var("array2"));
+ result.Delete(pp::Var("dictionary"));
+ result.Delete(pp::Var("array2"));
+
+ message_data_.clear();
+ ASSERT_TRUE(ClearListeners());
+
+ PASS();
+}
+
std::string TestPostMessage::TestMessageEvent() {
// Set up the JavaScript message event listener to pass us some values from
// the MessageEvent and make sure they match our expectations.