ipc_mojo_bootstrap_unittest.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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
  3. // found in the LICENSE file.
  4. #include "ipc/ipc_mojo_bootstrap.h"
  5. #include <cstdint>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/run_loop.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/threading/thread_task_runner_handle.h"
  11. #include "ipc/ipc.mojom.h"
  12. #include "ipc/ipc_test_base.h"
  13. #include "mojo/core/test/multiprocess_test_helper.h"
  14. #include "mojo/public/cpp/bindings/associated_receiver.h"
  15. namespace {
  16. constexpr int32_t kTestServerPid = 42;
  17. constexpr int32_t kTestClientPid = 4242;
  18. class Connection {
  19. public:
  20. explicit Connection(std::unique_ptr<IPC::MojoBootstrap> bootstrap,
  21. int32_t sender_id)
  22. : bootstrap_(std::move(bootstrap)) {
  23. mojo::PendingAssociatedRemote<IPC::mojom::Channel> sender;
  24. bootstrap_->Connect(&sender, &receiver_);
  25. sender_.Bind(std::move(sender));
  26. sender_->SetPeerPid(sender_id);
  27. // It's OK to start receiving right away even though `receiver_` isn't
  28. // bound, because all of these tests are single-threaded and it will be
  29. // bound before any incoming messages can be scheduled for processing.
  30. bootstrap_->StartReceiving();
  31. }
  32. void TakeReceiver(
  33. mojo::PendingAssociatedReceiver<IPC::mojom::Channel>* receiver) {
  34. *receiver = std::move(receiver_);
  35. }
  36. mojo::AssociatedRemote<IPC::mojom::Channel>& GetSender() { return sender_; }
  37. private:
  38. mojo::AssociatedRemote<IPC::mojom::Channel> sender_;
  39. mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver_;
  40. std::unique_ptr<IPC::MojoBootstrap> bootstrap_;
  41. };
  42. class PeerPidReceiver : public IPC::mojom::Channel {
  43. public:
  44. enum class MessageExpectation {
  45. kNotExpected,
  46. kExpectedValid,
  47. kExpectedInvalid
  48. };
  49. PeerPidReceiver(
  50. mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver,
  51. base::OnceClosure on_peer_pid_set,
  52. MessageExpectation message_expectation = MessageExpectation::kNotExpected)
  53. : receiver_(this, std::move(receiver)),
  54. on_peer_pid_set_(std::move(on_peer_pid_set)),
  55. message_expectation_(message_expectation) {
  56. receiver_.set_disconnect_handler(disconnect_run_loop_.QuitClosure());
  57. }
  58. PeerPidReceiver(const PeerPidReceiver&) = delete;
  59. PeerPidReceiver& operator=(const PeerPidReceiver&) = delete;
  60. ~PeerPidReceiver() override {
  61. bool expected_message =
  62. message_expectation_ != MessageExpectation::kNotExpected;
  63. EXPECT_EQ(expected_message, received_message_);
  64. }
  65. // mojom::Channel:
  66. void SetPeerPid(int32_t pid) override {
  67. peer_pid_ = pid;
  68. std::move(on_peer_pid_set_).Run();
  69. }
  70. void Receive(IPC::MessageView message_view) override {
  71. ASSERT_NE(MessageExpectation::kNotExpected, message_expectation_);
  72. received_message_ = true;
  73. IPC::Message message(
  74. reinterpret_cast<const char*>(message_view.bytes().data()),
  75. message_view.bytes().size());
  76. bool expected_valid =
  77. message_expectation_ == MessageExpectation::kExpectedValid;
  78. EXPECT_EQ(expected_valid, message.IsValid());
  79. }
  80. void GetAssociatedInterface(
  81. mojo::GenericPendingAssociatedReceiver receiver) override {}
  82. int32_t peer_pid() const { return peer_pid_; }
  83. void RunUntilDisconnect() { disconnect_run_loop_.Run(); }
  84. private:
  85. mojo::AssociatedReceiver<IPC::mojom::Channel> receiver_;
  86. base::OnceClosure on_peer_pid_set_;
  87. MessageExpectation message_expectation_;
  88. int32_t peer_pid_ = -1;
  89. bool received_message_ = false;
  90. base::RunLoop disconnect_run_loop_;
  91. };
  92. class IPCMojoBootstrapTest : public testing::Test {
  93. protected:
  94. mojo::core::test::MultiprocessTestHelper helper_;
  95. };
  96. TEST_F(IPCMojoBootstrapTest, Connect) {
  97. base::test::SingleThreadTaskEnvironment task_environment;
  98. Connection connection(
  99. IPC::MojoBootstrap::Create(
  100. helper_.StartChild("IPCMojoBootstrapTestClient"),
  101. IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
  102. base::ThreadTaskRunnerHandle::Get(), nullptr),
  103. kTestServerPid);
  104. mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
  105. connection.TakeReceiver(&receiver);
  106. base::RunLoop run_loop;
  107. PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
  108. run_loop.Run();
  109. EXPECT_EQ(kTestClientPid, impl.peer_pid());
  110. impl.RunUntilDisconnect();
  111. EXPECT_TRUE(helper_.WaitForChildTestShutdown());
  112. }
  113. // A long running process that connects to us.
  114. MULTIPROCESS_TEST_MAIN_WITH_SETUP(
  115. IPCMojoBootstrapTestClientTestChildMain,
  116. ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {
  117. base::test::SingleThreadTaskEnvironment task_environment;
  118. Connection connection(
  119. IPC::MojoBootstrap::Create(
  120. std::move(mojo::core::test::MultiprocessTestHelper::primordial_pipe),
  121. IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
  122. base::ThreadTaskRunnerHandle::Get(), nullptr),
  123. kTestClientPid);
  124. mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
  125. connection.TakeReceiver(&receiver);
  126. base::RunLoop run_loop;
  127. PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
  128. run_loop.Run();
  129. EXPECT_EQ(kTestServerPid, impl.peer_pid());
  130. return 0;
  131. }
  132. TEST_F(IPCMojoBootstrapTest, ReceiveEmptyMessage) {
  133. base::test::SingleThreadTaskEnvironment task_environment;
  134. Connection connection(
  135. IPC::MojoBootstrap::Create(
  136. helper_.StartChild("IPCMojoBootstrapTestEmptyMessage"),
  137. IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
  138. base::ThreadTaskRunnerHandle::Get(), nullptr),
  139. kTestServerPid);
  140. mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
  141. connection.TakeReceiver(&receiver);
  142. base::RunLoop run_loop;
  143. PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure(),
  144. PeerPidReceiver::MessageExpectation::kExpectedInvalid);
  145. run_loop.Run();
  146. // Wait for the Channel to be disconnected so we can reasonably assert that
  147. // the child's empty message must have been received before we pass the test.
  148. impl.RunUntilDisconnect();
  149. EXPECT_TRUE(helper_.WaitForChildTestShutdown());
  150. }
  151. // A long running process that connects to us.
  152. MULTIPROCESS_TEST_MAIN_WITH_SETUP(
  153. IPCMojoBootstrapTestEmptyMessageTestChildMain,
  154. ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {
  155. base::test::SingleThreadTaskEnvironment task_environment;
  156. Connection connection(
  157. IPC::MojoBootstrap::Create(
  158. std::move(mojo::core::test::MultiprocessTestHelper::primordial_pipe),
  159. IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
  160. base::ThreadTaskRunnerHandle::Get(), nullptr),
  161. kTestClientPid);
  162. mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
  163. connection.TakeReceiver(&receiver);
  164. auto& sender = connection.GetSender();
  165. uint8_t data = 0;
  166. sender->Receive(
  167. IPC::MessageView(base::make_span(&data, 0), absl::nullopt /* handles */));
  168. base::RunLoop run_loop;
  169. PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
  170. run_loop.Run();
  171. return 0;
  172. }
  173. } // namespace