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