OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/tests/test_post_message.h" | 5 #include "ppapi/tests/test_post_message.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | |
8 #include <sstream> | 9 #include <sstream> |
9 | 10 |
10 #include "ppapi/c/dev/ppb_testing_dev.h" | 11 #include "ppapi/c/dev/ppb_testing_dev.h" |
11 #include "ppapi/c/pp_var.h" | 12 #include "ppapi/c/pp_var.h" |
12 #include "ppapi/cpp/instance.h" | 13 #include "ppapi/cpp/instance.h" |
13 #include "ppapi/cpp/var.h" | 14 #include "ppapi/cpp/var.h" |
14 #include "ppapi/cpp/var_array_buffer.h" | 15 #include "ppapi/cpp/var_array_buffer.h" |
15 #include "ppapi/tests/pp_thread.h" | 16 #include "ppapi/tests/pp_thread.h" |
16 #include "ppapi/tests/test_utils.h" | 17 #include "ppapi/tests/test_utils.h" |
17 #include "ppapi/tests/testing_instance.h" | 18 #include "ppapi/tests/testing_instance.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 }; | 52 }; |
52 | 53 |
53 void InvokePostMessageThreadFunc(void* user_data) { | 54 void InvokePostMessageThreadFunc(void* user_data) { |
54 InvokePostMessageThreadArg* arg = | 55 InvokePostMessageThreadArg* arg = |
55 static_cast<InvokePostMessageThreadArg*>(user_data); | 56 static_cast<InvokePostMessageThreadArg*>(user_data); |
56 for (int32_t i = 0; i < kMessagesToSendPerThread; ++i) | 57 for (int32_t i = 0; i < kMessagesToSendPerThread; ++i) |
57 arg->instance->PostMessage(arg->value_to_send); | 58 arg->instance->PostMessage(arg->value_to_send); |
58 delete arg; | 59 delete arg; |
59 } | 60 } |
60 | 61 |
62 // TODO(raymes): Consider putting something like this into pp::Var. | |
63 bool VarsEqual(const pp::Var& expected, | |
64 const pp::Var& actual, | |
65 std::map<int64_t, int64_t>* visited_ids) { | |
66 if (expected.pp_var().type != actual.pp_var().type) { | |
67 if (!expected.is_number() && !actual.is_number()) | |
68 return false; | |
69 } | |
70 // TODO(raymes): Implement a pp::Var::IsRefCounted() function. | |
71 if (expected.pp_var().type > PP_VARTYPE_DOUBLE) { | |
72 std::map<int64_t, int64_t>::const_iterator it = | |
73 visited_ids->find(expected.pp_var().value.as_id); | |
74 if (it != visited_ids->end()) { | |
75 if (it->second == actual.pp_var().value.as_id) | |
76 return true; | |
77 return false; | |
78 } | |
79 (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id; | |
80 } | |
81 | |
82 if (expected.is_number()) { | |
83 return fabs(expected.AsDouble() - actual.AsDouble()) < 1.0e-4; | |
84 } else if (expected.is_array()) { | |
85 pp::VarArray_Dev expected_array(expected); | |
86 pp::VarArray_Dev actual_array(actual); | |
87 if (expected_array.GetLength() != actual_array.GetLength()) | |
88 return false; | |
89 for (uint32_t i = 0; i < expected_array.GetLength(); ++i) { | |
90 if (!VarsEqual(expected_array.Get(i), actual_array.Get(i), visited_ids)) | |
91 return false; | |
92 } | |
93 return true; | |
94 } else if (expected.is_dictionary()) { | |
95 pp::VarDictionary_Dev expected_dict(expected); | |
96 pp::VarDictionary_Dev actual_dict(actual); | |
97 if (expected_dict.GetKeys().GetLength() != | |
98 actual_dict.GetKeys().GetLength()) { | |
99 return false; | |
100 } | |
101 for (uint32_t i = 0; i < expected_dict.GetKeys().GetLength(); ++i) { | |
102 pp::Var key = expected_dict.GetKeys().Get(i); | |
103 if (actual_dict.HasKey(key) == PP_FALSE) | |
104 return false; | |
105 if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids)) | |
106 return false; | |
107 } | |
108 return true; | |
109 } else { | |
110 return expected == actual; | |
111 } | |
112 } | |
113 | |
114 bool VarsEqual(const pp::Var& expected, | |
115 const pp::Var& actual) { | |
116 std::map<int64_t, int64_t> visited_ids; | |
117 return VarsEqual(expected, actual, &visited_ids); | |
118 } | |
119 | |
61 class ScopedArrayBufferSizeSetter { | 120 class ScopedArrayBufferSizeSetter { |
62 public: | 121 public: |
63 ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface, | 122 ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface, |
64 PP_Instance instance, | 123 PP_Instance instance, |
65 uint32_t threshold) | 124 uint32_t threshold) |
66 : interface_(interface), | 125 : interface_(interface), |
67 instance_(instance) { | 126 instance_(instance) { |
68 interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold); | 127 interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold); |
69 } | 128 } |
70 ~ScopedArrayBufferSizeSetter() { | 129 ~ScopedArrayBufferSizeSetter() { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 | 187 |
129 return success; | 188 return success; |
130 } | 189 } |
131 | 190 |
132 void TestPostMessage::RunTests(const std::string& filter) { | 191 void TestPostMessage::RunTests(const std::string& filter) { |
133 // Note: SendInInit must be first, because it expects to receive a message | 192 // Note: SendInInit must be first, because it expects to receive a message |
134 // that was sent in Init above. | 193 // that was sent in Init above. |
135 RUN_TEST(SendInInit, filter); | 194 RUN_TEST(SendInInit, filter); |
136 RUN_TEST(SendingData, filter); | 195 RUN_TEST(SendingData, filter); |
137 RUN_TEST(SendingArrayBuffer, filter); | 196 RUN_TEST(SendingArrayBuffer, filter); |
197 RUN_TEST(SendingArray, filter); | |
198 RUN_TEST(SendingDictionary, filter); | |
199 RUN_TEST(SendingComplexVar, filter); | |
138 RUN_TEST(MessageEvent, filter); | 200 RUN_TEST(MessageEvent, filter); |
139 RUN_TEST(NoHandler, filter); | 201 RUN_TEST(NoHandler, filter); |
140 RUN_TEST(ExtraParam, filter); | 202 RUN_TEST(ExtraParam, filter); |
141 if (testing_interface_->IsOutOfProcess()) | 203 if (testing_interface_->IsOutOfProcess()) |
142 RUN_TEST(NonMainThread, filter); | 204 RUN_TEST(NonMainThread, filter); |
143 } | 205 } |
144 | 206 |
145 void TestPostMessage::HandleMessage(const pp::Var& message_data) { | 207 void TestPostMessage::HandleMessage(const pp::Var& message_data) { |
146 if (message_data.is_string() && | 208 if (message_data.is_string() && |
147 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) | 209 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to | 254 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to |
193 // come back _after_ any other incoming messages that were already pending. | 255 // come back _after_ any other incoming messages that were already pending. |
194 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); | 256 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); |
195 testing_interface_->RunMessageLoop(instance_->pp_instance()); | 257 testing_interface_->RunMessageLoop(instance_->pp_instance()); |
196 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know | 258 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know |
197 // that all pending messages have been slurped up. Return the number we | 259 // that all pending messages have been slurped up. Return the number we |
198 // received (which may be zero). | 260 // received (which may be zero). |
199 return message_data_.size() - message_size_before; | 261 return message_data_.size() - message_size_before; |
200 } | 262 } |
201 | 263 |
264 std::string TestPostMessage::CheckMessageProperties( | |
265 const pp::Var& test_data, | |
266 const std::vector<std::string>& properties_to_check) { | |
267 typedef std::vector<std::string>::const_iterator Iterator; | |
268 for (Iterator iter = properties_to_check.begin(); | |
269 iter != properties_to_check.end(); | |
270 ++iter) { | |
271 ASSERT_TRUE(AddEchoingListener(*iter)); | |
272 message_data_.clear(); | |
273 instance_->PostMessage(test_data); | |
274 ASSERT_EQ(message_data_.size(), 0); | |
275 ASSERT_EQ(WaitForMessages(), 1); | |
276 ASSERT_TRUE(message_data_.back().is_bool()); | |
277 if (!message_data_.back().AsBool()) | |
278 return std::string("Failed: ") + *iter; | |
279 ASSERT_TRUE(message_data_.back().AsBool()); | |
280 ASSERT_TRUE(ClearListeners()); | |
281 } | |
282 PASS(); | |
283 } | |
284 | |
202 std::string TestPostMessage::TestSendInInit() { | 285 std::string TestPostMessage::TestSendInInit() { |
203 ASSERT_EQ(WaitForMessages(), 1); | 286 ASSERT_EQ(WaitForMessages(), 1); |
204 // This test assumes Init already sent a message. | 287 // This test assumes Init already sent a message. |
205 ASSERT_EQ(message_data_.size(), 1); | 288 ASSERT_EQ(message_data_.size(), 1); |
206 ASSERT_TRUE(message_data_.back().is_string()); | 289 ASSERT_TRUE(message_data_.back().is_string()); |
207 ASSERT_EQ(message_data_.back().AsString(), kTestString); | 290 ASSERT_EQ(message_data_.back().AsString(), kTestString); |
208 message_data_.clear(); | 291 message_data_.clear(); |
209 PASS(); | 292 PASS(); |
210 } | 293 } |
211 | 294 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 std::string("message_event.data.byteLength === ") + kSizeAsString); | 393 std::string("message_event.data.byteLength === ") + kSizeAsString); |
311 if (sizes[i] > 0) { | 394 if (sizes[i] > 0) { |
312 properties_to_check.push_back( | 395 properties_to_check.push_back( |
313 "(new DataView(message_event.data)).getUint8(0) == 0"); | 396 "(new DataView(message_event.data)).getUint8(0) == 0"); |
314 // Checks that the last element has the right value: (byteLength-1)%256. | 397 // Checks that the last element has the right value: (byteLength-1)%256. |
315 std::string received_byte("(new DataView(message_event.data)).getUint8(" | 398 std::string received_byte("(new DataView(message_event.data)).getUint8(" |
316 " message_event.data.byteLength-1)"); | 399 " message_event.data.byteLength-1)"); |
317 std::string expected_byte("(message_event.data.byteLength-1)%256"); | 400 std::string expected_byte("(message_event.data.byteLength-1)%256"); |
318 properties_to_check.push_back(received_byte + " == " + expected_byte); | 401 properties_to_check.push_back(received_byte + " == " + expected_byte); |
319 } | 402 } |
320 for (std::vector<std::string>::iterator iter = properties_to_check.begin(); | 403 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(test_data, |
321 iter != properties_to_check.end(); | 404 properties_to_check)); |
322 ++iter) { | |
323 ASSERT_TRUE(AddEchoingListener(*iter)); | |
324 message_data_.clear(); | |
325 instance_->PostMessage(test_data); | |
326 ASSERT_EQ(message_data_.size(), 0); | |
327 ASSERT_EQ(WaitForMessages(), 1); | |
328 ASSERT_TRUE(message_data_.back().is_bool()); | |
329 if (!message_data_.back().AsBool()) | |
330 return std::string("Failed: ") + *iter + ", size: " + kSizeAsString; | |
331 ASSERT_TRUE(message_data_.back().AsBool()); | |
332 ASSERT_TRUE(ClearListeners()); | |
333 } | |
334 | 405 |
335 // Set up the JavaScript message event listener to echo the data part of the | 406 // Set up the JavaScript message event listener to echo the data part of the |
336 // message event back to us. | 407 // message event back to us. |
337 ASSERT_TRUE(AddEchoingListener("message_event.data")); | 408 ASSERT_TRUE(AddEchoingListener("message_event.data")); |
338 message_data_.clear(); | 409 message_data_.clear(); |
339 instance_->PostMessage(test_data); | 410 instance_->PostMessage(test_data); |
340 // PostMessage is asynchronous, so we should not receive a response yet. | 411 // PostMessage is asynchronous, so we should not receive a response yet. |
341 ASSERT_EQ(message_data_.size(), 0); | 412 ASSERT_EQ(message_data_.size(), 0); |
342 ASSERT_EQ(WaitForMessages(), 1); | 413 ASSERT_EQ(WaitForMessages(), 1); |
343 ASSERT_TRUE(message_data_.back().is_array_buffer()); | 414 ASSERT_TRUE(message_data_.back().is_array_buffer()); |
344 pp::VarArrayBuffer received(message_data_.back()); | 415 pp::VarArrayBuffer received(message_data_.back()); |
345 message_data_.clear(); | 416 message_data_.clear(); |
346 ASSERT_EQ(test_data.ByteLength(), received.ByteLength()); | 417 ASSERT_EQ(test_data.ByteLength(), received.ByteLength()); |
347 unsigned char* received_buff = static_cast<unsigned char*>(received.Map()); | 418 unsigned char* received_buff = static_cast<unsigned char*>(received.Map()); |
348 // The buffer should be copied, so this should be a distinct buffer. When | 419 // The buffer should be copied, so this should be a distinct buffer. When |
349 // 'transferrables' are implemented for PPAPI, we'll also want to test that | 420 // 'transferrables' are implemented for PPAPI, we'll also want to test that |
350 // we get the _same_ buffer back when it's transferred. | 421 // we get the _same_ buffer back when it's transferred. |
351 if (sizes[i] > 0) | 422 if (sizes[i] > 0) |
352 ASSERT_NE(buff, received_buff); | 423 ASSERT_NE(buff, received_buff); |
353 for (size_t i = 0; i < test_data.ByteLength(); ++i) | 424 for (size_t i = 0; i < test_data.ByteLength(); ++i) |
354 ASSERT_EQ(buff[i], received_buff[i]); | 425 ASSERT_EQ(buff[i], received_buff[i]); |
355 | 426 |
356 message_data_.clear(); | 427 message_data_.clear(); |
357 ASSERT_TRUE(ClearListeners()); | 428 ASSERT_TRUE(ClearListeners()); |
358 } | 429 } |
359 | 430 |
360 PASS(); | 431 PASS(); |
361 } | 432 } |
362 | 433 |
434 std::string TestPostMessage::TestSendingArray() { | |
435 // Clean up after previous tests. This also swallows the message sent by Init | |
436 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
437 // should start with these. | |
438 WaitForMessages(); | |
439 ASSERT_TRUE(ClearListeners()); | |
440 | |
441 pp::VarArray_Dev array; | |
442 array.Set(0, pp::Var(kTestBool)); | |
443 array.Set(1, pp::Var(kTestString)); | |
444 // Purposely leave index 2 empty. | |
445 array.Set(3, pp::Var(kTestInt)); | |
446 array.Set(4, pp::Var(kTestDouble)); | |
447 | |
448 std::stringstream ss; | |
449 ss << array.GetLength(); | |
450 std::string length_as_string(ss.str()); | |
451 | |
452 // Have the listener test some properties of the Array. | |
453 std::vector<std::string> properties_to_check; | |
454 properties_to_check.push_back( | |
455 "message_event.data.constructor.name === 'Array'"); | |
456 properties_to_check.push_back( | |
457 std::string("message_event.data.length === ") + length_as_string); | |
458 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(array, properties_to_check)); | |
459 | |
460 // Set up the JavaScript message event listener to echo the data part of the | |
461 // message event back to us. | |
462 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
463 message_data_.clear(); | |
464 instance_->PostMessage(array); | |
465 // PostMessage is asynchronous, so we should not receive a response yet. | |
466 ASSERT_EQ(message_data_.size(), 0); | |
467 ASSERT_EQ(WaitForMessages(), 1); | |
468 ASSERT_TRUE(message_data_.back().is_array()); | |
469 ASSERT_TRUE(VarsEqual(array, message_data_.back())); | |
470 | |
471 message_data_.clear(); | |
472 ASSERT_TRUE(ClearListeners()); | |
473 | |
474 PASS(); | |
475 } | |
476 | |
477 std::string TestPostMessage::TestSendingDictionary() { | |
478 // Clean up after previous tests. This also swallows the message sent by Init | |
479 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
480 // should start with these. | |
481 WaitForMessages(); | |
482 ASSERT_TRUE(ClearListeners()); | |
483 | |
484 pp::VarDictionary_Dev dictionary; | |
485 dictionary.Set(pp::Var("foo"), pp::Var(kTestBool)); | |
486 dictionary.Set(pp::Var("bar"), pp::Var(kTestString)); | |
487 dictionary.Set(pp::Var("abc"), pp::Var(kTestInt)); | |
488 dictionary.Set(pp::Var("def"), pp::Var()); | |
489 | |
490 std::stringstream ss; | |
491 ss << dictionary.GetKeys().GetLength(); | |
492 std::string length_as_string(ss.str()); | |
493 | |
494 // Have the listener test some properties of the Dictionary. | |
495 std::vector<std::string> properties_to_check; | |
496 properties_to_check.push_back( | |
497 "message_event.data.constructor.name === 'Object'"); | |
498 properties_to_check.push_back( | |
499 std::string("Object.keys(message_event.data).length === ") + | |
500 length_as_string); | |
dmichael (off chromium)
2013/05/13 18:02:26
nit: indentation is off
raymes
2013/05/17 17:39:12
Done.
| |
501 ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary, | |
502 properties_to_check)); | |
503 | |
504 // Set up the JavaScript message event listener to echo the data part of the | |
505 // message event back to us. | |
506 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
507 message_data_.clear(); | |
508 instance_->PostMessage(dictionary); | |
509 // PostMessage is asynchronous, so we should not receive a response yet. | |
510 ASSERT_EQ(message_data_.size(), 0); | |
511 ASSERT_EQ(WaitForMessages(), 1); | |
512 ASSERT_TRUE(message_data_.back().is_dictionary()); | |
513 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); | |
514 | |
515 message_data_.clear(); | |
516 ASSERT_TRUE(ClearListeners()); | |
517 | |
518 PASS(); | |
519 } | |
520 | |
521 std::string TestPostMessage::TestSendingComplexVar() { | |
522 // Clean up after previous tests. This also swallows the message sent by Init | |
523 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
524 // should start with these. | |
525 WaitForMessages(); | |
526 ASSERT_TRUE(ClearListeners()); | |
527 | |
528 pp::Var string(kTestString); | |
529 pp::VarDictionary_Dev dictionary; | |
530 dictionary.Set(pp::Var("foo"), pp::Var(kTestBool)); | |
531 dictionary.Set(pp::Var("bar"), string); | |
532 dictionary.Set(pp::Var("abc"), pp::Var(kTestInt)); | |
533 dictionary.Set(pp::Var("def"), pp::Var()); | |
534 dictionary.Set(pp::Var("dictionary"), dictionary); // Self-reference. | |
535 | |
536 // Reference to array. | |
537 pp::VarArray_Dev array; | |
538 array.Set(0, pp::Var(kTestBool)); | |
539 array.Set(1, string); | |
540 // Purposely leave index 2 empty (which will place an undefined var there). | |
541 array.Set(3, pp::Var(kTestInt)); | |
542 array.Set(4, pp::Var(kTestDouble)); | |
543 | |
544 dictionary.Set(pp::Var("array-ref1"), array); | |
545 dictionary.Set(pp::Var("array-ref2"), array); | |
546 | |
547 // Set up a (dictionary -> array -> dictionary) cycle. | |
548 pp::VarArray_Dev array2; | |
549 array2.Set(0, dictionary); | |
550 dictionary.Set(pp::Var("array2"), array2); | |
551 | |
552 // Set up the JavaScript message event listener to echo the data part of the | |
553 // message event back to us. | |
554 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
555 message_data_.clear(); | |
556 instance_->PostMessage(dictionary); | |
557 // PostMessage is asynchronous, so we should not receive a response yet. | |
558 ASSERT_EQ(message_data_.size(), 0); | |
559 ASSERT_EQ(WaitForMessages(), 1); | |
560 ASSERT_TRUE(message_data_.back().is_dictionary()); | |
561 pp::VarDictionary_Dev result(message_data_.back()); | |
562 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); | |
563 | |
564 // Break the cycles. | |
565 dictionary.Delete(pp::Var("dictionary")); | |
566 dictionary.Delete(pp::Var("array2")); | |
567 result.Delete(pp::Var("dictionary")); | |
568 result.Delete(pp::Var("array2")); | |
569 | |
570 message_data_.clear(); | |
571 ASSERT_TRUE(ClearListeners()); | |
572 | |
573 PASS(); | |
574 } | |
575 | |
363 std::string TestPostMessage::TestMessageEvent() { | 576 std::string TestPostMessage::TestMessageEvent() { |
364 // Set up the JavaScript message event listener to pass us some values from | 577 // Set up the JavaScript message event listener to pass us some values from |
365 // the MessageEvent and make sure they match our expectations. | 578 // the MessageEvent and make sure they match our expectations. |
366 | 579 |
367 WaitForMessages(); | 580 WaitForMessages(); |
368 ASSERT_TRUE(ClearListeners()); | 581 ASSERT_TRUE(ClearListeners()); |
369 // Have the listener pass back the class name of message_event and make sure | 582 // Have the listener pass back the class name of message_event and make sure |
370 // it's "MessageEvent". | 583 // it's "MessageEvent". |
371 ASSERT_TRUE(AddEchoingListener("message_event.constructor.name")); | 584 ASSERT_TRUE(AddEchoingListener("message_event.constructor.name")); |
372 message_data_.clear(); | 585 message_data_.clear(); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 ASSERT_TRUE(received_value <= kThreadsToRun); | 723 ASSERT_TRUE(received_value <= kThreadsToRun); |
511 ++received_counts[received_value]; | 724 ++received_counts[received_value]; |
512 } | 725 } |
513 ASSERT_EQ(received_counts, expected_counts); | 726 ASSERT_EQ(received_counts, expected_counts); |
514 | 727 |
515 message_data_.clear(); | 728 message_data_.clear(); |
516 ASSERT_TRUE(ClearListeners()); | 729 ASSERT_TRUE(ClearListeners()); |
517 | 730 |
518 PASS(); | 731 PASS(); |
519 } | 732 } |
OLD | NEW |