OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | 8 |
9 #include "ppapi/c/dev/ppb_testing_dev.h" | 9 #include "ppapi/c/dev/ppb_testing_dev.h" |
10 #include "ppapi/c/pp_var.h" | 10 #include "ppapi/c/pp_var.h" |
11 #include "ppapi/cpp/dev/scriptable_object_deprecated.h" | 11 #include "ppapi/cpp/dev/scriptable_object_deprecated.h" |
12 #include "ppapi/cpp/instance.h" | 12 #include "ppapi/cpp/instance.h" |
13 #include "ppapi/cpp/var.h" | 13 #include "ppapi/cpp/var.h" |
| 14 #include "ppapi/tests/pp_thread.h" |
14 #include "ppapi/tests/test_utils.h" | 15 #include "ppapi/tests/test_utils.h" |
15 #include "ppapi/tests/testing_instance.h" | 16 #include "ppapi/tests/testing_instance.h" |
16 | 17 |
17 // Windows defines 'PostMessage', so we have to undef it. | 18 // Windows defines 'PostMessage', so we have to undef it. |
18 #ifdef PostMessage | 19 #ifdef PostMessage |
19 #undef PostMessage | 20 #undef PostMessage |
20 #endif | 21 #endif |
21 | 22 |
22 REGISTER_TEST_CASE(PostMessage); | 23 REGISTER_TEST_CASE(PostMessage); |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 const char kTestString[] = "Hello world!"; | 27 const char kTestString[] = "Hello world!"; |
27 const bool kTestBool = true; | 28 const bool kTestBool = true; |
28 const int32_t kTestInt = 42; | 29 const int32_t kTestInt = 42; |
29 const double kTestDouble = 42.0; | 30 const double kTestDouble = 42.0; |
30 const int32_t kThreadsToRun = 10; | 31 const int32_t kThreadsToRun = 10; |
| 32 const int32_t kMessagesToSendPerThread = 50; |
| 33 |
| 34 // The struct that invoke_post_message_thread_func expects for its argument. |
| 35 // It includes the instance on which to invoke PostMessage, and the value to |
| 36 // pass to PostMessage. |
| 37 struct InvokePostMessageThreadArg { |
| 38 InvokePostMessageThreadArg(pp::Instance* i, const pp::Var& v) |
| 39 : instance(i), value_to_send(v) {} |
| 40 pp::Instance* instance; |
| 41 pp::Var value_to_send; |
| 42 }; |
| 43 |
| 44 void InvokePostMessageThreadFunc(void* user_data) { |
| 45 InvokePostMessageThreadArg* arg = |
| 46 static_cast<InvokePostMessageThreadArg*>(user_data); |
| 47 for (int32_t i = 0; i < kMessagesToSendPerThread; ++i) |
| 48 arg->instance->PostMessage(arg->value_to_send); |
| 49 delete arg; |
| 50 } |
31 | 51 |
32 } // namespace | 52 } // namespace |
33 | 53 |
34 bool TestPostMessage::Init() { | 54 bool TestPostMessage::Init() { |
35 return InitTestingInterface(); | 55 return InitTestingInterface(); |
36 } | 56 } |
37 | 57 |
38 void TestPostMessage::RunTest() { | 58 void TestPostMessage::RunTest() { |
39 RUN_TEST(SendingData); | 59 RUN_TEST(SendingData); |
40 RUN_TEST(MessageEvent); | 60 RUN_TEST(MessageEvent); |
41 RUN_TEST(NoHandler); | 61 RUN_TEST(NoHandler); |
42 RUN_TEST(ExtraParam); | 62 RUN_TEST(ExtraParam); |
| 63 if (testing_interface_->IsOutOfProcess()) |
| 64 RUN_TEST(NonMainThread); |
43 } | 65 } |
44 | 66 |
45 void TestPostMessage::HandleMessage(const pp::Var& message_data) { | 67 void TestPostMessage::HandleMessage(const pp::Var& message_data) { |
46 message_data_.push_back(message_data); | 68 message_data_.push_back(message_data); |
47 testing_interface_->QuitMessageLoop(instance_->pp_instance()); | 69 testing_interface_->QuitMessageLoop(instance_->pp_instance()); |
48 } | 70 } |
49 | 71 |
50 bool TestPostMessage::AddEchoingListener(const std::string& expression) { | 72 bool TestPostMessage::AddEchoingListener(const std::string& expression) { |
51 std::string js_code; | 73 std::string js_code; |
52 // Note the following code is dependent on some features of test_case.html. | 74 // Note the following code is dependent on some features of test_case.html. |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 // Therefore, we will do CallOnMainThread to yield control. That event should | 269 // Therefore, we will do CallOnMainThread to yield control. That event should |
248 // fire, but we should see no messages when we return. | 270 // fire, but we should see no messages when we return. |
249 TestCompletionCallback callback(instance_->pp_instance()); | 271 TestCompletionCallback callback(instance_->pp_instance()); |
250 pp::Module::Get()->core()->CallOnMainThread(0, callback); | 272 pp::Module::Get()->core()->CallOnMainThread(0, callback); |
251 callback.WaitForResult(); | 273 callback.WaitForResult(); |
252 ASSERT_TRUE(message_data_.empty()); | 274 ASSERT_TRUE(message_data_.empty()); |
253 | 275 |
254 PASS(); | 276 PASS(); |
255 } | 277 } |
256 | 278 |
| 279 std::string TestPostMessage::TestNonMainThread() { |
| 280 ASSERT_TRUE(ClearListeners()); |
| 281 ASSERT_TRUE(AddEchoingListener("message_event.data")); |
| 282 message_data_.clear(); |
| 283 |
| 284 // Set up a thread for each integer from 0 to (kThreadsToRun - 1). Make each |
| 285 // thread send the number that matches its index kMessagesToSendPerThread |
| 286 // times. For good measure, call postMessage from the main thread |
| 287 // kMessagesToSendPerThread times. At the end, we make sure we got all the |
| 288 // values we expected. |
| 289 PP_ThreadType threads[kThreadsToRun]; |
| 290 for (int32_t i = 0; i < kThreadsToRun; ++i) { |
| 291 // Set up a thread to send a value of i. |
| 292 void* arg = new InvokePostMessageThreadArg(instance_, pp::Var(i)); |
| 293 PP_CreateThread(&threads[i], &InvokePostMessageThreadFunc, arg); |
| 294 } |
| 295 // Invoke PostMessage right now to send a value of (kThreadsToRun). |
| 296 for (int32_t i = 0; i < kMessagesToSendPerThread; ++i) |
| 297 instance_->PostMessage(pp::Var(kThreadsToRun)); |
| 298 |
| 299 // Now join all threads. |
| 300 for (int32_t i = 0; i < kThreadsToRun; ++i) |
| 301 PP_JoinThread(threads[i]); |
| 302 |
| 303 // PostMessage is asynchronous, so we should not receive a response yet. |
| 304 ASSERT_EQ(message_data_.size(), 0); |
| 305 |
| 306 // Make sure we got all values that we expected. Note that because it's legal |
| 307 // for the JavaScript engine to treat our integers as floating points, we |
| 308 // can't just use std::find or equality comparison. So we instead, we convert |
| 309 // each incoming value to an integer, and count them in received_counts. |
| 310 int32_t expected_num = (kThreadsToRun + 1) * kMessagesToSendPerThread; |
| 311 // Count how many we receive per-index. |
| 312 std::vector<int32_t> expected_counts(kThreadsToRun + 1, |
| 313 kMessagesToSendPerThread); |
| 314 std::vector<int32_t> received_counts(kThreadsToRun + 1, 0); |
| 315 for (int32_t i = 0; i < expected_num; ++i) { |
| 316 // Run the message loop to get the next expected message. |
| 317 testing_interface_->RunMessageLoop(instance_->pp_instance()); |
| 318 // Make sure we got another message in. |
| 319 ASSERT_EQ(message_data_.size(), 1); |
| 320 pp::Var latest_var(message_data_.back()); |
| 321 message_data_.clear(); |
| 322 |
| 323 ASSERT_TRUE(latest_var.is_int() || latest_var.is_double()); |
| 324 int32_t received_value = -1; |
| 325 if (latest_var.is_int()) { |
| 326 received_value = latest_var.AsInt(); |
| 327 } else if (latest_var.is_double()) { |
| 328 received_value = static_cast<int32_t>(latest_var.AsDouble() + 0.5); |
| 329 } |
| 330 ASSERT_TRUE(received_value >= 0); |
| 331 ASSERT_TRUE(received_value <= kThreadsToRun); |
| 332 ++received_counts[received_value]; |
| 333 } |
| 334 ASSERT_EQ(received_counts, expected_counts); |
| 335 |
| 336 PASS(); |
| 337 } |
| 338 |
OLD | NEW |