Chromium Code Reviews| 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; | |
|
dmichael (off chromium)
2013/05/09 20:21:12
random trivia: You can do this with one lookup usi
raymes
2013/05/13 17:09:43
Cool thanks - yeah I didn't know (or I knew and fo
| |
| 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); | |
|
dmichael (off chromium)
2013/05/09 20:21:12
Don't you also need to compare the value of the ke
raymes
2013/05/13 17:09:43
Well it's not iterating through the values here, b
dmichael (off chromium)
2013/05/13 18:02:26
Sorry, I was misreading, as if you were using the
| |
| 103 if (!VarsEqual(expected_dict.Get(key), actual_dict.Get(key), visited_ids)) | |
| 104 return false; | |
| 105 } | |
| 106 return true; | |
| 107 } else { | |
| 108 return expected == actual; | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 bool VarsEqual(const pp::Var& expected, | |
| 113 const pp::Var& actual) { | |
| 114 std::map<int64_t, int64_t> visited_ids; | |
| 115 return VarsEqual(expected, actual, &visited_ids); | |
| 116 } | |
| 117 | |
| 61 class ScopedArrayBufferSizeSetter { | 118 class ScopedArrayBufferSizeSetter { |
| 62 public: | 119 public: |
| 63 ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface, | 120 ScopedArrayBufferSizeSetter(const PPB_Testing_Dev* interface, |
| 64 PP_Instance instance, | 121 PP_Instance instance, |
| 65 uint32_t threshold) | 122 uint32_t threshold) |
| 66 : interface_(interface), | 123 : interface_(interface), |
| 67 instance_(instance) { | 124 instance_(instance) { |
| 68 interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold); | 125 interface_->SetMinimumArrayBufferSizeForShmem(instance_, threshold); |
| 69 } | 126 } |
| 70 ~ScopedArrayBufferSizeSetter() { | 127 ~ScopedArrayBufferSizeSetter() { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 128 | 185 |
| 129 return success; | 186 return success; |
| 130 } | 187 } |
| 131 | 188 |
| 132 void TestPostMessage::RunTests(const std::string& filter) { | 189 void TestPostMessage::RunTests(const std::string& filter) { |
| 133 // Note: SendInInit must be first, because it expects to receive a message | 190 // Note: SendInInit must be first, because it expects to receive a message |
| 134 // that was sent in Init above. | 191 // that was sent in Init above. |
| 135 RUN_TEST(SendInInit, filter); | 192 RUN_TEST(SendInInit, filter); |
| 136 RUN_TEST(SendingData, filter); | 193 RUN_TEST(SendingData, filter); |
| 137 RUN_TEST(SendingArrayBuffer, filter); | 194 RUN_TEST(SendingArrayBuffer, filter); |
| 195 RUN_TEST(SendingArray, filter); | |
| 196 RUN_TEST(SendingDictionary, filter); | |
| 197 RUN_TEST(SendingComplexVar, filter); | |
| 138 RUN_TEST(MessageEvent, filter); | 198 RUN_TEST(MessageEvent, filter); |
| 139 RUN_TEST(NoHandler, filter); | 199 RUN_TEST(NoHandler, filter); |
| 140 RUN_TEST(ExtraParam, filter); | 200 RUN_TEST(ExtraParam, filter); |
| 141 if (testing_interface_->IsOutOfProcess()) | 201 if (testing_interface_->IsOutOfProcess()) |
| 142 RUN_TEST(NonMainThread, filter); | 202 RUN_TEST(NonMainThread, filter); |
| 143 } | 203 } |
| 144 | 204 |
| 145 void TestPostMessage::HandleMessage(const pp::Var& message_data) { | 205 void TestPostMessage::HandleMessage(const pp::Var& message_data) { |
| 146 if (message_data.is_string() && | 206 if (message_data.is_string() && |
| 147 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) | 207 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 for (size_t i = 0; i < test_data.ByteLength(); ++i) | 413 for (size_t i = 0; i < test_data.ByteLength(); ++i) |
| 354 ASSERT_EQ(buff[i], received_buff[i]); | 414 ASSERT_EQ(buff[i], received_buff[i]); |
| 355 | 415 |
| 356 message_data_.clear(); | 416 message_data_.clear(); |
| 357 ASSERT_TRUE(ClearListeners()); | 417 ASSERT_TRUE(ClearListeners()); |
| 358 } | 418 } |
| 359 | 419 |
| 360 PASS(); | 420 PASS(); |
| 361 } | 421 } |
| 362 | 422 |
| 423 std::string TestPostMessage::TestSendingArray() { | |
| 424 // Clean up after previous tests. This also swallows the message sent by Init | |
| 425 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
| 426 // should start with these. | |
| 427 WaitForMessages(); | |
| 428 ASSERT_TRUE(ClearListeners()); | |
| 429 | |
| 430 pp::VarArray_Dev array; | |
| 431 array.Set(0, pp::Var(kTestBool)); | |
| 432 array.Set(1, pp::Var(kTestString)); | |
| 433 // Purposely leave index 2 empty. | |
| 434 array.Set(3, pp::Var(kTestInt)); | |
| 435 array.Set(4, pp::Var(kTestDouble)); | |
| 436 | |
| 437 std::stringstream ss; | |
| 438 ss << array.GetLength(); | |
|
dmichael (off chromium)
2013/05/09 20:21:12
How about:
std::string length_as_string(ss.str());
raymes
2013/05/13 17:09:43
Done.
| |
| 439 | |
| 440 // Have the listener test some properties of the Array. | |
| 441 std::vector<std::string> properties_to_check; | |
| 442 properties_to_check.push_back( | |
| 443 "message_event.data.constructor.name === 'Array'"); | |
| 444 properties_to_check.push_back( | |
| 445 std::string("message_event.data.length === ") + ss.str()); | |
| 446 for (std::vector<std::string>::iterator iter = properties_to_check.begin(); | |
| 447 iter != properties_to_check.end(); | |
| 448 ++iter) { | |
| 449 ASSERT_TRUE(AddEchoingListener(*iter)); | |
| 450 message_data_.clear(); | |
| 451 instance_->PostMessage(array); | |
| 452 ASSERT_EQ(message_data_.size(), 0); | |
| 453 ASSERT_EQ(WaitForMessages(), 1); | |
| 454 ASSERT_TRUE(message_data_.back().is_bool()); | |
| 455 if (!message_data_.back().AsBool()) | |
| 456 return std::string("Failed: ") + *iter + ", size: " + ss.str(); | |
| 457 ASSERT_TRUE(message_data_.back().AsBool()); | |
| 458 ASSERT_TRUE(ClearListeners()); | |
|
dmichael (off chromium)
2013/05/09 20:21:12
I wonder how hard it would be to wrap this propert
raymes
2013/05/13 17:09:43
Done.
| |
| 459 } | |
| 460 | |
| 461 // Set up the JavaScript message event listener to echo the data part of the | |
| 462 // message event back to us. | |
| 463 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
| 464 message_data_.clear(); | |
| 465 instance_->PostMessage(array); | |
| 466 // PostMessage is asynchronous, so we should not receive a response yet. | |
| 467 ASSERT_EQ(message_data_.size(), 0); | |
| 468 ASSERT_EQ(WaitForMessages(), 1); | |
| 469 ASSERT_TRUE(message_data_.back().is_array()); | |
| 470 ASSERT_TRUE(VarsEqual(array, message_data_.back())); | |
| 471 | |
| 472 message_data_.clear(); | |
| 473 ASSERT_TRUE(ClearListeners()); | |
| 474 | |
| 475 PASS(); | |
| 476 } | |
| 477 | |
| 478 std::string TestPostMessage::TestSendingDictionary() { | |
| 479 // Clean up after previous tests. This also swallows the message sent by Init | |
| 480 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
| 481 // should start with these. | |
| 482 WaitForMessages(); | |
| 483 ASSERT_TRUE(ClearListeners()); | |
| 484 | |
| 485 pp::VarDictionary_Dev dictionary; | |
| 486 dictionary.Set(pp::Var("foo"), pp::Var(kTestBool)); | |
| 487 dictionary.Set(pp::Var("bar"), pp::Var(kTestString)); | |
| 488 dictionary.Set(pp::Var("abc"), pp::Var(kTestInt)); | |
| 489 dictionary.Set(pp::Var("def"), pp::Var()); | |
| 490 | |
| 491 std::stringstream ss; | |
| 492 ss << dictionary.GetKeys().GetLength(); | |
| 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 === ") + ss.str()); | |
| 500 for (std::vector<std::string>::iterator iter = properties_to_check.begin(); | |
| 501 iter != properties_to_check.end(); | |
| 502 ++iter) { | |
| 503 ASSERT_TRUE(AddEchoingListener(*iter)); | |
| 504 message_data_.clear(); | |
| 505 instance_->PostMessage(dictionary); | |
| 506 ASSERT_EQ(message_data_.size(), 0); | |
| 507 ASSERT_EQ(WaitForMessages(), 1); | |
| 508 ASSERT_TRUE(message_data_.back().is_bool()); | |
| 509 if (!message_data_.back().AsBool()) | |
| 510 return std::string("Failed: ") + *iter + ", size: " + ss.str(); | |
| 511 ASSERT_TRUE(message_data_.back().AsBool()); | |
| 512 ASSERT_TRUE(ClearListeners()); | |
| 513 } | |
| 514 | |
| 515 // Set up the JavaScript message event listener to echo the data part of the | |
| 516 // message event back to us. | |
| 517 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
| 518 message_data_.clear(); | |
| 519 instance_->PostMessage(dictionary); | |
| 520 // PostMessage is asynchronous, so we should not receive a response yet. | |
| 521 ASSERT_EQ(message_data_.size(), 0); | |
| 522 ASSERT_EQ(WaitForMessages(), 1); | |
| 523 ASSERT_TRUE(message_data_.back().is_dictionary()); | |
| 524 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); | |
| 525 | |
| 526 message_data_.clear(); | |
| 527 ASSERT_TRUE(ClearListeners()); | |
| 528 | |
| 529 PASS(); | |
| 530 } | |
| 531 | |
| 532 std::string TestPostMessage::TestSendingComplexVar() { | |
| 533 // Clean up after previous tests. This also swallows the message sent by Init | |
| 534 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
| 535 // should start with these. | |
| 536 WaitForMessages(); | |
| 537 ASSERT_TRUE(ClearListeners()); | |
| 538 | |
| 539 pp::VarDictionary_Dev dictionary; | |
| 540 dictionary.Set(pp::Var("foo"), pp::Var(kTestBool)); | |
| 541 dictionary.Set(pp::Var("bar"), pp::Var(kTestString)); | |
| 542 dictionary.Set(pp::Var("abc"), pp::Var(kTestInt)); | |
| 543 dictionary.Set(pp::Var("def"), pp::Var()); | |
| 544 dictionary.Set(pp::Var("dictionary"), dictionary); // Self-reference. | |
| 545 | |
| 546 // Reference to array. | |
| 547 pp::VarArray_Dev array; | |
| 548 array.Set(0, pp::Var(kTestBool)); | |
| 549 array.Set(1, pp::Var(kTestString)); | |
| 550 // Purposely leave index 2 empty. | |
|
dmichael (off chromium)
2013/05/09 20:21:12
This doesn't actually leave index 2 empty in our i
raymes
2013/05/13 17:09:43
Right - I updated the comment to clarify.
| |
| 551 array.Set(3, pp::Var(kTestInt)); | |
| 552 array.Set(4, pp::Var(kTestDouble)); | |
| 553 | |
| 554 dictionary.Set(pp::Var("array1"), array); | |
| 555 dictionary.Set(pp::Var("array2"), array); | |
| 556 | |
| 557 // Set up a (dictionary -> dictionary2 -> dictionary) cycle. | |
| 558 pp::VarDictionary_Dev dictionary2; | |
| 559 dictionary2.Set(pp::Var("dictionary"), dictionary); | |
| 560 dictionary.Set(pp::Var("dictionary2"), dictionary2); | |
|
dmichael (off chromium)
2013/05/09 20:21:12
Can we involve an array in a cycle too? And maybe
raymes
2013/05/13 17:09:43
Done - I modified it to add these 2 cases. I didn'
| |
| 561 | |
| 562 // Set up the JavaScript message event listener to echo the data part of the | |
| 563 // message event back to us. | |
| 564 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
| 565 message_data_.clear(); | |
| 566 instance_->PostMessage(dictionary); | |
| 567 // PostMessage is asynchronous, so we should not receive a response yet. | |
| 568 ASSERT_EQ(message_data_.size(), 0); | |
| 569 ASSERT_EQ(WaitForMessages(), 1); | |
| 570 ASSERT_TRUE(message_data_.back().is_dictionary()); | |
| 571 pp::VarDictionary_Dev result(message_data_.back()); | |
| 572 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); | |
| 573 | |
| 574 // Break the cycles. | |
| 575 dictionary.Delete(pp::Var("dictionary")); | |
| 576 dictionary.Delete(pp::Var("dictionary2")); | |
| 577 result.Delete(pp::Var("dictionary")); | |
| 578 result.Delete(pp::Var("dictionary2")); | |
| 579 | |
| 580 message_data_.clear(); | |
| 581 ASSERT_TRUE(ClearListeners()); | |
| 582 | |
| 583 PASS(); | |
| 584 } | |
| 585 | |
| 363 std::string TestPostMessage::TestMessageEvent() { | 586 std::string TestPostMessage::TestMessageEvent() { |
| 364 // Set up the JavaScript message event listener to pass us some values from | 587 // Set up the JavaScript message event listener to pass us some values from |
| 365 // the MessageEvent and make sure they match our expectations. | 588 // the MessageEvent and make sure they match our expectations. |
| 366 | 589 |
| 367 WaitForMessages(); | 590 WaitForMessages(); |
| 368 ASSERT_TRUE(ClearListeners()); | 591 ASSERT_TRUE(ClearListeners()); |
| 369 // Have the listener pass back the class name of message_event and make sure | 592 // Have the listener pass back the class name of message_event and make sure |
| 370 // it's "MessageEvent". | 593 // it's "MessageEvent". |
| 371 ASSERT_TRUE(AddEchoingListener("message_event.constructor.name")); | 594 ASSERT_TRUE(AddEchoingListener("message_event.constructor.name")); |
| 372 message_data_.clear(); | 595 message_data_.clear(); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 ASSERT_TRUE(received_value <= kThreadsToRun); | 733 ASSERT_TRUE(received_value <= kThreadsToRun); |
| 511 ++received_counts[received_value]; | 734 ++received_counts[received_value]; |
| 512 } | 735 } |
| 513 ASSERT_EQ(received_counts, expected_counts); | 736 ASSERT_EQ(received_counts, expected_counts); |
| 514 | 737 |
| 515 message_data_.clear(); | 738 message_data_.clear(); |
| 516 ASSERT_TRUE(ClearListeners()); | 739 ASSERT_TRUE(ClearListeners()); |
| 517 | 740 |
| 518 PASS(); | 741 PASS(); |
| 519 } | 742 } |
| OLD | NEW |