xref: /aosp_15_r20/external/libchrome/ipc/ipc_mojo_bootstrap_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_mojo_bootstrap.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <cstdint>
8*635a8641SAndroid Build Coastguard Worker #include <memory>
9*635a8641SAndroid Build Coastguard Worker #include <utility>
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/message_loop/message_loop.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/run_loop.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_task_runner_handle.h"
14*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc.mojom.h"
15*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_test_base.h"
16*635a8641SAndroid Build Coastguard Worker #include "mojo/core/test/multiprocess_test_helper.h"
17*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/bindings/associated_binding.h"
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker namespace {
20*635a8641SAndroid Build Coastguard Worker 
21*635a8641SAndroid Build Coastguard Worker constexpr int32_t kTestServerPid = 42;
22*635a8641SAndroid Build Coastguard Worker constexpr int32_t kTestClientPid = 4242;
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker class Connection {
25*635a8641SAndroid Build Coastguard Worker  public:
Connection(std::unique_ptr<IPC::MojoBootstrap> bootstrap,int32_t sender_id)26*635a8641SAndroid Build Coastguard Worker   explicit Connection(std::unique_ptr<IPC::MojoBootstrap> bootstrap,
27*635a8641SAndroid Build Coastguard Worker                       int32_t sender_id)
28*635a8641SAndroid Build Coastguard Worker       : bootstrap_(std::move(bootstrap)) {
29*635a8641SAndroid Build Coastguard Worker     bootstrap_->Connect(&sender_, &receiver_);
30*635a8641SAndroid Build Coastguard Worker     sender_->SetPeerPid(sender_id);
31*635a8641SAndroid Build Coastguard Worker   }
32*635a8641SAndroid Build Coastguard Worker 
TakeReceiver(IPC::mojom::ChannelAssociatedRequest * receiver)33*635a8641SAndroid Build Coastguard Worker   void TakeReceiver(IPC::mojom::ChannelAssociatedRequest* receiver) {
34*635a8641SAndroid Build Coastguard Worker     *receiver = std::move(receiver_);
35*635a8641SAndroid Build Coastguard Worker   }
36*635a8641SAndroid Build Coastguard Worker 
GetSender()37*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedPtr& GetSender() { return sender_; }
38*635a8641SAndroid Build Coastguard Worker 
39*635a8641SAndroid Build Coastguard Worker  private:
40*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedPtr sender_;
41*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedRequest receiver_;
42*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<IPC::MojoBootstrap> bootstrap_;
43*635a8641SAndroid Build Coastguard Worker };
44*635a8641SAndroid Build Coastguard Worker 
45*635a8641SAndroid Build Coastguard Worker class PeerPidReceiver : public IPC::mojom::Channel {
46*635a8641SAndroid Build Coastguard Worker  public:
47*635a8641SAndroid Build Coastguard Worker   enum class MessageExpectation {
48*635a8641SAndroid Build Coastguard Worker     kNotExpected,
49*635a8641SAndroid Build Coastguard Worker     kExpectedValid,
50*635a8641SAndroid Build Coastguard Worker     kExpectedInvalid
51*635a8641SAndroid Build Coastguard Worker   };
52*635a8641SAndroid Build Coastguard Worker 
PeerPidReceiver(IPC::mojom::ChannelAssociatedRequest request,const base::Closure & on_peer_pid_set,MessageExpectation message_expectation=MessageExpectation::kNotExpected)53*635a8641SAndroid Build Coastguard Worker   PeerPidReceiver(
54*635a8641SAndroid Build Coastguard Worker       IPC::mojom::ChannelAssociatedRequest request,
55*635a8641SAndroid Build Coastguard Worker       const base::Closure& on_peer_pid_set,
56*635a8641SAndroid Build Coastguard Worker       MessageExpectation message_expectation = MessageExpectation::kNotExpected)
57*635a8641SAndroid Build Coastguard Worker       : binding_(this, std::move(request)),
58*635a8641SAndroid Build Coastguard Worker         on_peer_pid_set_(on_peer_pid_set),
59*635a8641SAndroid Build Coastguard Worker         message_expectation_(message_expectation) {
60*635a8641SAndroid Build Coastguard Worker     binding_.set_connection_error_handler(disconnect_run_loop_.QuitClosure());
61*635a8641SAndroid Build Coastguard Worker   }
62*635a8641SAndroid Build Coastguard Worker 
~PeerPidReceiver()63*635a8641SAndroid Build Coastguard Worker   ~PeerPidReceiver() override {
64*635a8641SAndroid Build Coastguard Worker     bool expected_message =
65*635a8641SAndroid Build Coastguard Worker         message_expectation_ != MessageExpectation::kNotExpected;
66*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(expected_message, received_message_);
67*635a8641SAndroid Build Coastguard Worker   }
68*635a8641SAndroid Build Coastguard Worker 
69*635a8641SAndroid Build Coastguard Worker   // mojom::Channel:
SetPeerPid(int32_t pid)70*635a8641SAndroid Build Coastguard Worker   void SetPeerPid(int32_t pid) override {
71*635a8641SAndroid Build Coastguard Worker     peer_pid_ = pid;
72*635a8641SAndroid Build Coastguard Worker     on_peer_pid_set_.Run();
73*635a8641SAndroid Build Coastguard Worker   }
74*635a8641SAndroid Build Coastguard Worker 
Receive(IPC::MessageView message_view)75*635a8641SAndroid Build Coastguard Worker   void Receive(IPC::MessageView message_view) override {
76*635a8641SAndroid Build Coastguard Worker     ASSERT_NE(MessageExpectation::kNotExpected, message_expectation_);
77*635a8641SAndroid Build Coastguard Worker     received_message_ = true;
78*635a8641SAndroid Build Coastguard Worker 
79*635a8641SAndroid Build Coastguard Worker     IPC::Message message(message_view.data(), message_view.size());
80*635a8641SAndroid Build Coastguard Worker     bool expected_valid =
81*635a8641SAndroid Build Coastguard Worker         message_expectation_ == MessageExpectation::kExpectedValid;
82*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(expected_valid, message.IsValid());
83*635a8641SAndroid Build Coastguard Worker   }
84*635a8641SAndroid Build Coastguard Worker 
GetAssociatedInterface(const std::string & name,IPC::mojom::GenericInterfaceAssociatedRequest request)85*635a8641SAndroid Build Coastguard Worker   void GetAssociatedInterface(
86*635a8641SAndroid Build Coastguard Worker       const std::string& name,
87*635a8641SAndroid Build Coastguard Worker       IPC::mojom::GenericInterfaceAssociatedRequest request) override {}
88*635a8641SAndroid Build Coastguard Worker 
peer_pid() const89*635a8641SAndroid Build Coastguard Worker   int32_t peer_pid() const { return peer_pid_; }
90*635a8641SAndroid Build Coastguard Worker 
RunUntilDisconnect()91*635a8641SAndroid Build Coastguard Worker   void RunUntilDisconnect() { disconnect_run_loop_.Run(); }
92*635a8641SAndroid Build Coastguard Worker 
93*635a8641SAndroid Build Coastguard Worker  private:
94*635a8641SAndroid Build Coastguard Worker   mojo::AssociatedBinding<IPC::mojom::Channel> binding_;
95*635a8641SAndroid Build Coastguard Worker   const base::Closure on_peer_pid_set_;
96*635a8641SAndroid Build Coastguard Worker   MessageExpectation message_expectation_;
97*635a8641SAndroid Build Coastguard Worker   int32_t peer_pid_ = -1;
98*635a8641SAndroid Build Coastguard Worker   bool received_message_ = false;
99*635a8641SAndroid Build Coastguard Worker   base::RunLoop disconnect_run_loop_;
100*635a8641SAndroid Build Coastguard Worker 
101*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(PeerPidReceiver);
102*635a8641SAndroid Build Coastguard Worker };
103*635a8641SAndroid Build Coastguard Worker 
104*635a8641SAndroid Build Coastguard Worker class IPCMojoBootstrapTest : public testing::Test {
105*635a8641SAndroid Build Coastguard Worker  protected:
106*635a8641SAndroid Build Coastguard Worker   mojo::core::test::MultiprocessTestHelper helper_;
107*635a8641SAndroid Build Coastguard Worker };
108*635a8641SAndroid Build Coastguard Worker 
TEST_F(IPCMojoBootstrapTest,Connect)109*635a8641SAndroid Build Coastguard Worker TEST_F(IPCMojoBootstrapTest, Connect) {
110*635a8641SAndroid Build Coastguard Worker   base::MessageLoop message_loop;
111*635a8641SAndroid Build Coastguard Worker   Connection connection(
112*635a8641SAndroid Build Coastguard Worker       IPC::MojoBootstrap::Create(
113*635a8641SAndroid Build Coastguard Worker           helper_.StartChild("IPCMojoBootstrapTestClient"),
114*635a8641SAndroid Build Coastguard Worker           IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
115*635a8641SAndroid Build Coastguard Worker           base::ThreadTaskRunnerHandle::Get()),
116*635a8641SAndroid Build Coastguard Worker       kTestServerPid);
117*635a8641SAndroid Build Coastguard Worker 
118*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedRequest receiver;
119*635a8641SAndroid Build Coastguard Worker   connection.TakeReceiver(&receiver);
120*635a8641SAndroid Build Coastguard Worker 
121*635a8641SAndroid Build Coastguard Worker   base::RunLoop run_loop;
122*635a8641SAndroid Build Coastguard Worker   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
123*635a8641SAndroid Build Coastguard Worker   run_loop.Run();
124*635a8641SAndroid Build Coastguard Worker 
125*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kTestClientPid, impl.peer_pid());
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker   impl.RunUntilDisconnect();
128*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(helper_.WaitForChildTestShutdown());
129*635a8641SAndroid Build Coastguard Worker }
130*635a8641SAndroid Build Coastguard Worker 
131*635a8641SAndroid Build Coastguard Worker // A long running process that connects to us.
MULTIPROCESS_TEST_MAIN_WITH_SETUP(IPCMojoBootstrapTestClientTestChildMain,::mojo::core::test::MultiprocessTestHelper::ChildSetup)132*635a8641SAndroid Build Coastguard Worker MULTIPROCESS_TEST_MAIN_WITH_SETUP(
133*635a8641SAndroid Build Coastguard Worker     IPCMojoBootstrapTestClientTestChildMain,
134*635a8641SAndroid Build Coastguard Worker     ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {
135*635a8641SAndroid Build Coastguard Worker   base::MessageLoop message_loop;
136*635a8641SAndroid Build Coastguard Worker   Connection connection(
137*635a8641SAndroid Build Coastguard Worker       IPC::MojoBootstrap::Create(
138*635a8641SAndroid Build Coastguard Worker           std::move(mojo::core::test::MultiprocessTestHelper::primordial_pipe),
139*635a8641SAndroid Build Coastguard Worker           IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
140*635a8641SAndroid Build Coastguard Worker           base::ThreadTaskRunnerHandle::Get()),
141*635a8641SAndroid Build Coastguard Worker       kTestClientPid);
142*635a8641SAndroid Build Coastguard Worker 
143*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedRequest receiver;
144*635a8641SAndroid Build Coastguard Worker   connection.TakeReceiver(&receiver);
145*635a8641SAndroid Build Coastguard Worker 
146*635a8641SAndroid Build Coastguard Worker   base::RunLoop run_loop;
147*635a8641SAndroid Build Coastguard Worker   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
148*635a8641SAndroid Build Coastguard Worker   run_loop.Run();
149*635a8641SAndroid Build Coastguard Worker 
150*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kTestServerPid, impl.peer_pid());
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker   return 0;
153*635a8641SAndroid Build Coastguard Worker }
154*635a8641SAndroid Build Coastguard Worker 
TEST_F(IPCMojoBootstrapTest,ReceiveEmptyMessage)155*635a8641SAndroid Build Coastguard Worker TEST_F(IPCMojoBootstrapTest, ReceiveEmptyMessage) {
156*635a8641SAndroid Build Coastguard Worker   base::MessageLoop message_loop;
157*635a8641SAndroid Build Coastguard Worker   Connection connection(
158*635a8641SAndroid Build Coastguard Worker       IPC::MojoBootstrap::Create(
159*635a8641SAndroid Build Coastguard Worker           helper_.StartChild("IPCMojoBootstrapTestEmptyMessage"),
160*635a8641SAndroid Build Coastguard Worker           IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
161*635a8641SAndroid Build Coastguard Worker           base::ThreadTaskRunnerHandle::Get()),
162*635a8641SAndroid Build Coastguard Worker       kTestServerPid);
163*635a8641SAndroid Build Coastguard Worker 
164*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedRequest receiver;
165*635a8641SAndroid Build Coastguard Worker   connection.TakeReceiver(&receiver);
166*635a8641SAndroid Build Coastguard Worker 
167*635a8641SAndroid Build Coastguard Worker   base::RunLoop run_loop;
168*635a8641SAndroid Build Coastguard Worker   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure(),
169*635a8641SAndroid Build Coastguard Worker                        PeerPidReceiver::MessageExpectation::kExpectedInvalid);
170*635a8641SAndroid Build Coastguard Worker   run_loop.Run();
171*635a8641SAndroid Build Coastguard Worker 
172*635a8641SAndroid Build Coastguard Worker   // Wait for the Channel to be disconnected so we can reasonably assert that
173*635a8641SAndroid Build Coastguard Worker   // the child's empty message must have been received before we pass the test.
174*635a8641SAndroid Build Coastguard Worker   impl.RunUntilDisconnect();
175*635a8641SAndroid Build Coastguard Worker 
176*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(helper_.WaitForChildTestShutdown());
177*635a8641SAndroid Build Coastguard Worker }
178*635a8641SAndroid Build Coastguard Worker 
179*635a8641SAndroid Build Coastguard Worker // A long running process that connects to us.
MULTIPROCESS_TEST_MAIN_WITH_SETUP(IPCMojoBootstrapTestEmptyMessageTestChildMain,::mojo::core::test::MultiprocessTestHelper::ChildSetup)180*635a8641SAndroid Build Coastguard Worker MULTIPROCESS_TEST_MAIN_WITH_SETUP(
181*635a8641SAndroid Build Coastguard Worker     IPCMojoBootstrapTestEmptyMessageTestChildMain,
182*635a8641SAndroid Build Coastguard Worker     ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {
183*635a8641SAndroid Build Coastguard Worker   base::MessageLoop message_loop;
184*635a8641SAndroid Build Coastguard Worker   Connection connection(
185*635a8641SAndroid Build Coastguard Worker       IPC::MojoBootstrap::Create(
186*635a8641SAndroid Build Coastguard Worker           std::move(mojo::core::test::MultiprocessTestHelper::primordial_pipe),
187*635a8641SAndroid Build Coastguard Worker           IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
188*635a8641SAndroid Build Coastguard Worker           base::ThreadTaskRunnerHandle::Get()),
189*635a8641SAndroid Build Coastguard Worker       kTestClientPid);
190*635a8641SAndroid Build Coastguard Worker 
191*635a8641SAndroid Build Coastguard Worker   IPC::mojom::ChannelAssociatedRequest receiver;
192*635a8641SAndroid Build Coastguard Worker   connection.TakeReceiver(&receiver);
193*635a8641SAndroid Build Coastguard Worker   auto& sender = connection.GetSender();
194*635a8641SAndroid Build Coastguard Worker 
195*635a8641SAndroid Build Coastguard Worker   uint8_t data = 0;
196*635a8641SAndroid Build Coastguard Worker   sender->Receive(
197*635a8641SAndroid Build Coastguard Worker       IPC::MessageView(mojo_base::BigBufferView(base::make_span(&data, 0)),
198*635a8641SAndroid Build Coastguard Worker                        base::nullopt /* handles */));
199*635a8641SAndroid Build Coastguard Worker 
200*635a8641SAndroid Build Coastguard Worker   base::RunLoop run_loop;
201*635a8641SAndroid Build Coastguard Worker   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
202*635a8641SAndroid Build Coastguard Worker   run_loop.Run();
203*635a8641SAndroid Build Coastguard Worker 
204*635a8641SAndroid Build Coastguard Worker   return 0;
205*635a8641SAndroid Build Coastguard Worker }
206*635a8641SAndroid Build Coastguard Worker 
207*635a8641SAndroid Build Coastguard Worker }  // namespace
208