OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "mojo/edk/embedder/embedder.h" | 5 #include "mojo/edk/embedder/embedder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 namespace edk { | 27 namespace edk { |
28 namespace { | 28 namespace { |
29 | 29 |
30 const MojoHandleSignals kSignalReadadableWritable = | 30 const MojoHandleSignals kSignalReadadableWritable = |
31 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; | 31 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; |
32 | 32 |
33 const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | | 33 const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | |
34 MOJO_HANDLE_SIGNAL_WRITABLE | | 34 MOJO_HANDLE_SIGNAL_WRITABLE | |
35 MOJO_HANDLE_SIGNAL_PEER_CLOSED; | 35 MOJO_HANDLE_SIGNAL_PEER_CLOSED; |
36 | 36 |
37 class EmbedderTest : public test::MojoSystemTest { | 37 typedef testing::Test EmbedderTest; |
38 public: | |
39 EmbedderTest() {} | |
40 ~EmbedderTest() override {} | |
41 | |
42 private: | |
43 MOJO_DISALLOW_COPY_AND_ASSIGN(EmbedderTest); | |
44 }; | |
45 | 38 |
46 TEST_F(EmbedderTest, ChannelBasic) { | 39 TEST_F(EmbedderTest, ChannelBasic) { |
47 MojoHandle server_mp, client_mp; | 40 MojoHandle server_mp, client_mp; |
48 ASSERT_EQ(MOJO_RESULT_OK, | 41 ASSERT_EQ(MOJO_RESULT_OK, |
49 MojoCreateMessagePipe(nullptr, &server_mp, &client_mp)); | 42 MojoCreateMessagePipe(nullptr, &server_mp, &client_mp)); |
50 | 43 |
51 // We can write to a message pipe handle immediately. | 44 // We can write to a message pipe handle immediately. |
52 const char kHello[] = "hello"; | 45 const char kHello[] = "hello"; |
53 | 46 |
54 size_t write_size = sizeof(kHello); | 47 size_t write_size = sizeof(kHello); |
(...skipping 23 matching lines...) Expand all Loading... |
78 } | 71 } |
79 | 72 |
80 // Test sending a MP which has read messages out of the OS pipe but which have | 73 // Test sending a MP which has read messages out of the OS pipe but which have |
81 // not been consumed using MojoReadMessage yet. | 74 // not been consumed using MojoReadMessage yet. |
82 TEST_F(EmbedderTest, SendReadableMessagePipe) { | 75 TEST_F(EmbedderTest, SendReadableMessagePipe) { |
83 MojoHandle server_mp, client_mp; | 76 MojoHandle server_mp, client_mp; |
84 ASSERT_EQ(MOJO_RESULT_OK, | 77 ASSERT_EQ(MOJO_RESULT_OK, |
85 MojoCreateMessagePipe(nullptr, &server_mp, &client_mp)); | 78 MojoCreateMessagePipe(nullptr, &server_mp, &client_mp)); |
86 | 79 |
87 MojoHandle server_mp2, client_mp2; | 80 MojoHandle server_mp2, client_mp2; |
| 81 MojoCreateMessagePipeOptions options; |
| 82 options.struct_size = sizeof(MojoCreateMessagePipeOptions); |
| 83 options.flags = MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE; |
88 ASSERT_EQ(MOJO_RESULT_OK, | 84 ASSERT_EQ(MOJO_RESULT_OK, |
89 MojoCreateMessagePipe(nullptr, &server_mp2, &client_mp2)); | 85 MojoCreateMessagePipe(&options, &server_mp2, &client_mp2)); |
90 | 86 |
91 // Write to server2 and wait for client2 to be readable before sending it. | 87 // Write to server2 and wait for client2 to be readable before sending it. |
92 // client2's MessagePipeDispatcher will have the message below in its | 88 // client2's MessagePipeDispatcher will have the message below in its |
93 // message_queue_. For extra measures, also verify that this pending message | 89 // message_queue_. For extra measures, also verify that this pending message |
94 // can contain a message pipe. | 90 // can contain a message pipe. |
95 MojoHandle server_mp3, client_mp3; | 91 MojoHandle server_mp3, client_mp3; |
96 ASSERT_EQ(MOJO_RESULT_OK, | 92 ASSERT_EQ(MOJO_RESULT_OK, |
97 MojoCreateMessagePipe(nullptr, &server_mp3, &client_mp3)); | 93 MojoCreateMessagePipe(nullptr, &server_mp3, &client_mp3)); |
98 const char kHello[] = "hello"; | 94 const char kHello[] = "hello"; |
99 size_t write_size; | 95 size_t write_size; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); | 154 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); |
159 } | 155 } |
160 | 156 |
161 // Verifies that a MP with pending messages to be written can be sent and the | 157 // Verifies that a MP with pending messages to be written can be sent and the |
162 // pending messages aren't dropped. | 158 // pending messages aren't dropped. |
163 TEST_F(EmbedderTest, SendMessagePipeWithWriteQueue) { | 159 TEST_F(EmbedderTest, SendMessagePipeWithWriteQueue) { |
164 MojoHandle server_mp, client_mp; | 160 MojoHandle server_mp, client_mp; |
165 ASSERT_EQ(MOJO_RESULT_OK, | 161 ASSERT_EQ(MOJO_RESULT_OK, |
166 MojoCreateMessagePipe(nullptr, &server_mp, &client_mp)); | 162 MojoCreateMessagePipe(nullptr, &server_mp, &client_mp)); |
167 | 163 |
| 164 MojoCreateMessagePipeOptions options; |
| 165 options.struct_size = sizeof(MojoCreateMessagePipeOptions); |
| 166 options.flags = MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE; |
168 MojoHandle server_mp2, client_mp2; | 167 MojoHandle server_mp2, client_mp2; |
169 ASSERT_EQ(MOJO_RESULT_OK, | 168 ASSERT_EQ(MOJO_RESULT_OK, |
170 MojoCreateMessagePipe(nullptr, &server_mp2, &client_mp2)); | 169 MojoCreateMessagePipe(&options, &server_mp2, &client_mp2)); |
171 | 170 |
172 static const size_t kNumMessages = 1001; | 171 static const size_t kNumMessages = 1001; |
173 for (size_t i = 0; i < kNumMessages; i++) { | 172 for (size_t i = 0; i < kNumMessages; i++) { |
174 std::string write_buffer(i, 'A' + (i % 26)); | 173 std::string write_buffer(i, 'A' + (i % 26)); |
175 ASSERT_EQ(MOJO_RESULT_OK, | 174 ASSERT_EQ(MOJO_RESULT_OK, |
176 MojoWriteMessage(client_mp2, write_buffer.data(), | 175 MojoWriteMessage(client_mp2, write_buffer.data(), |
177 static_cast<uint32_t>(write_buffer.size()), | 176 static_cast<uint32_t>(write_buffer.size()), |
178 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 177 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
179 } | 178 } |
180 | 179 |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 ASSERT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); | 457 ASSERT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); |
459 ASSERT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfiable_signals); | 458 ASSERT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfiable_signals); |
460 #endif | 459 #endif |
461 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); | 460 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); |
462 } | 461 } |
463 | 462 |
464 EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); | 463 EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); |
465 } | 464 } |
466 | 465 |
467 MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { | 466 MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { |
468 base::MessageLoop message_loop; | |
469 ScopedPlatformHandle client_platform_handle = | 467 ScopedPlatformHandle client_platform_handle = |
470 test::MultiprocessTestHelper::client_platform_handle.Pass(); | 468 test::MultiprocessTestHelper::client_platform_handle.Pass(); |
471 EXPECT_TRUE(client_platform_handle.is_valid()); | 469 EXPECT_TRUE(client_platform_handle.is_valid()); |
472 | 470 |
473 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | 471 MojoHandle client_mp = CreateMessagePipe( |
| 472 client_platform_handle.Pass()).release().value(); |
474 | 473 |
475 { | 474 // 1. Read the first message from |client_mp|. |
476 test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); | 475 MojoHandleSignalsState state; |
477 MojoHandle client_mp = CreateMessagePipe( | 476 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, |
478 client_platform_handle.Pass()).release().value(); | 477 MOJO_DEADLINE_INDEFINITE, &state)); |
| 478 ASSERT_EQ(kSignalReadadableWritable, state.satisfied_signals); |
| 479 ASSERT_EQ(kSignalAll, state.satisfiable_signals); |
479 | 480 |
480 // 1. Read the first message from |client_mp|. | 481 char buffer[1000] = {}; |
481 MojoHandleSignalsState state; | 482 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
482 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, | 483 ASSERT_EQ(MOJO_RESULT_OK, |
483 MOJO_DEADLINE_INDEFINITE, &state)); | 484 MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, |
484 ASSERT_EQ(kSignalReadadableWritable, state.satisfied_signals); | 485 MOJO_READ_MESSAGE_FLAG_NONE)); |
485 ASSERT_EQ(kSignalAll, state.satisfiable_signals); | 486 const char kHello[] = "hello"; |
| 487 ASSERT_EQ(sizeof(kHello), num_bytes); |
| 488 EXPECT_STREQ(kHello, buffer); |
486 | 489 |
487 char buffer[1000] = {}; | 490 // 2. Write a message to |client_mp| (attaching nothing). |
488 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | 491 const char kWorld[] = "world!"; |
489 ASSERT_EQ(MOJO_RESULT_OK, | 492 ASSERT_EQ(MOJO_RESULT_OK, |
490 MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, | 493 MojoWriteMessage(client_mp, kWorld, |
491 MOJO_READ_MESSAGE_FLAG_NONE)); | 494 static_cast<uint32_t>(sizeof(kWorld)), nullptr, |
492 const char kHello[] = "hello"; | 495 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
493 ASSERT_EQ(sizeof(kHello), num_bytes); | |
494 EXPECT_STREQ(kHello, buffer); | |
495 | 496 |
496 // 2. Write a message to |client_mp| (attaching nothing). | 497 // 4. Read a message from |client_mp|, which should have |mp1| attached. |
497 const char kWorld[] = "world!"; | 498 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, |
498 ASSERT_EQ(MOJO_RESULT_OK, | 499 MOJO_DEADLINE_INDEFINITE, &state)); |
499 MojoWriteMessage(client_mp, kWorld, | 500 // The other end of the handle may or may not be closed at this point, so we |
500 static_cast<uint32_t>(sizeof(kWorld)), nullptr, | 501 // can't test MOJO_HANDLE_SIGNAL_WRITABLE or MOJO_HANDLE_SIGNAL_PEER_CLOSED. |
501 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 502 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, |
| 503 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); |
| 504 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, |
| 505 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); |
| 506 // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd |
| 507 // die (again due to |Channel::HandleLocalError()|). |
| 508 memset(buffer, 0, sizeof(buffer)); |
| 509 num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| 510 MojoHandle mp1 = MOJO_HANDLE_INVALID; |
| 511 uint32_t num_handles = 1; |
| 512 ASSERT_EQ(MOJO_RESULT_OK, |
| 513 MojoReadMessage(client_mp, buffer, &num_bytes, &mp1, &num_handles, |
| 514 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 515 const char kBar[] = "Bar"; |
| 516 ASSERT_EQ(sizeof(kBar), num_bytes); |
| 517 EXPECT_STREQ(kBar, buffer); |
| 518 ASSERT_EQ(1u, num_handles); |
| 519 EXPECT_NE(mp1, MOJO_HANDLE_INVALID); |
| 520 // TODO(vtl): If the scope were to end here (and the two handles closed), |
| 521 // we'd die due to |Channel::RunRemoteMessagePipeEndpoint()| not handling |
| 522 // write errors (assuming the parent had closed the pipe). |
502 | 523 |
503 // 4. Read a message from |client_mp|, which should have |mp1| attached. | 524 // 6. Close |client_mp|. |
504 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, | 525 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); |
505 MOJO_DEADLINE_INDEFINITE, &state)); | |
506 // The other end of the handle may or may not be closed at this point, so we | |
507 // can't test MOJO_HANDLE_SIGNAL_WRITABLE or MOJO_HANDLE_SIGNAL_PEER_CLOSED. | |
508 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, | |
509 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); | |
510 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, | |
511 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); | |
512 // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd | |
513 // die (again due to |Channel::HandleLocalError()|). | |
514 memset(buffer, 0, sizeof(buffer)); | |
515 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
516 MojoHandle mp1 = MOJO_HANDLE_INVALID; | |
517 uint32_t num_handles = 1; | |
518 ASSERT_EQ(MOJO_RESULT_OK, | |
519 MojoReadMessage(client_mp, buffer, &num_bytes, &mp1, &num_handles, | |
520 MOJO_READ_MESSAGE_FLAG_NONE)); | |
521 const char kBar[] = "Bar"; | |
522 ASSERT_EQ(sizeof(kBar), num_bytes); | |
523 EXPECT_STREQ(kBar, buffer); | |
524 ASSERT_EQ(1u, num_handles); | |
525 EXPECT_NE(mp1, MOJO_HANDLE_INVALID); | |
526 // TODO(vtl): If the scope were to end here (and the two handles closed), | |
527 // we'd die due to |Channel::RunRemoteMessagePipeEndpoint()| not handling | |
528 // write errors (assuming the parent had closed the pipe). | |
529 | 526 |
530 // 6. Close |client_mp|. | 527 // Create a new message pipe (endpoints |mp2| and |mp3|). |
531 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); | 528 MojoHandle mp2, mp3; |
| 529 ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp3)); |
532 | 530 |
533 // Create a new message pipe (endpoints |mp2| and |mp3|). | 531 // 7. Write a message to |mp3|. |
534 MojoHandle mp2, mp3; | 532 const char kBaz[] = "baz"; |
535 ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp3)); | 533 ASSERT_EQ(MOJO_RESULT_OK, |
| 534 MojoWriteMessage(mp3, kBaz, static_cast<uint32_t>(sizeof(kBaz)), |
| 535 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
536 | 536 |
537 // 7. Write a message to |mp3|. | 537 // 8. Close |mp3|. |
538 const char kBaz[] = "baz"; | 538 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp3)); |
539 ASSERT_EQ(MOJO_RESULT_OK, | |
540 MojoWriteMessage(mp3, kBaz, static_cast<uint32_t>(sizeof(kBaz)), | |
541 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
542 | 539 |
543 // 8. Close |mp3|. | 540 // 9. Write a message to |mp1|, attaching |mp2|. |
544 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp3)); | 541 const char kQuux[] = "quux"; |
| 542 ASSERT_EQ(MOJO_RESULT_OK, |
| 543 MojoWriteMessage(mp1, kQuux, static_cast<uint32_t>(sizeof(kQuux)), |
| 544 &mp2, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 545 mp2 = MOJO_HANDLE_INVALID; |
545 | 546 |
546 // 9. Write a message to |mp1|, attaching |mp2|. | 547 // 3. Read a message from |mp1|. |
547 const char kQuux[] = "quux"; | 548 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |
548 ASSERT_EQ(MOJO_RESULT_OK, | 549 MOJO_DEADLINE_INDEFINITE, &state)); |
549 MojoWriteMessage(mp1, kQuux, static_cast<uint32_t>(sizeof(kQuux)), | 550 ASSERT_EQ(kSignalReadadableWritable, state.satisfied_signals); |
550 &mp2, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 551 ASSERT_EQ(kSignalAll, state.satisfiable_signals); |
551 mp2 = MOJO_HANDLE_INVALID; | |
552 | 552 |
553 // 3. Read a message from |mp1|. | 553 memset(buffer, 0, sizeof(buffer)); |
554 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | 554 num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
555 MOJO_DEADLINE_INDEFINITE, &state)); | 555 ASSERT_EQ(MOJO_RESULT_OK, |
556 ASSERT_EQ(kSignalReadadableWritable, state.satisfied_signals); | 556 MojoReadMessage(mp1, buffer, &num_bytes, nullptr, nullptr, |
557 ASSERT_EQ(kSignalAll, state.satisfiable_signals); | 557 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 558 const char kFoo[] = "FOO"; |
| 559 ASSERT_EQ(sizeof(kFoo), num_bytes); |
| 560 EXPECT_STREQ(kFoo, buffer); |
558 | 561 |
559 memset(buffer, 0, sizeof(buffer)); | 562 // 11. Wait on |mp1| (which should eventually fail) and then close it. |
560 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | 563 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
561 ASSERT_EQ(MOJO_RESULT_OK, | 564 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |
562 MojoReadMessage(mp1, buffer, &num_bytes, nullptr, nullptr, | 565 MOJO_DEADLINE_INDEFINITE, &state)); |
563 MOJO_READ_MESSAGE_FLAG_NONE)); | 566 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); |
564 const char kFoo[] = "FOO"; | 567 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); |
565 ASSERT_EQ(sizeof(kFoo), num_bytes); | 568 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); |
566 EXPECT_STREQ(kFoo, buffer); | |
567 | |
568 // 11. Wait on |mp1| (which should eventually fail) and then close it. | |
569 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
570 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
571 MOJO_DEADLINE_INDEFINITE, &state)); | |
572 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); | |
573 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); | |
574 ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); | |
575 } | |
576 } | 569 } |
577 | 570 |
578 // TODO(vtl): Test immediate write & close. | 571 // TODO(vtl): Test immediate write & close. |
579 // TODO(vtl): Test broken-connection cases. | 572 // TODO(vtl): Test broken-connection cases. |
580 | 573 |
581 } // namespace | 574 } // namespace |
582 } // namespace edk | 575 } // namespace edk |
583 } // namespace mojo | 576 } // namespace mojo |
OLD | NEW |