15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_post_message.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_testing_dev.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/cpp/var_array.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var_array_buffer.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/cpp/var_dictionary.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/pp_thread.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_utils.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/testing_instance.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows defines 'PostMessage', so we have to undef it.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PostMessage
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef PostMessage
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_TEST_CASE(PostMessage);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestString[] = "Hello world!";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const bool kTestBool = true;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32_t kTestInt = 42;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double kTestDouble = 42.0;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Windows XP bots, the NonMainThread test can run very slowly. So we dial
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// back the number of threads & messages when running on Windows.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PPAPI_OS_WIN
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32_t kThreadsToRun = 2;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32_t kMessagesToSendPerThread = 5;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32_t kThreadsToRun = 4;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32_t kMessagesToSendPerThread = 10;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The struct that invoke_post_message_thread_func expects for its argument.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It includes the instance on which to invoke PostMessage, and the value to
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pass to PostMessage.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct InvokePostMessageThreadArg {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InvokePostMessageThreadArg(pp::Instance* i, const pp::Var& v)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : instance(i), value_to_send(v) {}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Instance* instance;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var value_to_send;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvokePostMessageThreadFunc(void* user_data) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InvokePostMessageThreadArg* arg =
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<InvokePostMessageThreadArg*>(user_data);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg->instance->PostMessage(arg->value_to_send);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete arg;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// TODO(raymes): Consider putting something like this into pp::Var.
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool VarsEqual(const pp::Var& expected,
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               const pp::Var& actual,
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               std::map<int64_t, int64_t>* visited_ids) {
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (expected.pp_var().type != actual.pp_var().type) {
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!expected.is_number() && !actual.is_number())
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(raymes): Implement a pp::Var::IsRefCounted() function.
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (expected.pp_var().type > PP_VARTYPE_DOUBLE) {
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::map<int64_t, int64_t>::const_iterator it =
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        visited_ids->find(expected.pp_var().value.as_id);
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it != visited_ids->end()) {
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (it->second == actual.pp_var().value.as_id)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return true;
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id;
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (expected.is_number()) {
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return fabs(expected.AsDouble() - actual.AsDouble()) < 1.0e-4;
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (expected.is_array()) {
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::VarArray expected_array(expected);
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::VarArray actual_array(actual);
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (expected_array.GetLength() != actual_array.GetLength())
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (uint32_t i = 0; i < expected_array.GetLength(); ++i) {
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!VarsEqual(expected_array.Get(i), actual_array.Get(i), visited_ids))
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (expected.is_dictionary()) {
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::VarDictionary expected_dict(expected);
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::VarDictionary actual_dict(actual);
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (expected_dict.GetKeys().GetLength() !=
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        actual_dict.GetKeys().GetLength()) {
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (uint32_t i = 0; i < expected_dict.GetKeys().GetLength(); ++i) {
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      pp::Var key = expected_dict.GetKeys().Get(i);
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!actual_dict.HasKey(key))
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids))
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return expected == actual;
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool VarsEqual(const pp::Var& expected,
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               const pp::Var& actual) {
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::map<int64_t, int64_t> visited_ids;
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return VarsEqual(expected, actual, &visited_ids);
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ScopedArrayBufferSizeSetter {
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface,
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              PP_Instance instance,
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              uint32_t threshold)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     : interface_(interface),
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       instance_(instance) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold);
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~ScopedArrayBufferSizeSetter() {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    interface_->SetMinimumArrayBufferSizeForShmem(instance_, 0);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const PPB_Testing_Dev* interface_;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Instance instance_;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FINISHED_WAITING_MESSAGE "TEST_POST_MESSAGE_FINISHED_WAITING"
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestPostMessage::TestPostMessage(TestingInstance* instance)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : TestCase(instance) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestPostMessage::~TestPostMessage() {
148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  instance_->PostMessage(pp::Var("This isn't guaranteed to be received, but "
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                 "shouldn't cause a crash."));
150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the special listener that only responds to a FINISHED_WAITING
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string. See Init for where it gets added.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string js_code;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_code += "var plugin = document.getElementById('plugin');"
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "plugin.removeEventListener('message',"
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "                           plugin.wait_for_messages_handler);"
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "delete plugin.wait_for_messages_handler;";
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->EvalScript(js_code);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestPostMessage::Init() {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = CheckTestingInterface();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up a special listener that only responds to a FINISHED_WAITING string.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is for use by WaitForMessages.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string js_code;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note the following code is dependent on some features of test_case.html.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // E.g., it is assumed that the DOM element where the plugin is embedded has
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // us to ignore the messages that are intended for use by the testing
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // framework itself.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_code += "var plugin = document.getElementById('plugin');"
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "var wait_for_messages_handler = function(message_event) {"
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "  if (!IsTestingMessage(message_event.data) &&"
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "      message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "    plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "  }"
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "};"
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "plugin.addEventListener('message', wait_for_messages_handler);"
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             // Stash it on the plugin so we can remove it in the destructor.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "plugin.wait_for_messages_handler = wait_for_messages_handler;";
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->EvalScript(js_code);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up the JavaScript message event listener to echo the data part of the
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message event back to us.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  success = success && AddEchoingListener("message_event.data");
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a message that the first test will expect to receive. This is to
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify that we can send messages when the 'Instance::Init' function is on
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the stack.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestString));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestPostMessage::RunTests(const std::string& filter) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: SendInInit must be first, because it expects to receive a message
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that was sent in Init above.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(SendInInit, filter);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(SendingData, filter);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(SendingArrayBuffer, filter);
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RUN_TEST(SendingArray, filter);
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RUN_TEST(SendingDictionary, filter);
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RUN_TEST(SendingComplexVar, filter);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(MessageEvent, filter);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(NoHandler, filter);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(ExtraParam, filter);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (testing_interface_->IsOutOfProcess())
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN_TEST(NonMainThread, filter);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestPostMessage::HandleMessage(const pp::Var& message_data) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_data.is_string() &&
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (message_data.AsString() == FINISHED_WAITING_MESSAGE))
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    testing_interface_->QuitMessageLoop(instance_->pp_instance());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_data_.push_back(message_data);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestPostMessage::AddEchoingListener(const std::string& expression) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string js_code;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note the following code is dependent on some features of test_case.html.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // E.g., it is assumed that the DOM element where the plugin is embedded has
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // us to ignore the messages that are intended for use by the testing
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // framework itself.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_code += "var plugin = document.getElementById('plugin');"
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "var message_handler = function(message_event) {"
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "  if (!IsTestingMessage(message_event.data) &&"
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "      !(message_event.data === '" FINISHED_WAITING_MESSAGE "')) {"
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "    plugin.postMessage(";
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_code += expression;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_code += "                      );"
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "  }"
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "};"
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "plugin.addEventListener('message', message_handler);"
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             // Maintain an array of all event listeners, attached to the
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             // plugin. This is so that we can easily remove them later (see
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             // ClearListeners()).
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "if (!plugin.eventListeners) plugin.eventListeners = [];"
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "plugin.eventListeners.push(message_handler);";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->EvalScript(js_code);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) {
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string js_code;
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  js_code += "var plugin = document.getElementById('plugin');"
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             "plugin.postMessage(";
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  js_code += func + "()";
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  js_code += "                      );";
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  instance_->EvalScript(js_code);
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return true;
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestPostMessage::ClearListeners() {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string js_code;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_code += "var plugin = document.getElementById('plugin');"
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "while (plugin.eventListeners.length) {"
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "  plugin.removeEventListener('message',"
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "                             plugin.eventListeners.pop());"
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             "}";
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->EvalScript(js_code);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestPostMessage::WaitForMessages() {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t message_size_before = message_data_.size();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // come back _after_ any other incoming messages that were already pending.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  testing_interface_->RunMessageLoop(instance_->pp_instance());
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that all pending messages have been slurped up. Return the number we
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // received (which may be zero).
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return message_data_.size() - message_size_before;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string TestPostMessage::CheckMessageProperties(
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const pp::Var& test_data,
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::vector<std::string>& properties_to_check) {
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  typedef std::vector<std::string>::const_iterator Iterator;
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (Iterator iter = properties_to_check.begin();
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       iter != properties_to_check.end();
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       ++iter) {
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_TRUE(AddEchoingListener(*iter));
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    message_data_.clear();
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    instance_->PostMessage(test_data);
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_EQ(message_data_.size(), 0);
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_EQ(WaitForMessages(), 1);
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_TRUE(message_data_.back().is_bool());
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!message_data_.back().AsBool())
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return std::string("Failed: ") + *iter;
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_TRUE(message_data_.back().AsBool());
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_TRUE(ClearListeners());
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PASS();
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestSendInInit() {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test assumes Init already sent a message.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 1);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_string());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.back().AsString(), kTestString);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestSendingData() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clean up after previous tests. This also swallows the message sent by Init
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should start with these.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForMessages();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up the JavaScript message event listener to echo the data part of the
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message event back to us.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test sending a message to JavaScript for each supported type.  The JS sends
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the data back to us, and we check that they match.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestString));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PostMessage is asynchronous, so we should not receive a response yet.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_string());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.back().AsString(), kTestString);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestBool));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_bool());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.back().AsBool(), kTestBool);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestInt));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_number());
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   static_cast<double>(kTestInt));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestDouble));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_number());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(), kTestDouble);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var());
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_undefined());
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(pp::Var::Null()));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_null());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestSendingArrayBuffer() {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clean up after previous tests. This also swallows the message sent by Init
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should start with these.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForMessages();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sehr,dmichael): Add testing of longer array buffers when
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // crbug.com/110086 is fixed.
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScopedArrayBufferSizeSetter setter(testing_interface_,
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     instance_->pp_instance(),
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     200);
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32_t sizes[] = { 0, 100, 1000, 10000 };
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < sizeof(sizes)/sizeof(sizes[i]); ++i) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::ostringstream size_stream;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_stream << sizes[i];
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string kSizeAsString(size_stream.str());
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create an appropriately sized array buffer with test_data[i] == i.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::VarArrayBuffer test_data(sizes[i]);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sizes[i] > 0)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(NULL, test_data.Map());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure we can Unmap/Map successfully (there's not really any way to
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // detect if it's unmapped, so we just re-map before getting the pointer to
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the buffer).
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_data.Unmap();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_data.Map();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(sizes[i], test_data.ByteLength());
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char* buff = static_cast<unsigned char*>(test_data.Map());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t kByteLength = test_data.ByteLength();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < kByteLength; ++j)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buff[j] = static_cast<uint8_t>(j % 256u);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Have the listener test some properties of the ArrayBuffer.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> properties_to_check;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    properties_to_check.push_back(
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "message_event.data.constructor.name === 'ArrayBuffer'");
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    properties_to_check.push_back(
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string("message_event.data.byteLength === ") + kSizeAsString);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sizes[i] > 0) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      properties_to_check.push_back(
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "(new DataView(message_event.data)).getUint8(0) == 0");
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Checks that the last element has the right value: (byteLength-1)%256.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string received_byte("(new DataView(message_event.data)).getUint8("
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                "    message_event.data.byteLength-1)");
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string expected_byte("(message_event.data.byteLength-1)%256");
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      properties_to_check.push_back(received_byte + " == " + expected_byte);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(test_data,
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                  properties_to_check));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up the JavaScript message event listener to echo the data part of the
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // message event back to us.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(AddEchoingListener("message_event.data"));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_data_.clear();
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance_->PostMessage(test_data);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // PostMessage is asynchronous, so we should not receive a response yet.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(message_data_.size(), 0);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WaitForMessages(), 1);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(message_data_.back().is_array_buffer());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::VarArrayBuffer received(message_data_.back());
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_data_.clear();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(test_data.ByteLength(), received.ByteLength());
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char* received_buff = static_cast<unsigned char*>(received.Map());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The buffer should be copied, so this should be a distinct buffer. When
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 'transferrables' are implemented for PPAPI, we'll also want to test that
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we get the _same_ buffer back when it's transferred.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sizes[i] > 0)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(buff, received_buff);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < test_data.ByteLength(); ++i)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(buff[i], received_buff[i]);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_data_.clear();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(ClearListeners());
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string TestPostMessage::TestSendingArray() {
45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Clean up after previous tests. This also swallows the message sent by Init
45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // should start with these.
45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WaitForMessages();
45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(ClearListeners());
45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarArray array;
45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(0, pp::Var(kTestBool));
45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(1, pp::Var(kTestString));
45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Purposely leave index 2 empty.
46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(3, pp::Var(kTestInt));
46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(4, pp::Var(kTestDouble));
46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::stringstream ss;
46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ss << array.GetLength();
46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string length_as_string(ss.str());
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Have the listener test some properties of the Array.
46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<std::string> properties_to_check;
46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  properties_to_check.push_back(
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "message_event.data.constructor.name === 'Array'");
47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  properties_to_check.push_back(
47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string("message_event.data.length === ") + length_as_string);
47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(array, properties_to_check));
47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set up the JavaScript message event listener to echo the data part of the
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // message event back to us.
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  message_data_.clear();
47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  instance_->PostMessage(array);
48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // PostMessage is asynchronous, so we should not receive a response yet.
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
48290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
48390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_array());
48490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(VarsEqual(array, message_data_.back()));
48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  message_data_.clear();
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(ClearListeners());
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PASS();
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string TestPostMessage::TestSendingDictionary() {
49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Clean up after previous tests. This also swallows the message sent by Init
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // should start with these.
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WaitForMessages();
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(ClearListeners());
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarDictionary dictionary;
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("bar"), pp::Var(kTestString));
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("def"), pp::Var());
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::stringstream ss;
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ss << dictionary.GetKeys().GetLength();
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string length_as_string(ss.str());
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Have the listener test some properties of the Dictionary.
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<std::string> properties_to_check;
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  properties_to_check.push_back(
51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "message_event.data.constructor.name === 'Object'");
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  properties_to_check.push_back(
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string("Object.keys(message_event.data).length === ") +
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      length_as_string);
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary,
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                properties_to_check));
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set up the JavaScript message event listener to echo the data part of the
52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // message event back to us.
52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
52290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  message_data_.clear();
52390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  instance_->PostMessage(dictionary);
52490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // PostMessage is asynchronous, so we should not receive a response yet.
52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
52790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_dictionary());
52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
52990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  message_data_.clear();
53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(ClearListeners());
53290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PASS();
53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string TestPostMessage::TestSendingComplexVar() {
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Clean up after previous tests. This also swallows the message sent by Init
53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // should start with these.
54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WaitForMessages();
5417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  message_data_.clear();
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(ClearListeners());
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pp::Var string(kTestString);
545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarDictionary dictionary;
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("bar"), string);
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("def"), pp::Var());
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference to array.
552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarArray array;
55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(0, pp::Var(kTestBool));
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(1, string);
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Purposely leave index 2 empty (which will place an undefined var there).
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(3, pp::Var(kTestInt));
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  array.Set(4, pp::Var(kTestDouble));
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("array-ref1"), array);
56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Set(pp::Var("array-ref2"), array);
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set up the JavaScript message event listener to echo the data part of the
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // message event back to us.
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  instance_->PostMessage(dictionary);
56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // PostMessage is asynchronous, so we should not receive a response yet.
56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_dictionary());
570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarDictionary result(message_data_.back());
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  WaitForMessages();
5747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  message_data_.clear();
5757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Set up a (dictionary -> array -> dictionary) cycle. Cycles shouldn't be
5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // transmitted.
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarArray array2;
5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  array2.Set(0, dictionary);
5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  dictionary.Set(pp::Var("array2"), array2);
5827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
5847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  instance_->PostMessage(dictionary);
5857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // PostMessage is asynchronous, so we should not receive a response yet.
5867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 0);
5887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Break the cycles.
59090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  dictionary.Delete(pp::Var("array2"));
59190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  WaitForMessages();
5937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  message_data_.clear();
5947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
5957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Test sending a cycle from JavaScript to the plugin.
5977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
5987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PostMessageFromJavaScript("function() { var x = []; x[0] = x; return x; }");
5997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
6007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 0);
6017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  WaitForMessages();
60390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  message_data_.clear();
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(ClearListeners());
60590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PASS();
60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestMessageEvent() {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up the JavaScript message event listener to pass us some values from
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the MessageEvent and make sure they match our expectations.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForMessages();
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Have the listener pass back the class name of message_event and make sure
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's "MessageEvent".
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.constructor.name"));
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestInt));
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_string());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.back().AsString(), "MessageEvent");
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure all the non-data properties have the expected values.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = AddEchoingListener("((message_event.origin === '')"
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   " && (message_event.lastEventId === '')"
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   " && (message_event.source === null)"
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   " && (message_event.ports.length === 0)"
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   " && (message_event.bubbles === false)"
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   " && (message_event.cancelable === false)"
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   ")");
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(success);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestInt));
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 1);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().is_bool());
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.back().AsBool());
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add some event handlers to make sure they receive messages.
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("1"));
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("2"));
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("3"));
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var(kTestInt));
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we don't get a response in a re-entrant fashion.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should get 3 messages.
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 3);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy to a vector of doubles and sort; w3c does not specify the order for
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event listeners. (Copying is easier than writing an operator< for pp::Var.)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VarVector::iterator iter(message_data_.begin()), the_end(message_data_.end());
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<double> double_vec;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; iter != the_end; ++iter) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(iter->is_number());
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double_vec.push_back(iter->AsDouble());
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(double_vec.begin(), double_vec.end());
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_DOUBLE_EQ(double_vec[0], 1.0);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_DOUBLE_EQ(double_vec[1], 2.0);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_DOUBLE_EQ(double_vec[2], 3.0);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestNoHandler() {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete any lingering messages and event listeners.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForMessages();
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now send a message.  We shouldn't get a response.
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var());
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 0);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.empty());
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestExtraParam() {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete any lingering messages and event listeners.
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForMessages();
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a listener that will respond with 1 and an empty array (where the
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message port array would appear if it was Worker postMessage).
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("1, []"));
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now send a message.  We shouldn't get a response.
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_->PostMessage(pp::Var());
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), 0);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(message_data_.empty());
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestPostMessage::TestNonMainThread() {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForMessages();
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AddEchoingListener("message_event.data"));
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up a thread for each integer from 0 to (kThreadsToRun - 1).  Make each
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread send the number that matches its index kMessagesToSendPerThread
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // times.  For good measure, call postMessage from the main thread
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kMessagesToSendPerThread times. At the end, we make sure we got all the
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values we expected.
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_ThreadType threads[kThreadsToRun];
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32_t i = 0; i < kThreadsToRun; ++i) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up a thread to send a value of i.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg = new InvokePostMessageThreadArg(instance_, pp::Var(i));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_CreateThread(&threads[i], &InvokePostMessageThreadFunc, arg);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke PostMessage right now to send a value of (kThreadsToRun).
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance_->PostMessage(pp::Var(kThreadsToRun));
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now join all threads.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32_t i = 0; i < kThreadsToRun; ++i)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_JoinThread(threads[i]);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PostMessage is asynchronous, so we should not receive a response yet.
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(message_data_.size(), 0);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we got all values that we expected.  Note that because it's legal
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the JavaScript engine to treat our integers as floating points, we
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't just use std::find or equality comparison. So we instead, we convert
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // each incoming value to an integer, and count them in received_counts.
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t expected_num = (kThreadsToRun + 1) * kMessagesToSendPerThread;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Count how many we receive per-index.
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int32_t> expected_counts(kThreadsToRun + 1,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       kMessagesToSendPerThread);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int32_t> received_counts(kThreadsToRun + 1, 0);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WaitForMessages(), expected_num);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32_t i = 0; i < expected_num; ++i) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const pp::Var& latest_var(message_data_[i]);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(latest_var.is_int() || latest_var.is_double());
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t received_value = -1;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (latest_var.is_int()) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      received_value = latest_var.AsInt();
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (latest_var.is_double()) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      received_value = static_cast<int32_t>(latest_var.AsDouble() + 0.5);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(received_value >= 0);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(received_value <= kThreadsToRun);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++received_counts[received_value];
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(received_counts, expected_counts);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_data_.clear();
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ClearListeners());
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
766