Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / ppapi / tests / test_post_message.cc
blob5cd42003332c8d62b3268b2e2b2b0219f9077c97
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/tests/test_post_message.h"
7 #include <string.h>
8 #include <algorithm>
9 #include <map>
10 #include <sstream>
12 #include "ppapi/c/pp_var.h"
13 #include "ppapi/c/ppb_file_io.h"
14 #include "ppapi/cpp/dev/var_resource_dev.h"
15 #include "ppapi/cpp/file_io.h"
16 #include "ppapi/cpp/file_ref.h"
17 #include "ppapi/cpp/file_system.h"
18 #include "ppapi/cpp/instance.h"
19 #include "ppapi/cpp/var.h"
20 #include "ppapi/cpp/var_array.h"
21 #include "ppapi/cpp/var_array_buffer.h"
22 #include "ppapi/cpp/var_dictionary.h"
23 #include "ppapi/tests/pp_thread.h"
24 #include "ppapi/tests/test_utils.h"
25 #include "ppapi/tests/testing_instance.h"
27 // Windows defines 'PostMessage', so we have to undef it.
28 #ifdef PostMessage
29 #undef PostMessage
30 #endif
32 REGISTER_TEST_CASE(PostMessage);
34 namespace {
36 const char kTestFilename[] = "testfile.txt";
37 const char kTestString[] = "Hello world!";
38 const bool kTestBool = true;
39 const int32_t kTestInt = 42;
40 const double kTestDouble = 42.0;
42 // On Windows XP bots, the NonMainThread test can run very slowly. So we dial
43 // back the number of threads & messages when running on Windows.
44 #ifdef PPAPI_OS_WIN
45 const int32_t kThreadsToRun = 2;
46 const int32_t kMessagesToSendPerThread = 5;
47 #else
48 const int32_t kThreadsToRun = 4;
49 const int32_t kMessagesToSendPerThread = 10;
50 #endif
52 // The struct that invoke_post_message_thread_func expects for its argument.
53 // It includes the instance on which to invoke PostMessage, and the value to
54 // pass to PostMessage.
55 struct InvokePostMessageThreadArg {
56 InvokePostMessageThreadArg(pp::Instance* i, const pp::Var& v)
57 : instance(i), value_to_send(v) {}
58 pp::Instance* instance;
59 pp::Var value_to_send;
62 void InvokePostMessageThreadFunc(void* user_data) {
63 InvokePostMessageThreadArg* arg =
64 static_cast<InvokePostMessageThreadArg*>(user_data);
65 for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
66 arg->instance->PostMessage(arg->value_to_send);
67 delete arg;
70 // TODO(raymes): Consider putting something like this into pp::Var.
71 bool VarsEqual(const pp::Var& expected,
72 const pp::Var& actual,
73 std::map<int64_t, int64_t>* visited_ids) {
74 if (expected.pp_var().type != actual.pp_var().type) {
75 if (!expected.is_number() && !actual.is_number())
76 return false;
78 // TODO(raymes): Implement a pp::Var::IsRefCounted() function.
79 if (expected.pp_var().type > PP_VARTYPE_DOUBLE) {
80 std::map<int64_t, int64_t>::const_iterator it =
81 visited_ids->find(expected.pp_var().value.as_id);
82 if (it != visited_ids->end()) {
83 if (it->second == actual.pp_var().value.as_id)
84 return true;
85 return false;
87 (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id;
90 if (expected.is_number()) {
91 return fabs(expected.AsDouble() - actual.AsDouble()) < 1.0e-4;
92 } else if (expected.is_array()) {
93 pp::VarArray expected_array(expected);
94 pp::VarArray actual_array(actual);
95 if (expected_array.GetLength() != actual_array.GetLength())
96 return false;
97 for (uint32_t i = 0; i < expected_array.GetLength(); ++i) {
98 if (!VarsEqual(expected_array.Get(i), actual_array.Get(i), visited_ids))
99 return false;
101 return true;
102 } else if (expected.is_dictionary()) {
103 pp::VarDictionary expected_dict(expected);
104 pp::VarDictionary actual_dict(actual);
105 if (expected_dict.GetKeys().GetLength() !=
106 actual_dict.GetKeys().GetLength()) {
107 return false;
109 for (uint32_t i = 0; i < expected_dict.GetKeys().GetLength(); ++i) {
110 pp::Var key = expected_dict.GetKeys().Get(i);
111 if (!actual_dict.HasKey(key))
112 return false;
113 if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids))
114 return false;
116 return true;
117 } else {
118 return expected == actual;
122 bool VarsEqual(const pp::Var& expected,
123 const pp::Var& actual) {
124 std::map<int64_t, int64_t> visited_ids;
125 return VarsEqual(expected, actual, &visited_ids);
128 class ScopedArrayBufferSizeSetter {
129 public:
130 ScopedArrayBufferSizeSetter(const PPB_Testing_Private* interface,
131 PP_Instance instance,
132 uint32_t threshold)
133 : interface_(interface),
134 instance_(instance) {
135 interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold);
137 ~ScopedArrayBufferSizeSetter() {
138 interface_->SetMinimumArrayBufferSizeForShmem(instance_, 0);
140 private:
141 const PPB_Testing_Private* interface_;
142 PP_Instance instance_;
145 #define FINISHED_WAITING_MESSAGE "TEST_POST_MESSAGE_FINISHED_WAITING"
147 } // namespace
149 TestPostMessage::TestPostMessage(TestingInstance* instance)
150 : TestCase(instance) {
153 TestPostMessage::~TestPostMessage() {
154 instance_->PostMessage(pp::Var("This isn't guaranteed to be received, but "
155 "shouldn't cause a crash."));
157 // Remove the special listener that only responds to a FINISHED_WAITING
158 // string. See Init for where it gets added.
159 std::string js_code;
160 js_code += "var plugin = document.getElementById('plugin');"
161 "plugin.removeEventListener('message',"
162 " plugin.wait_for_messages_handler);"
163 "delete plugin.wait_for_messages_handler;";
164 instance_->EvalScript(js_code);
167 bool TestPostMessage::Init() {
168 bool success = CheckTestingInterface();
170 // Set up a special listener that only responds to a FINISHED_WAITING string.
171 // This is for use by WaitForMessages.
172 std::string js_code;
173 // Note the following code is dependent on some features of test_case.html.
174 // E.g., it is assumed that the DOM element where the plugin is embedded has
175 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
176 // us to ignore the messages that are intended for use by the testing
177 // framework itself.
178 js_code += "var plugin = document.getElementById('plugin');"
179 "var wait_for_messages_handler = function(message_event) {"
180 " if (!IsTestingMessage(message_event.data) &&"
181 " message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
182 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
183 " }"
184 "};"
185 "plugin.addEventListener('message', wait_for_messages_handler);"
186 // Stash it on the plugin so we can remove it in the destructor.
187 "plugin.wait_for_messages_handler = wait_for_messages_handler;";
188 instance_->EvalScript(js_code);
190 // Set up the JavaScript message event listener to echo the data part of the
191 // message event back to us.
192 success = success && AddEchoingListener("message_event.data");
193 message_data_.clear();
194 // Send a message that the first test will expect to receive. This is to
195 // verify that we can send messages when the 'Instance::Init' function is on
196 // the stack.
197 instance_->PostMessage(pp::Var(kTestString));
199 return success;
202 void TestPostMessage::RunTests(const std::string& filter) {
203 // Note: SendInInit must be first, because it expects to receive a message
204 // that was sent in Init above.
205 RUN_TEST(SendInInit, filter);
206 RUN_TEST(SendingData, filter);
207 RUN_TEST(SendingArrayBuffer, filter);
208 RUN_TEST(SendingArray, filter);
209 RUN_TEST(SendingDictionary, filter);
210 RUN_TEST(SendingResource, filter);
211 RUN_TEST(SendingComplexVar, filter);
212 RUN_TEST(MessageEvent, filter);
213 RUN_TEST(NoHandler, filter);
214 RUN_TEST(ExtraParam, filter);
215 if (testing_interface_->IsOutOfProcess())
216 RUN_TEST(NonMainThread, filter);
219 void TestPostMessage::HandleMessage(const pp::Var& message_data) {
220 if (message_data.is_string() &&
221 (message_data.AsString() == FINISHED_WAITING_MESSAGE))
222 testing_interface_->QuitMessageLoop(instance_->pp_instance());
223 else
224 message_data_.push_back(message_data);
227 bool TestPostMessage::AddEchoingListener(const std::string& expression) {
228 std::string js_code;
229 // Note the following code is dependent on some features of test_case.html.
230 // E.g., it is assumed that the DOM element where the plugin is embedded has
231 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
232 // us to ignore the messages that are intended for use by the testing
233 // framework itself.
234 js_code += "var plugin = document.getElementById('plugin');"
235 "var message_handler = function(message_event) {"
236 " if (!IsTestingMessage(message_event.data) &&"
237 " !(message_event.data === '" FINISHED_WAITING_MESSAGE "')) {"
238 " plugin.postMessage(";
239 js_code += expression;
240 js_code += " );"
241 " }"
242 "};"
243 "plugin.addEventListener('message', message_handler);"
244 // Maintain an array of all event listeners, attached to the
245 // plugin. This is so that we can easily remove them later (see
246 // ClearListeners()).
247 "if (!plugin.eventListeners) plugin.eventListeners = [];"
248 "plugin.eventListeners.push(message_handler);";
249 instance_->EvalScript(js_code);
250 return true;
253 bool TestPostMessage::PostMessageFromJavaScript(const std::string& func) {
254 std::string js_code;
255 js_code += "var plugin = document.getElementById('plugin');"
256 "plugin.postMessage(";
257 js_code += func + "()";
258 js_code += " );";
259 instance_->EvalScript(js_code);
260 return true;
263 bool TestPostMessage::ClearListeners() {
264 std::string js_code;
265 js_code += "var plugin = document.getElementById('plugin');"
266 "while (plugin.eventListeners.length) {"
267 " plugin.removeEventListener('message',"
268 " plugin.eventListeners.pop());"
269 "}";
270 instance_->EvalScript(js_code);
271 return true;
274 int TestPostMessage::WaitForMessages() {
275 size_t message_size_before = message_data_.size();
276 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to
277 // come back _after_ any other incoming messages that were already pending.
278 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
279 testing_interface_->RunMessageLoop(instance_->pp_instance());
280 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know
281 // that all pending messages have been slurped up. Return the number we
282 // received (which may be zero).
283 return message_data_.size() - message_size_before;
286 int TestPostMessage::PostAsyncMessageFromJavaScriptAndWait(
287 const std::string& func) {
288 // After the |func| calls callback, post both the given |message|, as well as
289 // the special message FINISHED_WAITING_MESSAGE. This ensures that
290 // RunMessageLoop correctly waits until the callback is called.
291 std::string js_code;
292 js_code += "var plugin = document.getElementById('plugin');"
293 "var callback = function(message) {"
294 " plugin.postMessage(message);"
295 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
296 "};";
297 js_code += "(" + func + ")(callback);";
298 instance_->EvalScript(js_code);
300 size_t message_size_before = message_data_.size();
301 // Unlike WaitForMessages, we do not post FINISHED_WAITING_MESSAGE. This is
302 // because the above JavaScript code will post it for us, when the
303 // asynchronous operation completes.
304 testing_interface_->RunMessageLoop(instance_->pp_instance());
305 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know
306 // that all pending messages have been slurped up. Return the number we
307 // received (which may be zero).
308 return message_data_.size() - message_size_before;
311 std::string TestPostMessage::CheckMessageProperties(
312 const pp::Var& test_data,
313 const std::vector<std::string>& properties_to_check) {
314 typedef std::vector<std::string>::const_iterator Iterator;
315 for (Iterator iter = properties_to_check.begin();
316 iter != properties_to_check.end();
317 ++iter) {
318 ASSERT_TRUE(AddEchoingListener(*iter));
319 message_data_.clear();
320 instance_->PostMessage(test_data);
321 ASSERT_EQ(message_data_.size(), 0);
322 ASSERT_EQ(WaitForMessages(), 1);
323 ASSERT_TRUE(message_data_.back().is_bool());
324 if (!message_data_.back().AsBool())
325 return std::string("Failed: ") + *iter;
326 ASSERT_TRUE(message_data_.back().AsBool());
327 ASSERT_TRUE(ClearListeners());
329 PASS();
332 std::string TestPostMessage::TestSendInInit() {
333 ASSERT_EQ(WaitForMessages(), 1);
334 // This test assumes Init already sent a message.
335 ASSERT_EQ(message_data_.size(), 1);
336 ASSERT_TRUE(message_data_.back().is_string());
337 ASSERT_EQ(message_data_.back().AsString(), kTestString);
338 message_data_.clear();
339 PASS();
342 std::string TestPostMessage::TestSendingData() {
343 // Clean up after previous tests. This also swallows the message sent by Init
344 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
345 // should start with these.
346 WaitForMessages();
347 ASSERT_TRUE(ClearListeners());
348 // Set up the JavaScript message event listener to echo the data part of the
349 // message event back to us.
350 ASSERT_TRUE(AddEchoingListener("message_event.data"));
352 // Test sending a message to JavaScript for each supported type. The JS sends
353 // the data back to us, and we check that they match.
354 message_data_.clear();
355 instance_->PostMessage(pp::Var(kTestString));
356 // PostMessage is asynchronous, so we should not receive a response yet.
357 ASSERT_EQ(message_data_.size(), 0);
358 ASSERT_EQ(WaitForMessages(), 1);
359 ASSERT_TRUE(message_data_.back().is_string());
360 ASSERT_EQ(message_data_.back().AsString(), kTestString);
362 message_data_.clear();
363 instance_->PostMessage(pp::Var(kTestBool));
364 ASSERT_EQ(message_data_.size(), 0);
365 ASSERT_EQ(WaitForMessages(), 1);
366 ASSERT_TRUE(message_data_.back().is_bool());
367 ASSERT_EQ(message_data_.back().AsBool(), kTestBool);
369 message_data_.clear();
370 instance_->PostMessage(pp::Var(kTestInt));
371 ASSERT_EQ(message_data_.size(), 0);
372 ASSERT_EQ(WaitForMessages(), 1);
373 ASSERT_TRUE(message_data_.back().is_number());
374 ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(),
375 static_cast<double>(kTestInt));
377 message_data_.clear();
378 instance_->PostMessage(pp::Var(kTestDouble));
379 ASSERT_EQ(message_data_.size(), 0);
380 ASSERT_EQ(WaitForMessages(), 1);
381 ASSERT_TRUE(message_data_.back().is_number());
382 ASSERT_DOUBLE_EQ(message_data_.back().AsDouble(), kTestDouble);
384 message_data_.clear();
385 instance_->PostMessage(pp::Var());
386 ASSERT_EQ(message_data_.size(), 0);
387 ASSERT_EQ(WaitForMessages(), 1);
388 ASSERT_TRUE(message_data_.back().is_undefined());
390 message_data_.clear();
391 instance_->PostMessage(pp::Var(pp::Var::Null()));
392 ASSERT_EQ(message_data_.size(), 0);
393 ASSERT_EQ(WaitForMessages(), 1);
394 ASSERT_TRUE(message_data_.back().is_null());
396 message_data_.clear();
397 ASSERT_TRUE(ClearListeners());
399 PASS();
402 std::string TestPostMessage::TestSendingArrayBuffer() {
403 // Clean up after previous tests. This also swallows the message sent by Init
404 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
405 // should start with these.
406 WaitForMessages();
407 ASSERT_TRUE(ClearListeners());
409 // TODO(sehr,dmichael): Add testing of longer array buffers when
410 // crbug.com/110086 is fixed.
411 ScopedArrayBufferSizeSetter setter(testing_interface_,
412 instance_->pp_instance(),
413 200);
414 uint32_t sizes[] = { 0, 100, 1000, 10000 };
415 for (size_t i = 0; i < sizeof(sizes)/sizeof(sizes[i]); ++i) {
416 std::ostringstream size_stream;
417 size_stream << sizes[i];
418 const std::string kSizeAsString(size_stream.str());
420 // Create an appropriately sized array buffer with test_data[i] == i.
421 pp::VarArrayBuffer test_data(sizes[i]);
422 if (sizes[i] > 0)
423 ASSERT_NE(NULL, test_data.Map());
424 // Make sure we can Unmap/Map successfully (there's not really any way to
425 // detect if it's unmapped, so we just re-map before getting the pointer to
426 // the buffer).
427 test_data.Unmap();
428 test_data.Map();
429 ASSERT_EQ(sizes[i], test_data.ByteLength());
430 unsigned char* buff = static_cast<unsigned char*>(test_data.Map());
431 const uint32_t kByteLength = test_data.ByteLength();
432 for (size_t j = 0; j < kByteLength; ++j)
433 buff[j] = static_cast<uint8_t>(j % 256u);
435 // Have the listener test some properties of the ArrayBuffer.
436 std::vector<std::string> properties_to_check;
437 properties_to_check.push_back(
438 "message_event.data.constructor.name === 'ArrayBuffer'");
439 properties_to_check.push_back(
440 std::string("message_event.data.byteLength === ") + kSizeAsString);
441 if (sizes[i] > 0) {
442 properties_to_check.push_back(
443 "(new DataView(message_event.data)).getUint8(0) == 0");
444 // Checks that the last element has the right value: (byteLength-1)%256.
445 std::string received_byte("(new DataView(message_event.data)).getUint8("
446 " message_event.data.byteLength-1)");
447 std::string expected_byte("(message_event.data.byteLength-1)%256");
448 properties_to_check.push_back(received_byte + " == " + expected_byte);
450 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(test_data,
451 properties_to_check));
453 // Set up the JavaScript message event listener to echo the data part of the
454 // message event back to us.
455 ASSERT_TRUE(AddEchoingListener("message_event.data"));
456 message_data_.clear();
457 instance_->PostMessage(test_data);
458 // PostMessage is asynchronous, so we should not receive a response yet.
459 ASSERT_EQ(message_data_.size(), 0);
460 ASSERT_EQ(WaitForMessages(), 1);
461 ASSERT_TRUE(message_data_.back().is_array_buffer());
462 pp::VarArrayBuffer received(message_data_.back());
463 message_data_.clear();
464 ASSERT_EQ(test_data.ByteLength(), received.ByteLength());
465 unsigned char* received_buff = static_cast<unsigned char*>(received.Map());
466 // The buffer should be copied, so this should be a distinct buffer. When
467 // 'transferrables' are implemented for PPAPI, we'll also want to test that
468 // we get the _same_ buffer back when it's transferred.
469 if (sizes[i] > 0)
470 ASSERT_NE(buff, received_buff);
471 for (size_t i = 0; i < test_data.ByteLength(); ++i)
472 ASSERT_EQ(buff[i], received_buff[i]);
474 message_data_.clear();
475 ASSERT_TRUE(ClearListeners());
478 PASS();
481 std::string TestPostMessage::TestSendingArray() {
482 // Clean up after previous tests. This also swallows the message sent by Init
483 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
484 // should start with these.
485 WaitForMessages();
486 ASSERT_TRUE(ClearListeners());
488 pp::VarArray array;
489 array.Set(0, pp::Var(kTestBool));
490 array.Set(1, pp::Var(kTestString));
491 // Purposely leave index 2 empty.
492 array.Set(3, pp::Var(kTestInt));
493 array.Set(4, pp::Var(kTestDouble));
495 std::stringstream ss;
496 ss << array.GetLength();
497 std::string length_as_string(ss.str());
499 // Have the listener test some properties of the Array.
500 std::vector<std::string> properties_to_check;
501 properties_to_check.push_back(
502 "message_event.data.constructor.name === 'Array'");
503 properties_to_check.push_back(
504 std::string("message_event.data.length === ") + length_as_string);
505 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(array, properties_to_check));
507 // Set up the JavaScript message event listener to echo the data part of the
508 // message event back to us.
509 ASSERT_TRUE(AddEchoingListener("message_event.data"));
510 message_data_.clear();
511 instance_->PostMessage(array);
512 // PostMessage is asynchronous, so we should not receive a response yet.
513 ASSERT_EQ(message_data_.size(), 0);
514 ASSERT_EQ(WaitForMessages(), 1);
515 ASSERT_TRUE(message_data_.back().is_array());
516 ASSERT_TRUE(VarsEqual(array, message_data_.back()));
518 message_data_.clear();
519 ASSERT_TRUE(ClearListeners());
521 PASS();
524 std::string TestPostMessage::TestSendingDictionary() {
525 // Clean up after previous tests. This also swallows the message sent by Init
526 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
527 // should start with these.
528 WaitForMessages();
529 ASSERT_TRUE(ClearListeners());
531 pp::VarDictionary dictionary;
532 dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
533 dictionary.Set(pp::Var("bar"), pp::Var(kTestString));
534 dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
535 dictionary.Set(pp::Var("def"), pp::Var());
537 std::stringstream ss;
538 ss << dictionary.GetKeys().GetLength();
539 std::string length_as_string(ss.str());
541 // Have the listener test some properties of the Dictionary.
542 std::vector<std::string> properties_to_check;
543 properties_to_check.push_back(
544 "message_event.data.constructor.name === 'Object'");
545 properties_to_check.push_back(
546 std::string("Object.keys(message_event.data).length === ") +
547 length_as_string);
548 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary,
549 properties_to_check));
551 // Set up the JavaScript message event listener to echo the data part of the
552 // message event back to us.
553 ASSERT_TRUE(AddEchoingListener("message_event.data"));
554 message_data_.clear();
555 instance_->PostMessage(dictionary);
556 // PostMessage is asynchronous, so we should not receive a response yet.
557 ASSERT_EQ(message_data_.size(), 0);
558 ASSERT_EQ(WaitForMessages(), 1);
559 ASSERT_TRUE(message_data_.back().is_dictionary());
560 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
562 message_data_.clear();
563 ASSERT_TRUE(ClearListeners());
565 PASS();
568 std::string TestPostMessage::TestSendingResource() {
569 // Clean up after previous tests. This also swallows the message sent by Init
570 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
571 // should start with these.
572 WaitForMessages();
573 message_data_.clear();
574 ASSERT_TRUE(ClearListeners());
576 // Test sending a DOMFileSystem from JavaScript to the plugin.
577 // This opens a real (temporary) file using the HTML5 FileSystem API and
578 // writes to it.
579 ASSERT_TRUE(AddEchoingListener("message_event.data"));
580 ASSERT_EQ(message_data_.size(), 0);
581 std::string js_code =
582 "function(callback) {"
583 " window.webkitRequestFileSystem(window.TEMPORARY, 1024,"
584 " function(fileSystem) {"
585 " fileSystem.root.getFile('";
586 js_code += kTestFilename;
587 js_code += "', {create: true}, function(tempFile) {"
588 " tempFile.createWriter(function(writer) {"
589 " writer.onerror = function() { callback(null); };"
590 " writer.onwriteend = function() { callback(fileSystem); };"
591 " var blob = new Blob(['";
592 js_code += kTestString;
593 js_code += "'], {'type': 'text/plain'});"
594 " writer.write(blob);"
595 " });"
596 " }, function() { callback(null); });"
597 " }, function() { callback(null); });"
598 "}";
599 ASSERT_EQ(PostAsyncMessageFromJavaScriptAndWait(js_code), 1);
600 pp::Var var = message_data_.back();
601 ASSERT_TRUE(var.is_resource());
602 pp::VarResource_Dev var_resource(var);
603 pp::Resource result = var_resource.AsResource();
604 ASSERT_TRUE(pp::FileSystem::IsFileSystem(result));
606 pp::FileSystem file_system(result);
607 std::string file_path("/");
608 file_path += kTestFilename;
609 pp::FileRef file_ref(file_system, file_path.c_str());
610 ASSERT_NE(0, file_ref.pp_resource());
612 // Ensure that the file can be queried.
613 TestCompletionCallbackWithOutput<PP_FileInfo> cc(instance_->pp_instance(),
614 callback_type());
615 cc.WaitForResult(file_ref.Query(cc.GetCallback()));
616 CHECK_CALLBACK_BEHAVIOR(cc);
617 ASSERT_EQ(PP_OK, cc.result());
619 // Read the file and test that its contents match.
620 pp::FileIO file_io(instance_);
621 ASSERT_NE(0, file_io.pp_resource());
622 TestCompletionCallback callback(instance_->pp_instance(),
623 callback_type());
624 callback.WaitForResult(
625 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, callback.GetCallback()));
626 CHECK_CALLBACK_BEHAVIOR(callback);
627 ASSERT_EQ(PP_OK, callback.result());
629 int length = strlen(kTestString);
630 std::vector<char> buffer_vector(length);
631 char* buffer = &buffer_vector[0]; // Note: Not null-terminated!
632 callback.WaitForResult(
633 file_io.Read(0, buffer, length, callback.GetCallback()));
634 CHECK_CALLBACK_BEHAVIOR(callback);
635 ASSERT_EQ(length, callback.result());
636 ASSERT_EQ(0, memcmp(buffer, kTestString, length));
639 WaitForMessages();
640 message_data_.clear();
641 ASSERT_TRUE(ClearListeners());
643 // TODO(mgiuca): Test roundtrip from plugin to JS and back, when the plugin to
644 // JS support is available.
646 PASS();
649 std::string TestPostMessage::TestSendingComplexVar() {
650 // Clean up after previous tests. This also swallows the message sent by Init
651 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
652 // should start with these.
653 WaitForMessages();
654 message_data_.clear();
655 ASSERT_TRUE(ClearListeners());
657 pp::Var string(kTestString);
658 pp::VarDictionary dictionary;
659 dictionary.Set(pp::Var("foo"), pp::Var(kTestBool));
660 dictionary.Set(pp::Var("bar"), string);
661 dictionary.Set(pp::Var("abc"), pp::Var(kTestInt));
662 dictionary.Set(pp::Var("def"), pp::Var());
664 // Reference to array.
665 pp::VarArray array;
666 array.Set(0, pp::Var(kTestBool));
667 array.Set(1, string);
668 // Purposely leave index 2 empty (which will place an undefined var there).
669 array.Set(3, pp::Var(kTestInt));
670 array.Set(4, pp::Var(kTestDouble));
672 dictionary.Set(pp::Var("array-ref1"), array);
673 dictionary.Set(pp::Var("array-ref2"), array);
675 // Set up the JavaScript message event listener to echo the data part of the
676 // message event back to us.
677 ASSERT_TRUE(AddEchoingListener("message_event.data"));
678 instance_->PostMessage(dictionary);
679 // PostMessage is asynchronous, so we should not receive a response yet.
680 ASSERT_EQ(message_data_.size(), 0);
681 ASSERT_EQ(WaitForMessages(), 1);
682 ASSERT_TRUE(message_data_.back().is_dictionary());
683 pp::VarDictionary result(message_data_.back());
684 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back()));
686 WaitForMessages();
687 message_data_.clear();
688 ASSERT_TRUE(ClearListeners());
690 // Set up a (dictionary -> array -> dictionary) cycle. Cycles shouldn't be
691 // transmitted.
692 pp::VarArray array2;
693 array2.Set(0, dictionary);
694 dictionary.Set(pp::Var("array2"), array2);
696 ASSERT_TRUE(AddEchoingListener("message_event.data"));
697 instance_->PostMessage(dictionary);
698 // PostMessage is asynchronous, so we should not receive a response yet.
699 ASSERT_EQ(message_data_.size(), 0);
700 ASSERT_EQ(WaitForMessages(), 0);
702 // Break the cycles.
703 dictionary.Delete(pp::Var("array2"));
705 WaitForMessages();
706 message_data_.clear();
707 ASSERT_TRUE(ClearListeners());
709 // Test sending a cycle from JavaScript to the plugin.
710 ASSERT_TRUE(AddEchoingListener("message_event.data"));
711 PostMessageFromJavaScript("function() { var x = []; x[0] = x; return x; }");
712 ASSERT_EQ(message_data_.size(), 0);
713 ASSERT_EQ(WaitForMessages(), 0);
715 WaitForMessages();
716 message_data_.clear();
717 ASSERT_TRUE(ClearListeners());
719 PASS();
722 std::string TestPostMessage::TestMessageEvent() {
723 // Set up the JavaScript message event listener to pass us some values from
724 // the MessageEvent and make sure they match our expectations.
726 WaitForMessages();
727 ASSERT_TRUE(ClearListeners());
728 // Have the listener pass back the class name of message_event and make sure
729 // it's "MessageEvent".
730 ASSERT_TRUE(AddEchoingListener("message_event.constructor.name"));
731 message_data_.clear();
732 instance_->PostMessage(pp::Var(kTestInt));
733 ASSERT_EQ(message_data_.size(), 0);
734 ASSERT_EQ(WaitForMessages(), 1);
735 ASSERT_TRUE(message_data_.back().is_string());
736 ASSERT_EQ(message_data_.back().AsString(), "MessageEvent");
737 ASSERT_TRUE(ClearListeners());
739 // Make sure all the non-data properties have the expected values.
740 bool success = AddEchoingListener("((message_event.origin === '')"
741 " && (message_event.lastEventId === '')"
742 " && (message_event.source === null)"
743 " && (message_event.ports.length === 0)"
744 " && (message_event.bubbles === false)"
745 " && (message_event.cancelable === false)"
746 ")");
747 ASSERT_TRUE(success);
748 message_data_.clear();
749 instance_->PostMessage(pp::Var(kTestInt));
750 ASSERT_EQ(message_data_.size(), 0);
751 ASSERT_EQ(WaitForMessages(), 1);
752 ASSERT_TRUE(message_data_.back().is_bool());
753 ASSERT_TRUE(message_data_.back().AsBool());
754 ASSERT_TRUE(ClearListeners());
756 // Add some event handlers to make sure they receive messages.
757 ASSERT_TRUE(AddEchoingListener("1"));
758 ASSERT_TRUE(AddEchoingListener("2"));
759 ASSERT_TRUE(AddEchoingListener("3"));
761 message_data_.clear();
762 instance_->PostMessage(pp::Var(kTestInt));
763 // Make sure we don't get a response in a re-entrant fashion.
764 ASSERT_EQ(message_data_.size(), 0);
765 // We should get 3 messages.
766 ASSERT_EQ(WaitForMessages(), 3);
767 // Copy to a vector of doubles and sort; w3c does not specify the order for
768 // event listeners. (Copying is easier than writing an operator< for pp::Var.)
770 // See http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html.
771 VarVector::iterator iter(message_data_.begin()), the_end(message_data_.end());
772 std::vector<double> double_vec;
773 for (; iter != the_end; ++iter) {
774 ASSERT_TRUE(iter->is_number());
775 double_vec.push_back(iter->AsDouble());
777 std::sort(double_vec.begin(), double_vec.end());
778 ASSERT_DOUBLE_EQ(double_vec[0], 1.0);
779 ASSERT_DOUBLE_EQ(double_vec[1], 2.0);
780 ASSERT_DOUBLE_EQ(double_vec[2], 3.0);
782 message_data_.clear();
783 ASSERT_TRUE(ClearListeners());
785 PASS();
788 std::string TestPostMessage::TestNoHandler() {
789 // Delete any lingering messages and event listeners.
790 WaitForMessages();
791 ASSERT_TRUE(ClearListeners());
793 // Now send a message. We shouldn't get a response.
794 message_data_.clear();
795 instance_->PostMessage(pp::Var());
796 ASSERT_EQ(WaitForMessages(), 0);
797 ASSERT_TRUE(message_data_.empty());
799 PASS();
802 std::string TestPostMessage::TestExtraParam() {
803 // Delete any lingering messages and event listeners.
804 WaitForMessages();
805 ASSERT_TRUE(ClearListeners());
806 // Add a listener that will respond with 1 and an empty array (where the
807 // message port array would appear if it was Worker postMessage).
808 ASSERT_TRUE(AddEchoingListener("1, []"));
810 // Now send a message. We shouldn't get a response.
811 message_data_.clear();
812 instance_->PostMessage(pp::Var());
813 ASSERT_EQ(WaitForMessages(), 0);
814 ASSERT_TRUE(message_data_.empty());
816 ASSERT_TRUE(ClearListeners());
818 PASS();
821 std::string TestPostMessage::TestNonMainThread() {
822 WaitForMessages();
823 ASSERT_TRUE(ClearListeners());
824 ASSERT_TRUE(AddEchoingListener("message_event.data"));
825 message_data_.clear();
827 // Set up a thread for each integer from 0 to (kThreadsToRun - 1). Make each
828 // thread send the number that matches its index kMessagesToSendPerThread
829 // times. For good measure, call postMessage from the main thread
830 // kMessagesToSendPerThread times. At the end, we make sure we got all the
831 // values we expected.
832 PP_ThreadType threads[kThreadsToRun];
833 for (int32_t i = 0; i < kThreadsToRun; ++i) {
834 // Set up a thread to send a value of i.
835 void* arg = new InvokePostMessageThreadArg(instance_, pp::Var(i));
836 PP_CreateThread(&threads[i], &InvokePostMessageThreadFunc, arg);
838 // Invoke PostMessage right now to send a value of (kThreadsToRun).
839 for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
840 instance_->PostMessage(pp::Var(kThreadsToRun));
842 // Now join all threads.
843 for (int32_t i = 0; i < kThreadsToRun; ++i)
844 PP_JoinThread(threads[i]);
846 // PostMessage is asynchronous, so we should not receive a response yet.
847 ASSERT_EQ(message_data_.size(), 0);
849 // Make sure we got all values that we expected. Note that because it's legal
850 // for the JavaScript engine to treat our integers as floating points, we
851 // can't just use std::find or equality comparison. So we instead, we convert
852 // each incoming value to an integer, and count them in received_counts.
853 int32_t expected_num = (kThreadsToRun + 1) * kMessagesToSendPerThread;
854 // Count how many we receive per-index.
855 std::vector<int32_t> expected_counts(kThreadsToRun + 1,
856 kMessagesToSendPerThread);
857 std::vector<int32_t> received_counts(kThreadsToRun + 1, 0);
858 ASSERT_EQ(WaitForMessages(), expected_num);
859 for (int32_t i = 0; i < expected_num; ++i) {
860 const pp::Var& latest_var(message_data_[i]);
861 ASSERT_TRUE(latest_var.is_int() || latest_var.is_double());
862 int32_t received_value = -1;
863 if (latest_var.is_int()) {
864 received_value = latest_var.AsInt();
865 } else if (latest_var.is_double()) {
866 received_value = static_cast<int32_t>(latest_var.AsDouble() + 0.5);
868 ASSERT_TRUE(received_value >= 0);
869 ASSERT_TRUE(received_value <= kThreadsToRun);
870 ++received_counts[received_value];
872 ASSERT_EQ(received_counts, expected_counts);
874 message_data_.clear();
875 ASSERT_TRUE(ClearListeners());
877 PASS();