| Index: ppapi/tests/test_post_message.cc
|
| diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
|
| index 39102e1f6ebb64cf964c1d490d399158f4c0f2b7..8c67ee5a7c1b8907c89d6d86708ba8145cccba1f 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.
|
|
|