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