1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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_sync_channel.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <memory>
10*6777b538SAndroid Build Coastguard Worker #include <string>
11*6777b538SAndroid Build Coastguard Worker #include <utility>
12*6777b538SAndroid Build Coastguard Worker #include <vector>
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_type.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/process/process_handle.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread.h"
28*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
29*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_listener.h"
30*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_message.h"
31*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_sender.h"
32*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_sync_message_filter.h"
33*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_sync_message_unittest.h"
34*6777b538SAndroid Build Coastguard Worker #include "mojo/public/cpp/system/message_pipe.h"
35*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker using base::WaitableEvent;
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker namespace IPC {
40*6777b538SAndroid Build Coastguard Worker namespace {
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker // Base class for a "process" with listener and IPC threads.
43*6777b538SAndroid Build Coastguard Worker class Worker : public Listener, public Sender {
44*6777b538SAndroid Build Coastguard Worker public:
45*6777b538SAndroid Build Coastguard Worker // Will create a channel without a name.
Worker(Channel::Mode mode,const std::string & thread_name,mojo::ScopedMessagePipeHandle channel_handle)46*6777b538SAndroid Build Coastguard Worker Worker(Channel::Mode mode,
47*6777b538SAndroid Build Coastguard Worker const std::string& thread_name,
48*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
49*6777b538SAndroid Build Coastguard Worker : done_(
50*6777b538SAndroid Build Coastguard Worker new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
51*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED)),
52*6777b538SAndroid Build Coastguard Worker channel_created_(
53*6777b538SAndroid Build Coastguard Worker new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
54*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED)),
55*6777b538SAndroid Build Coastguard Worker channel_handle_(std::move(channel_handle)),
56*6777b538SAndroid Build Coastguard Worker mode_(mode),
57*6777b538SAndroid Build Coastguard Worker ipc_thread_(
58*6777b538SAndroid Build Coastguard Worker std::make_unique<base::Thread>((thread_name + "_ipc").c_str())),
59*6777b538SAndroid Build Coastguard Worker listener_thread_((thread_name + "_listener").c_str()),
60*6777b538SAndroid Build Coastguard Worker overrided_thread_(nullptr),
61*6777b538SAndroid Build Coastguard Worker shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
62*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED),
63*6777b538SAndroid Build Coastguard Worker is_shutdown_(false) {}
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker // Will create a named channel and use this name for the threads' name.
Worker(mojo::ScopedMessagePipeHandle channel_handle,Channel::Mode mode)66*6777b538SAndroid Build Coastguard Worker Worker(mojo::ScopedMessagePipeHandle channel_handle, Channel::Mode mode)
67*6777b538SAndroid Build Coastguard Worker : done_(
68*6777b538SAndroid Build Coastguard Worker new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
69*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED)),
70*6777b538SAndroid Build Coastguard Worker channel_created_(
71*6777b538SAndroid Build Coastguard Worker new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
72*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED)),
73*6777b538SAndroid Build Coastguard Worker channel_handle_(std::move(channel_handle)),
74*6777b538SAndroid Build Coastguard Worker mode_(mode),
75*6777b538SAndroid Build Coastguard Worker ipc_thread_(std::make_unique<base::Thread>("ipc thread")),
76*6777b538SAndroid Build Coastguard Worker listener_thread_("listener thread"),
77*6777b538SAndroid Build Coastguard Worker overrided_thread_(nullptr),
78*6777b538SAndroid Build Coastguard Worker shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
79*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED),
80*6777b538SAndroid Build Coastguard Worker is_shutdown_(false) {}
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker Worker(const Worker&) = delete;
83*6777b538SAndroid Build Coastguard Worker Worker& operator=(const Worker&) = delete;
84*6777b538SAndroid Build Coastguard Worker
~Worker()85*6777b538SAndroid Build Coastguard Worker ~Worker() override {
86*6777b538SAndroid Build Coastguard Worker // Shutdown() must be called before destruction.
87*6777b538SAndroid Build Coastguard Worker CHECK(is_shutdown_);
88*6777b538SAndroid Build Coastguard Worker }
Send(Message * msg)89*6777b538SAndroid Build Coastguard Worker bool Send(Message* msg) override { return channel_->Send(msg); }
WaitForChannelCreation()90*6777b538SAndroid Build Coastguard Worker void WaitForChannelCreation() { channel_created_->Wait(); }
CloseChannel()91*6777b538SAndroid Build Coastguard Worker void CloseChannel() {
92*6777b538SAndroid Build Coastguard Worker DCHECK(ListenerThread()->task_runner()->BelongsToCurrentThread());
93*6777b538SAndroid Build Coastguard Worker channel_->Close();
94*6777b538SAndroid Build Coastguard Worker }
Start()95*6777b538SAndroid Build Coastguard Worker void Start() {
96*6777b538SAndroid Build Coastguard Worker StartThread(&listener_thread_, base::MessagePumpType::DEFAULT);
97*6777b538SAndroid Build Coastguard Worker ListenerThread()->task_runner()->PostTask(
98*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&Worker::OnStart, base::Unretained(this)));
99*6777b538SAndroid Build Coastguard Worker }
Shutdown()100*6777b538SAndroid Build Coastguard Worker void Shutdown() {
101*6777b538SAndroid Build Coastguard Worker // The IPC thread needs to outlive SyncChannel. We can't do this in
102*6777b538SAndroid Build Coastguard Worker // ~Worker(), since that'll reset the vtable pointer (to Worker's), which
103*6777b538SAndroid Build Coastguard Worker // may result in a race conditions. See http://crbug.com/25841.
104*6777b538SAndroid Build Coastguard Worker WaitableEvent listener_done(
105*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::ResetPolicy::AUTOMATIC,
106*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
107*6777b538SAndroid Build Coastguard Worker ListenerThread()->task_runner()->PostTask(
108*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&Worker::OnListenerThreadShutdown1,
109*6777b538SAndroid Build Coastguard Worker base::Unretained(this), &listener_done));
110*6777b538SAndroid Build Coastguard Worker listener_done.Wait();
111*6777b538SAndroid Build Coastguard Worker listener_thread_.Stop();
112*6777b538SAndroid Build Coastguard Worker is_shutdown_ = true;
113*6777b538SAndroid Build Coastguard Worker }
OverrideThread(base::Thread * overrided_thread)114*6777b538SAndroid Build Coastguard Worker void OverrideThread(base::Thread* overrided_thread) {
115*6777b538SAndroid Build Coastguard Worker DCHECK(!overrided_thread_);
116*6777b538SAndroid Build Coastguard Worker overrided_thread_ = overrided_thread;
117*6777b538SAndroid Build Coastguard Worker }
SendAnswerToLife(bool succeed)118*6777b538SAndroid Build Coastguard Worker bool SendAnswerToLife(bool succeed) {
119*6777b538SAndroid Build Coastguard Worker int answer = 0;
120*6777b538SAndroid Build Coastguard Worker SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
121*6777b538SAndroid Build Coastguard Worker bool result = Send(msg);
122*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(result, succeed);
123*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(answer, (succeed ? 42 : 0));
124*6777b538SAndroid Build Coastguard Worker return result;
125*6777b538SAndroid Build Coastguard Worker }
SendDouble(bool succeed)126*6777b538SAndroid Build Coastguard Worker bool SendDouble(bool succeed) {
127*6777b538SAndroid Build Coastguard Worker int answer = 0;
128*6777b538SAndroid Build Coastguard Worker SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
129*6777b538SAndroid Build Coastguard Worker bool result = Send(msg);
130*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(result, succeed);
131*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(answer, (succeed ? 10 : 0));
132*6777b538SAndroid Build Coastguard Worker return result;
133*6777b538SAndroid Build Coastguard Worker }
TakeChannelHandle()134*6777b538SAndroid Build Coastguard Worker mojo::MessagePipeHandle TakeChannelHandle() {
135*6777b538SAndroid Build Coastguard Worker DCHECK(channel_handle_.is_valid());
136*6777b538SAndroid Build Coastguard Worker return channel_handle_.release();
137*6777b538SAndroid Build Coastguard Worker }
mode()138*6777b538SAndroid Build Coastguard Worker Channel::Mode mode() { return mode_; }
done_event()139*6777b538SAndroid Build Coastguard Worker WaitableEvent* done_event() { return done_.get(); }
shutdown_event()140*6777b538SAndroid Build Coastguard Worker WaitableEvent* shutdown_event() { return &shutdown_event_; }
ResetChannel()141*6777b538SAndroid Build Coastguard Worker void ResetChannel() { channel_.reset(); }
142*6777b538SAndroid Build Coastguard Worker // Derived classes need to call this when they've completed their part of
143*6777b538SAndroid Build Coastguard Worker // the test.
Done()144*6777b538SAndroid Build Coastguard Worker void Done() { done_->Signal(); }
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker protected:
channel()147*6777b538SAndroid Build Coastguard Worker SyncChannel* channel() { return channel_.get(); }
148*6777b538SAndroid Build Coastguard Worker // Functions for derived classes to implement if they wish.
Run()149*6777b538SAndroid Build Coastguard Worker virtual void Run() { }
OnAnswer(int * answer)150*6777b538SAndroid Build Coastguard Worker virtual void OnAnswer(int* answer) { NOTREACHED(); }
OnAnswerDelay(Message * reply_msg)151*6777b538SAndroid Build Coastguard Worker virtual void OnAnswerDelay(Message* reply_msg) {
152*6777b538SAndroid Build Coastguard Worker // The message handler map below can only take one entry for
153*6777b538SAndroid Build Coastguard Worker // SyncChannelTestMsg_AnswerToLife, so since some classes want
154*6777b538SAndroid Build Coastguard Worker // the normal version while other want the delayed reply, we
155*6777b538SAndroid Build Coastguard Worker // call the normal version if the derived class didn't override
156*6777b538SAndroid Build Coastguard Worker // this function.
157*6777b538SAndroid Build Coastguard Worker int answer;
158*6777b538SAndroid Build Coastguard Worker OnAnswer(&answer);
159*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
160*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
161*6777b538SAndroid Build Coastguard Worker }
OnDouble(int in,int * out)162*6777b538SAndroid Build Coastguard Worker virtual void OnDouble(int in, int* out) { NOTREACHED(); }
OnDoubleDelay(int in,Message * reply_msg)163*6777b538SAndroid Build Coastguard Worker virtual void OnDoubleDelay(int in, Message* reply_msg) {
164*6777b538SAndroid Build Coastguard Worker int result;
165*6777b538SAndroid Build Coastguard Worker OnDouble(in, &result);
166*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
167*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
168*6777b538SAndroid Build Coastguard Worker }
169*6777b538SAndroid Build Coastguard Worker
OnNestedTestMsg(Message * reply_msg)170*6777b538SAndroid Build Coastguard Worker virtual void OnNestedTestMsg(Message* reply_msg) {
171*6777b538SAndroid Build Coastguard Worker NOTREACHED();
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker
CreateChannel()174*6777b538SAndroid Build Coastguard Worker virtual SyncChannel* CreateChannel() {
175*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SyncChannel> channel = SyncChannel::Create(
176*6777b538SAndroid Build Coastguard Worker TakeChannelHandle(), mode_, this, ipc_thread_->task_runner(),
177*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault(), true,
178*6777b538SAndroid Build Coastguard Worker &shutdown_event_);
179*6777b538SAndroid Build Coastguard Worker return channel.release();
180*6777b538SAndroid Build Coastguard Worker }
181*6777b538SAndroid Build Coastguard Worker
ListenerThread()182*6777b538SAndroid Build Coastguard Worker base::Thread* ListenerThread() {
183*6777b538SAndroid Build Coastguard Worker return overrided_thread_ ? overrided_thread_.get() : &listener_thread_;
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
ipc_thread() const186*6777b538SAndroid Build Coastguard Worker const base::Thread& ipc_thread() const { return *ipc_thread_.get(); }
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker private:
189*6777b538SAndroid Build Coastguard Worker // Called on the listener thread to create the sync channel.
OnStart()190*6777b538SAndroid Build Coastguard Worker void OnStart() {
191*6777b538SAndroid Build Coastguard Worker // Link ipc_thread_, listener_thread_ and channel_ altogether.
192*6777b538SAndroid Build Coastguard Worker StartThread(ipc_thread_.get(), base::MessagePumpType::IO);
193*6777b538SAndroid Build Coastguard Worker channel_.reset(CreateChannel());
194*6777b538SAndroid Build Coastguard Worker channel_created_->Signal();
195*6777b538SAndroid Build Coastguard Worker Run();
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker
OnListenerThreadShutdown1(WaitableEvent * listener_event)198*6777b538SAndroid Build Coastguard Worker void OnListenerThreadShutdown1(WaitableEvent* listener_event) {
199*6777b538SAndroid Build Coastguard Worker WaitableEvent ipc_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
200*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
201*6777b538SAndroid Build Coastguard Worker // SyncChannel needs to be destructed on the thread that it was created on.
202*6777b538SAndroid Build Coastguard Worker channel_.reset();
203*6777b538SAndroid Build Coastguard Worker
204*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
205*6777b538SAndroid Build Coastguard Worker
206*6777b538SAndroid Build Coastguard Worker ipc_thread_->task_runner()->PostTask(
207*6777b538SAndroid Build Coastguard Worker FROM_HERE,
208*6777b538SAndroid Build Coastguard Worker base::BindOnce(&Worker::OnIPCThreadShutdown, base::Unretained(this),
209*6777b538SAndroid Build Coastguard Worker listener_event, &ipc_event));
210*6777b538SAndroid Build Coastguard Worker ipc_event.Wait();
211*6777b538SAndroid Build Coastguard Worker // This destructs `ipc_thread_` on the listener thread.
212*6777b538SAndroid Build Coastguard Worker ipc_thread_.reset();
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Worker listener_thread_.task_runner()->PostTask(
215*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&Worker::OnListenerThreadShutdown2,
216*6777b538SAndroid Build Coastguard Worker base::Unretained(this), listener_event));
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker
OnIPCThreadShutdown(WaitableEvent * listener_event,WaitableEvent * ipc_event)219*6777b538SAndroid Build Coastguard Worker void OnIPCThreadShutdown(WaitableEvent* listener_event,
220*6777b538SAndroid Build Coastguard Worker WaitableEvent* ipc_event) {
221*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
222*6777b538SAndroid Build Coastguard Worker ipc_event->Signal();
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker
OnListenerThreadShutdown2(WaitableEvent * listener_event)225*6777b538SAndroid Build Coastguard Worker void OnListenerThreadShutdown2(WaitableEvent* listener_event) {
226*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
227*6777b538SAndroid Build Coastguard Worker listener_event->Signal();
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker
OnMessageReceived(const Message & message)230*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
231*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(Worker, message)
232*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
233*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
234*6777b538SAndroid Build Coastguard Worker OnAnswerDelay)
235*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String,
236*6777b538SAndroid Build Coastguard Worker OnNestedTestMsg)
237*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
238*6777b538SAndroid Build Coastguard Worker return true;
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker
StartThread(base::Thread * thread,base::MessagePumpType type)241*6777b538SAndroid Build Coastguard Worker void StartThread(base::Thread* thread, base::MessagePumpType type) {
242*6777b538SAndroid Build Coastguard Worker base::Thread::Options options;
243*6777b538SAndroid Build Coastguard Worker options.message_pump_type = type;
244*6777b538SAndroid Build Coastguard Worker thread->StartWithOptions(std::move(options));
245*6777b538SAndroid Build Coastguard Worker }
246*6777b538SAndroid Build Coastguard Worker
247*6777b538SAndroid Build Coastguard Worker std::unique_ptr<WaitableEvent> done_;
248*6777b538SAndroid Build Coastguard Worker std::unique_ptr<WaitableEvent> channel_created_;
249*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle_;
250*6777b538SAndroid Build Coastguard Worker Channel::Mode mode_;
251*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SyncChannel> channel_;
252*6777b538SAndroid Build Coastguard Worker // This thread is constructed on the main thread, Start() on
253*6777b538SAndroid Build Coastguard Worker // `listener_thread_`, and therefore destructed/Stop()'d on the
254*6777b538SAndroid Build Coastguard Worker // `listener_thread_` too.
255*6777b538SAndroid Build Coastguard Worker std::unique_ptr<base::Thread> ipc_thread_;
256*6777b538SAndroid Build Coastguard Worker base::Thread listener_thread_;
257*6777b538SAndroid Build Coastguard Worker raw_ptr<base::Thread> overrided_thread_;
258*6777b538SAndroid Build Coastguard Worker
259*6777b538SAndroid Build Coastguard Worker base::WaitableEvent shutdown_event_;
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker bool is_shutdown_;
262*6777b538SAndroid Build Coastguard Worker };
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker
265*6777b538SAndroid Build Coastguard Worker // Starts the test with the given workers. This function deletes the workers
266*6777b538SAndroid Build Coastguard Worker // when it's done.
RunTest(std::vector<Worker * > workers)267*6777b538SAndroid Build Coastguard Worker void RunTest(std::vector<Worker*> workers) {
268*6777b538SAndroid Build Coastguard Worker // First we create the workers that are channel servers, or else the other
269*6777b538SAndroid Build Coastguard Worker // workers' channel initialization might fail because the pipe isn't created..
270*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < workers.size(); ++i) {
271*6777b538SAndroid Build Coastguard Worker if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) {
272*6777b538SAndroid Build Coastguard Worker workers[i]->Start();
273*6777b538SAndroid Build Coastguard Worker workers[i]->WaitForChannelCreation();
274*6777b538SAndroid Build Coastguard Worker }
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker
277*6777b538SAndroid Build Coastguard Worker // now create the clients
278*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < workers.size(); ++i) {
279*6777b538SAndroid Build Coastguard Worker if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG)
280*6777b538SAndroid Build Coastguard Worker workers[i]->Start();
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker
283*6777b538SAndroid Build Coastguard Worker // wait for all the workers to finish
284*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < workers.size(); ++i)
285*6777b538SAndroid Build Coastguard Worker workers[i]->done_event()->Wait();
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < workers.size(); ++i) {
288*6777b538SAndroid Build Coastguard Worker workers[i]->Shutdown();
289*6777b538SAndroid Build Coastguard Worker delete workers[i];
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker class IPCSyncChannelTest : public testing::Test {
294*6777b538SAndroid Build Coastguard Worker private:
295*6777b538SAndroid Build Coastguard Worker base::test::SingleThreadTaskEnvironment task_environment_;
296*6777b538SAndroid Build Coastguard Worker };
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker class SimpleServer : public Worker {
301*6777b538SAndroid Build Coastguard Worker public:
SimpleServer(mojo::ScopedMessagePipeHandle channel_handle)302*6777b538SAndroid Build Coastguard Worker explicit SimpleServer(mojo::ScopedMessagePipeHandle channel_handle)
303*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
304*6777b538SAndroid Build Coastguard Worker "simpler_server",
305*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)) {}
Run()306*6777b538SAndroid Build Coastguard Worker void Run() override {
307*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(true);
308*6777b538SAndroid Build Coastguard Worker Done();
309*6777b538SAndroid Build Coastguard Worker }
310*6777b538SAndroid Build Coastguard Worker };
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker class SimpleClient : public Worker {
313*6777b538SAndroid Build Coastguard Worker public:
SimpleClient(mojo::ScopedMessagePipeHandle channel_handle)314*6777b538SAndroid Build Coastguard Worker explicit SimpleClient(mojo::ScopedMessagePipeHandle channel_handle)
315*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_CLIENT,
316*6777b538SAndroid Build Coastguard Worker "simple_client",
317*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)) {}
318*6777b538SAndroid Build Coastguard Worker
OnAnswer(int * answer)319*6777b538SAndroid Build Coastguard Worker void OnAnswer(int* answer) override {
320*6777b538SAndroid Build Coastguard Worker *answer = 42;
321*6777b538SAndroid Build Coastguard Worker Done();
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker };
324*6777b538SAndroid Build Coastguard Worker
Simple()325*6777b538SAndroid Build Coastguard Worker void Simple() {
326*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
327*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
328*6777b538SAndroid Build Coastguard Worker workers.push_back(new SimpleServer(std::move(pipe.handle0)));
329*6777b538SAndroid Build Coastguard Worker workers.push_back(new SimpleClient(std::move(pipe.handle1)));
330*6777b538SAndroid Build Coastguard Worker RunTest(workers);
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
334*6777b538SAndroid Build Coastguard Worker #define MAYBE_Simple DISABLED_Simple
335*6777b538SAndroid Build Coastguard Worker #else
336*6777b538SAndroid Build Coastguard Worker #define MAYBE_Simple Simple
337*6777b538SAndroid Build Coastguard Worker #endif
338*6777b538SAndroid Build Coastguard Worker // Tests basic synchronous call
TEST_F(IPCSyncChannelTest,MAYBE_Simple)339*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, MAYBE_Simple) {
340*6777b538SAndroid Build Coastguard Worker Simple();
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker
343*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Worker // Worker classes which override how the sync channel is created to use the
346*6777b538SAndroid Build Coastguard Worker // two-step initialization (calling the lightweight constructor and then
347*6777b538SAndroid Build Coastguard Worker // ChannelProxy::Init separately) process.
348*6777b538SAndroid Build Coastguard Worker class TwoStepServer : public Worker {
349*6777b538SAndroid Build Coastguard Worker public:
TwoStepServer(bool create_pipe_now,mojo::ScopedMessagePipeHandle channel_handle)350*6777b538SAndroid Build Coastguard Worker TwoStepServer(bool create_pipe_now,
351*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
352*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
353*6777b538SAndroid Build Coastguard Worker "simpler_server",
354*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
355*6777b538SAndroid Build Coastguard Worker create_pipe_now_(create_pipe_now) {}
356*6777b538SAndroid Build Coastguard Worker
Run()357*6777b538SAndroid Build Coastguard Worker void Run() override {
358*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(true);
359*6777b538SAndroid Build Coastguard Worker Done();
360*6777b538SAndroid Build Coastguard Worker }
361*6777b538SAndroid Build Coastguard Worker
CreateChannel()362*6777b538SAndroid Build Coastguard Worker SyncChannel* CreateChannel() override {
363*6777b538SAndroid Build Coastguard Worker SyncChannel* channel =
364*6777b538SAndroid Build Coastguard Worker SyncChannel::Create(TakeChannelHandle(), mode(), this,
365*6777b538SAndroid Build Coastguard Worker ipc_thread().task_runner(),
366*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault(),
367*6777b538SAndroid Build Coastguard Worker create_pipe_now_, shutdown_event())
368*6777b538SAndroid Build Coastguard Worker .release();
369*6777b538SAndroid Build Coastguard Worker return channel;
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker
372*6777b538SAndroid Build Coastguard Worker bool create_pipe_now_;
373*6777b538SAndroid Build Coastguard Worker };
374*6777b538SAndroid Build Coastguard Worker
375*6777b538SAndroid Build Coastguard Worker class TwoStepClient : public Worker {
376*6777b538SAndroid Build Coastguard Worker public:
TwoStepClient(bool create_pipe_now,mojo::ScopedMessagePipeHandle channel_handle)377*6777b538SAndroid Build Coastguard Worker TwoStepClient(bool create_pipe_now,
378*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
379*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_CLIENT,
380*6777b538SAndroid Build Coastguard Worker "simple_client",
381*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
382*6777b538SAndroid Build Coastguard Worker create_pipe_now_(create_pipe_now) {}
383*6777b538SAndroid Build Coastguard Worker
OnAnswer(int * answer)384*6777b538SAndroid Build Coastguard Worker void OnAnswer(int* answer) override {
385*6777b538SAndroid Build Coastguard Worker *answer = 42;
386*6777b538SAndroid Build Coastguard Worker Done();
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker
CreateChannel()389*6777b538SAndroid Build Coastguard Worker SyncChannel* CreateChannel() override {
390*6777b538SAndroid Build Coastguard Worker SyncChannel* channel =
391*6777b538SAndroid Build Coastguard Worker SyncChannel::Create(TakeChannelHandle(), mode(), this,
392*6777b538SAndroid Build Coastguard Worker ipc_thread().task_runner(),
393*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault(),
394*6777b538SAndroid Build Coastguard Worker create_pipe_now_, shutdown_event())
395*6777b538SAndroid Build Coastguard Worker .release();
396*6777b538SAndroid Build Coastguard Worker return channel;
397*6777b538SAndroid Build Coastguard Worker }
398*6777b538SAndroid Build Coastguard Worker
399*6777b538SAndroid Build Coastguard Worker bool create_pipe_now_;
400*6777b538SAndroid Build Coastguard Worker };
401*6777b538SAndroid Build Coastguard Worker
TwoStep(bool create_server_pipe_now,bool create_client_pipe_now)402*6777b538SAndroid Build Coastguard Worker void TwoStep(bool create_server_pipe_now, bool create_client_pipe_now) {
403*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
404*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
405*6777b538SAndroid Build Coastguard Worker workers.push_back(
406*6777b538SAndroid Build Coastguard Worker new TwoStepServer(create_server_pipe_now, std::move(pipe.handle0)));
407*6777b538SAndroid Build Coastguard Worker workers.push_back(
408*6777b538SAndroid Build Coastguard Worker new TwoStepClient(create_client_pipe_now, std::move(pipe.handle1)));
409*6777b538SAndroid Build Coastguard Worker RunTest(workers);
410*6777b538SAndroid Build Coastguard Worker }
411*6777b538SAndroid Build Coastguard Worker
412*6777b538SAndroid Build Coastguard Worker // Tests basic two-step initialization, where you call the lightweight
413*6777b538SAndroid Build Coastguard Worker // constructor then Init.
TEST_F(IPCSyncChannelTest,TwoStepInitialization)414*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, TwoStepInitialization) {
415*6777b538SAndroid Build Coastguard Worker TwoStep(false, false);
416*6777b538SAndroid Build Coastguard Worker TwoStep(false, true);
417*6777b538SAndroid Build Coastguard Worker TwoStep(true, false);
418*6777b538SAndroid Build Coastguard Worker TwoStep(true, true);
419*6777b538SAndroid Build Coastguard Worker }
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
422*6777b538SAndroid Build Coastguard Worker
423*6777b538SAndroid Build Coastguard Worker class DelayClient : public Worker {
424*6777b538SAndroid Build Coastguard Worker public:
DelayClient(mojo::ScopedMessagePipeHandle channel_handle)425*6777b538SAndroid Build Coastguard Worker explicit DelayClient(mojo::ScopedMessagePipeHandle channel_handle)
426*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_CLIENT,
427*6777b538SAndroid Build Coastguard Worker "delay_client",
428*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)) {}
429*6777b538SAndroid Build Coastguard Worker
OnAnswerDelay(Message * reply_msg)430*6777b538SAndroid Build Coastguard Worker void OnAnswerDelay(Message* reply_msg) override {
431*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
432*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
433*6777b538SAndroid Build Coastguard Worker Done();
434*6777b538SAndroid Build Coastguard Worker }
435*6777b538SAndroid Build Coastguard Worker };
436*6777b538SAndroid Build Coastguard Worker
DelayReply()437*6777b538SAndroid Build Coastguard Worker void DelayReply() {
438*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
439*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
440*6777b538SAndroid Build Coastguard Worker workers.push_back(new SimpleServer(std::move(pipe.handle0)));
441*6777b538SAndroid Build Coastguard Worker workers.push_back(new DelayClient(std::move(pipe.handle1)));
442*6777b538SAndroid Build Coastguard Worker RunTest(workers);
443*6777b538SAndroid Build Coastguard Worker }
444*6777b538SAndroid Build Coastguard Worker
445*6777b538SAndroid Build Coastguard Worker // Tests that asynchronous replies work
TEST_F(IPCSyncChannelTest,DelayReply)446*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, DelayReply) {
447*6777b538SAndroid Build Coastguard Worker DelayReply();
448*6777b538SAndroid Build Coastguard Worker }
449*6777b538SAndroid Build Coastguard Worker
450*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
451*6777b538SAndroid Build Coastguard Worker
452*6777b538SAndroid Build Coastguard Worker class NoHangServer : public Worker {
453*6777b538SAndroid Build Coastguard Worker public:
NoHangServer(WaitableEvent * got_first_reply,mojo::ScopedMessagePipeHandle channel_handle)454*6777b538SAndroid Build Coastguard Worker NoHangServer(WaitableEvent* got_first_reply,
455*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
456*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
457*6777b538SAndroid Build Coastguard Worker "no_hang_server",
458*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
459*6777b538SAndroid Build Coastguard Worker got_first_reply_(got_first_reply) {}
Run()460*6777b538SAndroid Build Coastguard Worker void Run() override {
461*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(true);
462*6777b538SAndroid Build Coastguard Worker got_first_reply_->Signal();
463*6777b538SAndroid Build Coastguard Worker
464*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(false);
465*6777b538SAndroid Build Coastguard Worker Done();
466*6777b538SAndroid Build Coastguard Worker }
467*6777b538SAndroid Build Coastguard Worker
468*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> got_first_reply_;
469*6777b538SAndroid Build Coastguard Worker };
470*6777b538SAndroid Build Coastguard Worker
471*6777b538SAndroid Build Coastguard Worker class NoHangClient : public Worker {
472*6777b538SAndroid Build Coastguard Worker public:
NoHangClient(WaitableEvent * got_first_reply,mojo::ScopedMessagePipeHandle channel_handle)473*6777b538SAndroid Build Coastguard Worker NoHangClient(WaitableEvent* got_first_reply,
474*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
475*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_CLIENT,
476*6777b538SAndroid Build Coastguard Worker "no_hang_client",
477*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
478*6777b538SAndroid Build Coastguard Worker got_first_reply_(got_first_reply) {}
479*6777b538SAndroid Build Coastguard Worker
OnAnswerDelay(Message * reply_msg)480*6777b538SAndroid Build Coastguard Worker void OnAnswerDelay(Message* reply_msg) override {
481*6777b538SAndroid Build Coastguard Worker // Use the DELAY_REPLY macro so that we can force the reply to be sent
482*6777b538SAndroid Build Coastguard Worker // before this function returns (when the channel will be reset).
483*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
484*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
485*6777b538SAndroid Build Coastguard Worker got_first_reply_->Wait();
486*6777b538SAndroid Build Coastguard Worker CloseChannel();
487*6777b538SAndroid Build Coastguard Worker Done();
488*6777b538SAndroid Build Coastguard Worker }
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> got_first_reply_;
491*6777b538SAndroid Build Coastguard Worker };
492*6777b538SAndroid Build Coastguard Worker
NoHang()493*6777b538SAndroid Build Coastguard Worker void NoHang() {
494*6777b538SAndroid Build Coastguard Worker WaitableEvent got_first_reply(
495*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::ResetPolicy::AUTOMATIC,
496*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
497*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
498*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
499*6777b538SAndroid Build Coastguard Worker workers.push_back(
500*6777b538SAndroid Build Coastguard Worker new NoHangServer(&got_first_reply, std::move(pipe.handle0)));
501*6777b538SAndroid Build Coastguard Worker workers.push_back(
502*6777b538SAndroid Build Coastguard Worker new NoHangClient(&got_first_reply, std::move(pipe.handle1)));
503*6777b538SAndroid Build Coastguard Worker RunTest(workers);
504*6777b538SAndroid Build Coastguard Worker }
505*6777b538SAndroid Build Coastguard Worker
506*6777b538SAndroid Build Coastguard Worker // Tests that caller doesn't hang if receiver dies
TEST_F(IPCSyncChannelTest,NoHang)507*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, NoHang) {
508*6777b538SAndroid Build Coastguard Worker NoHang();
509*6777b538SAndroid Build Coastguard Worker }
510*6777b538SAndroid Build Coastguard Worker
511*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
512*6777b538SAndroid Build Coastguard Worker
513*6777b538SAndroid Build Coastguard Worker class UnblockServer : public Worker {
514*6777b538SAndroid Build Coastguard Worker public:
UnblockServer(bool delete_during_send,mojo::ScopedMessagePipeHandle channel_handle)515*6777b538SAndroid Build Coastguard Worker UnblockServer(bool delete_during_send,
516*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
517*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
518*6777b538SAndroid Build Coastguard Worker "unblock_server",
519*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
520*6777b538SAndroid Build Coastguard Worker delete_during_send_(delete_during_send) {}
Run()521*6777b538SAndroid Build Coastguard Worker void Run() override {
522*6777b538SAndroid Build Coastguard Worker if (delete_during_send_) {
523*6777b538SAndroid Build Coastguard Worker // Use custom code since race conditions mean the answer may or may not be
524*6777b538SAndroid Build Coastguard Worker // available.
525*6777b538SAndroid Build Coastguard Worker int answer = 0;
526*6777b538SAndroid Build Coastguard Worker SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
527*6777b538SAndroid Build Coastguard Worker Send(msg);
528*6777b538SAndroid Build Coastguard Worker } else {
529*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(true);
530*6777b538SAndroid Build Coastguard Worker }
531*6777b538SAndroid Build Coastguard Worker Done();
532*6777b538SAndroid Build Coastguard Worker }
533*6777b538SAndroid Build Coastguard Worker
OnDoubleDelay(int in,Message * reply_msg)534*6777b538SAndroid Build Coastguard Worker void OnDoubleDelay(int in, Message* reply_msg) override {
535*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
536*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
537*6777b538SAndroid Build Coastguard Worker if (delete_during_send_)
538*6777b538SAndroid Build Coastguard Worker ResetChannel();
539*6777b538SAndroid Build Coastguard Worker }
540*6777b538SAndroid Build Coastguard Worker
541*6777b538SAndroid Build Coastguard Worker bool delete_during_send_;
542*6777b538SAndroid Build Coastguard Worker };
543*6777b538SAndroid Build Coastguard Worker
544*6777b538SAndroid Build Coastguard Worker class UnblockClient : public Worker {
545*6777b538SAndroid Build Coastguard Worker public:
UnblockClient(mojo::ScopedMessagePipeHandle channel_handle)546*6777b538SAndroid Build Coastguard Worker explicit UnblockClient(mojo::ScopedMessagePipeHandle channel_handle)
547*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_CLIENT,
548*6777b538SAndroid Build Coastguard Worker "unblock_client",
549*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)) {}
550*6777b538SAndroid Build Coastguard Worker
OnAnswer(int * answer)551*6777b538SAndroid Build Coastguard Worker void OnAnswer(int* answer) override {
552*6777b538SAndroid Build Coastguard Worker SendDouble(true);
553*6777b538SAndroid Build Coastguard Worker *answer = 42;
554*6777b538SAndroid Build Coastguard Worker Done();
555*6777b538SAndroid Build Coastguard Worker }
556*6777b538SAndroid Build Coastguard Worker };
557*6777b538SAndroid Build Coastguard Worker
Unblock(bool delete_during_send)558*6777b538SAndroid Build Coastguard Worker void Unblock(bool delete_during_send) {
559*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
560*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
561*6777b538SAndroid Build Coastguard Worker workers.push_back(
562*6777b538SAndroid Build Coastguard Worker new UnblockServer(delete_during_send, std::move(pipe.handle0)));
563*6777b538SAndroid Build Coastguard Worker workers.push_back(new UnblockClient(std::move(pipe.handle1)));
564*6777b538SAndroid Build Coastguard Worker RunTest(workers);
565*6777b538SAndroid Build Coastguard Worker }
566*6777b538SAndroid Build Coastguard Worker
567*6777b538SAndroid Build Coastguard Worker // Tests that the caller unblocks to answer a sync message from the receiver.
TEST_F(IPCSyncChannelTest,Unblock)568*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, Unblock) {
569*6777b538SAndroid Build Coastguard Worker Unblock(false);
570*6777b538SAndroid Build Coastguard Worker }
571*6777b538SAndroid Build Coastguard Worker
572*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
573*6777b538SAndroid Build Coastguard Worker
574*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
575*6777b538SAndroid Build Coastguard Worker #define MAYBE_ChannelDeleteDuringSend DISABLED_ChannelDeleteDuringSend
576*6777b538SAndroid Build Coastguard Worker #else
577*6777b538SAndroid Build Coastguard Worker #define MAYBE_ChannelDeleteDuringSend ChannelDeleteDuringSend
578*6777b538SAndroid Build Coastguard Worker #endif
579*6777b538SAndroid Build Coastguard Worker // Tests that the the SyncChannel object can be deleted during a Send.
TEST_F(IPCSyncChannelTest,MAYBE_ChannelDeleteDuringSend)580*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, MAYBE_ChannelDeleteDuringSend) {
581*6777b538SAndroid Build Coastguard Worker Unblock(true);
582*6777b538SAndroid Build Coastguard Worker }
583*6777b538SAndroid Build Coastguard Worker
584*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
585*6777b538SAndroid Build Coastguard Worker
586*6777b538SAndroid Build Coastguard Worker class RecursiveServer : public Worker {
587*6777b538SAndroid Build Coastguard Worker public:
RecursiveServer(bool expected_send_result,mojo::ScopedMessagePipeHandle channel_handle)588*6777b538SAndroid Build Coastguard Worker RecursiveServer(bool expected_send_result,
589*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
590*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
591*6777b538SAndroid Build Coastguard Worker "recursive_server",
592*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
593*6777b538SAndroid Build Coastguard Worker expected_send_result_(expected_send_result) {}
Run()594*6777b538SAndroid Build Coastguard Worker void Run() override {
595*6777b538SAndroid Build Coastguard Worker SendDouble(expected_send_result_);
596*6777b538SAndroid Build Coastguard Worker Done();
597*6777b538SAndroid Build Coastguard Worker }
598*6777b538SAndroid Build Coastguard Worker
OnDouble(int in,int * out)599*6777b538SAndroid Build Coastguard Worker void OnDouble(int in, int* out) override {
600*6777b538SAndroid Build Coastguard Worker *out = in * 2;
601*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(expected_send_result_);
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker
604*6777b538SAndroid Build Coastguard Worker bool expected_send_result_;
605*6777b538SAndroid Build Coastguard Worker };
606*6777b538SAndroid Build Coastguard Worker
607*6777b538SAndroid Build Coastguard Worker class RecursiveClient : public Worker {
608*6777b538SAndroid Build Coastguard Worker public:
RecursiveClient(bool close_channel,mojo::ScopedMessagePipeHandle channel_handle)609*6777b538SAndroid Build Coastguard Worker RecursiveClient(bool close_channel,
610*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
611*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_CLIENT,
612*6777b538SAndroid Build Coastguard Worker "recursive_client",
613*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
614*6777b538SAndroid Build Coastguard Worker close_channel_(close_channel) {}
615*6777b538SAndroid Build Coastguard Worker
OnDoubleDelay(int in,Message * reply_msg)616*6777b538SAndroid Build Coastguard Worker void OnDoubleDelay(int in, Message* reply_msg) override {
617*6777b538SAndroid Build Coastguard Worker SendDouble(!close_channel_);
618*6777b538SAndroid Build Coastguard Worker if (close_channel_) {
619*6777b538SAndroid Build Coastguard Worker delete reply_msg;
620*6777b538SAndroid Build Coastguard Worker } else {
621*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
622*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
623*6777b538SAndroid Build Coastguard Worker }
624*6777b538SAndroid Build Coastguard Worker Done();
625*6777b538SAndroid Build Coastguard Worker }
626*6777b538SAndroid Build Coastguard Worker
OnAnswerDelay(Message * reply_msg)627*6777b538SAndroid Build Coastguard Worker void OnAnswerDelay(Message* reply_msg) override {
628*6777b538SAndroid Build Coastguard Worker if (close_channel_) {
629*6777b538SAndroid Build Coastguard Worker delete reply_msg;
630*6777b538SAndroid Build Coastguard Worker CloseChannel();
631*6777b538SAndroid Build Coastguard Worker } else {
632*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
633*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
634*6777b538SAndroid Build Coastguard Worker }
635*6777b538SAndroid Build Coastguard Worker }
636*6777b538SAndroid Build Coastguard Worker
637*6777b538SAndroid Build Coastguard Worker bool close_channel_;
638*6777b538SAndroid Build Coastguard Worker };
639*6777b538SAndroid Build Coastguard Worker
Recursive()640*6777b538SAndroid Build Coastguard Worker void Recursive() {
641*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
642*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
643*6777b538SAndroid Build Coastguard Worker workers.push_back(new RecursiveServer(true, std::move(pipe.handle0)));
644*6777b538SAndroid Build Coastguard Worker workers.push_back(new RecursiveClient(false, std::move(pipe.handle1)));
645*6777b538SAndroid Build Coastguard Worker RunTest(workers);
646*6777b538SAndroid Build Coastguard Worker }
647*6777b538SAndroid Build Coastguard Worker
648*6777b538SAndroid Build Coastguard Worker // Tests a server calling Send while another Send is pending.
TEST_F(IPCSyncChannelTest,Recursive)649*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, Recursive) {
650*6777b538SAndroid Build Coastguard Worker Recursive();
651*6777b538SAndroid Build Coastguard Worker }
652*6777b538SAndroid Build Coastguard Worker
653*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
654*6777b538SAndroid Build Coastguard Worker
RecursiveNoHang()655*6777b538SAndroid Build Coastguard Worker void RecursiveNoHang() {
656*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
657*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
658*6777b538SAndroid Build Coastguard Worker workers.push_back(new RecursiveServer(false, std::move(pipe.handle0)));
659*6777b538SAndroid Build Coastguard Worker workers.push_back(new RecursiveClient(true, std::move(pipe.handle1)));
660*6777b538SAndroid Build Coastguard Worker RunTest(workers);
661*6777b538SAndroid Build Coastguard Worker }
662*6777b538SAndroid Build Coastguard Worker
663*6777b538SAndroid Build Coastguard Worker // Tests that if a caller makes a sync call during an existing sync call and
664*6777b538SAndroid Build Coastguard Worker // the receiver dies, neither of the Send() calls hang.
TEST_F(IPCSyncChannelTest,RecursiveNoHang)665*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
666*6777b538SAndroid Build Coastguard Worker RecursiveNoHang();
667*6777b538SAndroid Build Coastguard Worker }
668*6777b538SAndroid Build Coastguard Worker
669*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
670*6777b538SAndroid Build Coastguard Worker
671*6777b538SAndroid Build Coastguard Worker class MultipleServer1 : public Worker {
672*6777b538SAndroid Build Coastguard Worker public:
MultipleServer1(mojo::ScopedMessagePipeHandle channel_handle)673*6777b538SAndroid Build Coastguard Worker explicit MultipleServer1(mojo::ScopedMessagePipeHandle channel_handle)
674*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER) {}
675*6777b538SAndroid Build Coastguard Worker
Run()676*6777b538SAndroid Build Coastguard Worker void Run() override {
677*6777b538SAndroid Build Coastguard Worker SendDouble(true);
678*6777b538SAndroid Build Coastguard Worker Done();
679*6777b538SAndroid Build Coastguard Worker }
680*6777b538SAndroid Build Coastguard Worker };
681*6777b538SAndroid Build Coastguard Worker
682*6777b538SAndroid Build Coastguard Worker class MultipleClient1 : public Worker {
683*6777b538SAndroid Build Coastguard Worker public:
MultipleClient1(WaitableEvent * client1_msg_received,WaitableEvent * client1_can_reply,mojo::ScopedMessagePipeHandle channel_handle)684*6777b538SAndroid Build Coastguard Worker MultipleClient1(WaitableEvent* client1_msg_received,
685*6777b538SAndroid Build Coastguard Worker WaitableEvent* client1_can_reply,
686*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
687*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
688*6777b538SAndroid Build Coastguard Worker client1_msg_received_(client1_msg_received),
689*6777b538SAndroid Build Coastguard Worker client1_can_reply_(client1_can_reply) {}
690*6777b538SAndroid Build Coastguard Worker
OnDouble(int in,int * out)691*6777b538SAndroid Build Coastguard Worker void OnDouble(int in, int* out) override {
692*6777b538SAndroid Build Coastguard Worker client1_msg_received_->Signal();
693*6777b538SAndroid Build Coastguard Worker *out = in * 2;
694*6777b538SAndroid Build Coastguard Worker client1_can_reply_->Wait();
695*6777b538SAndroid Build Coastguard Worker Done();
696*6777b538SAndroid Build Coastguard Worker }
697*6777b538SAndroid Build Coastguard Worker
698*6777b538SAndroid Build Coastguard Worker private:
699*6777b538SAndroid Build Coastguard Worker // This field is not a raw_ptr<> because it was filtered by the rewriter for:
700*6777b538SAndroid Build Coastguard Worker // #overlapping
701*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION WaitableEvent *client1_msg_received_, *client1_can_reply_;
702*6777b538SAndroid Build Coastguard Worker };
703*6777b538SAndroid Build Coastguard Worker
704*6777b538SAndroid Build Coastguard Worker class MultipleServer2 : public Worker {
705*6777b538SAndroid Build Coastguard Worker public:
MultipleServer2(mojo::ScopedMessagePipeHandle channel_handle)706*6777b538SAndroid Build Coastguard Worker explicit MultipleServer2(mojo::ScopedMessagePipeHandle channel_handle)
707*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER) {}
708*6777b538SAndroid Build Coastguard Worker
OnAnswer(int * result)709*6777b538SAndroid Build Coastguard Worker void OnAnswer(int* result) override {
710*6777b538SAndroid Build Coastguard Worker *result = 42;
711*6777b538SAndroid Build Coastguard Worker Done();
712*6777b538SAndroid Build Coastguard Worker }
713*6777b538SAndroid Build Coastguard Worker };
714*6777b538SAndroid Build Coastguard Worker
715*6777b538SAndroid Build Coastguard Worker class MultipleClient2 : public Worker {
716*6777b538SAndroid Build Coastguard Worker public:
MultipleClient2(WaitableEvent * client1_msg_received,WaitableEvent * client1_can_reply,mojo::ScopedMessagePipeHandle channel_handle)717*6777b538SAndroid Build Coastguard Worker MultipleClient2(WaitableEvent* client1_msg_received,
718*6777b538SAndroid Build Coastguard Worker WaitableEvent* client1_can_reply,
719*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
720*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
721*6777b538SAndroid Build Coastguard Worker client1_msg_received_(client1_msg_received),
722*6777b538SAndroid Build Coastguard Worker client1_can_reply_(client1_can_reply) {}
723*6777b538SAndroid Build Coastguard Worker
Run()724*6777b538SAndroid Build Coastguard Worker void Run() override {
725*6777b538SAndroid Build Coastguard Worker client1_msg_received_->Wait();
726*6777b538SAndroid Build Coastguard Worker SendAnswerToLife(true);
727*6777b538SAndroid Build Coastguard Worker client1_can_reply_->Signal();
728*6777b538SAndroid Build Coastguard Worker Done();
729*6777b538SAndroid Build Coastguard Worker }
730*6777b538SAndroid Build Coastguard Worker
731*6777b538SAndroid Build Coastguard Worker private:
732*6777b538SAndroid Build Coastguard Worker // This field is not a raw_ptr<> because it was filtered by the rewriter for:
733*6777b538SAndroid Build Coastguard Worker // #overlapping
734*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION WaitableEvent *client1_msg_received_, *client1_can_reply_;
735*6777b538SAndroid Build Coastguard Worker };
736*6777b538SAndroid Build Coastguard Worker
Multiple()737*6777b538SAndroid Build Coastguard Worker void Multiple() {
738*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
739*6777b538SAndroid Build Coastguard Worker
740*6777b538SAndroid Build Coastguard Worker // A shared worker thread so that server1 and server2 run on one thread.
741*6777b538SAndroid Build Coastguard Worker base::Thread worker_thread("Multiple");
742*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(worker_thread.Start());
743*6777b538SAndroid Build Coastguard Worker
744*6777b538SAndroid Build Coastguard Worker // Server1 sends a sync msg to client1, which blocks the reply until
745*6777b538SAndroid Build Coastguard Worker // server2 (which runs on the same worker thread as server1) responds
746*6777b538SAndroid Build Coastguard Worker // to a sync msg from client2.
747*6777b538SAndroid Build Coastguard Worker WaitableEvent client1_msg_received(
748*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::ResetPolicy::AUTOMATIC,
749*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
750*6777b538SAndroid Build Coastguard Worker WaitableEvent client1_can_reply(
751*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::ResetPolicy::AUTOMATIC,
752*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
753*6777b538SAndroid Build Coastguard Worker
754*6777b538SAndroid Build Coastguard Worker Worker* worker;
755*6777b538SAndroid Build Coastguard Worker
756*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe1, pipe2;
757*6777b538SAndroid Build Coastguard Worker worker = new MultipleServer2(std::move(pipe2.handle0));
758*6777b538SAndroid Build Coastguard Worker worker->OverrideThread(&worker_thread);
759*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
760*6777b538SAndroid Build Coastguard Worker
761*6777b538SAndroid Build Coastguard Worker worker = new MultipleClient2(&client1_msg_received, &client1_can_reply,
762*6777b538SAndroid Build Coastguard Worker std::move(pipe2.handle1));
763*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
764*6777b538SAndroid Build Coastguard Worker
765*6777b538SAndroid Build Coastguard Worker worker = new MultipleServer1(std::move(pipe1.handle0));
766*6777b538SAndroid Build Coastguard Worker worker->OverrideThread(&worker_thread);
767*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
768*6777b538SAndroid Build Coastguard Worker
769*6777b538SAndroid Build Coastguard Worker worker = new MultipleClient1(&client1_msg_received, &client1_can_reply,
770*6777b538SAndroid Build Coastguard Worker std::move(pipe1.handle1));
771*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
772*6777b538SAndroid Build Coastguard Worker
773*6777b538SAndroid Build Coastguard Worker RunTest(workers);
774*6777b538SAndroid Build Coastguard Worker }
775*6777b538SAndroid Build Coastguard Worker
776*6777b538SAndroid Build Coastguard Worker // Tests that multiple SyncObjects on the same listener thread can unblock each
777*6777b538SAndroid Build Coastguard Worker // other.
TEST_F(IPCSyncChannelTest,Multiple)778*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, Multiple) {
779*6777b538SAndroid Build Coastguard Worker Multiple();
780*6777b538SAndroid Build Coastguard Worker }
781*6777b538SAndroid Build Coastguard Worker
782*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
783*6777b538SAndroid Build Coastguard Worker
784*6777b538SAndroid Build Coastguard Worker // This class provides server side functionality to test the case where
785*6777b538SAndroid Build Coastguard Worker // multiple sync channels are in use on the same thread on the client.
786*6777b538SAndroid Build Coastguard Worker class QueuedReplyServer : public Worker {
787*6777b538SAndroid Build Coastguard Worker public:
QueuedReplyServer(base::Thread * listener_thread,mojo::ScopedMessagePipeHandle channel_handle,const std::string & reply_text)788*6777b538SAndroid Build Coastguard Worker QueuedReplyServer(base::Thread* listener_thread,
789*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle,
790*6777b538SAndroid Build Coastguard Worker const std::string& reply_text)
791*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER),
792*6777b538SAndroid Build Coastguard Worker reply_text_(reply_text) {
793*6777b538SAndroid Build Coastguard Worker Worker::OverrideThread(listener_thread);
794*6777b538SAndroid Build Coastguard Worker }
795*6777b538SAndroid Build Coastguard Worker
OnNestedTestMsg(Message * reply_msg)796*6777b538SAndroid Build Coastguard Worker void OnNestedTestMsg(Message* reply_msg) override {
797*6777b538SAndroid Build Coastguard Worker VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
798*6777b538SAndroid Build Coastguard Worker SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
799*6777b538SAndroid Build Coastguard Worker Send(reply_msg);
800*6777b538SAndroid Build Coastguard Worker Done();
801*6777b538SAndroid Build Coastguard Worker }
802*6777b538SAndroid Build Coastguard Worker
803*6777b538SAndroid Build Coastguard Worker private:
804*6777b538SAndroid Build Coastguard Worker std::string reply_text_;
805*6777b538SAndroid Build Coastguard Worker };
806*6777b538SAndroid Build Coastguard Worker
807*6777b538SAndroid Build Coastguard Worker // The QueuedReplyClient class provides functionality to test the case where
808*6777b538SAndroid Build Coastguard Worker // multiple sync channels are in use on the same thread.
809*6777b538SAndroid Build Coastguard Worker class QueuedReplyClient : public Worker {
810*6777b538SAndroid Build Coastguard Worker public:
QueuedReplyClient(base::Thread * listener_thread,mojo::ScopedMessagePipeHandle channel_handle,const std::string & expected_text)811*6777b538SAndroid Build Coastguard Worker QueuedReplyClient(base::Thread* listener_thread,
812*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle,
813*6777b538SAndroid Build Coastguard Worker const std::string& expected_text)
814*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
815*6777b538SAndroid Build Coastguard Worker expected_text_(expected_text) {
816*6777b538SAndroid Build Coastguard Worker Worker::OverrideThread(listener_thread);
817*6777b538SAndroid Build Coastguard Worker }
818*6777b538SAndroid Build Coastguard Worker
Run()819*6777b538SAndroid Build Coastguard Worker void Run() override {
820*6777b538SAndroid Build Coastguard Worker std::string response;
821*6777b538SAndroid Build Coastguard Worker SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
822*6777b538SAndroid Build Coastguard Worker bool result = Send(msg);
823*6777b538SAndroid Build Coastguard Worker DCHECK(result);
824*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(response, expected_text_);
825*6777b538SAndroid Build Coastguard Worker
826*6777b538SAndroid Build Coastguard Worker VLOG(1) << __FUNCTION__ << " Received reply: " << response;
827*6777b538SAndroid Build Coastguard Worker Done();
828*6777b538SAndroid Build Coastguard Worker }
829*6777b538SAndroid Build Coastguard Worker
830*6777b538SAndroid Build Coastguard Worker private:
831*6777b538SAndroid Build Coastguard Worker std::string expected_text_;
832*6777b538SAndroid Build Coastguard Worker };
833*6777b538SAndroid Build Coastguard Worker
QueuedReply()834*6777b538SAndroid Build Coastguard Worker void QueuedReply() {
835*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
836*6777b538SAndroid Build Coastguard Worker
837*6777b538SAndroid Build Coastguard Worker // A shared worker thread for servers
838*6777b538SAndroid Build Coastguard Worker base::Thread server_worker_thread("QueuedReply_ServerListener");
839*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(server_worker_thread.Start());
840*6777b538SAndroid Build Coastguard Worker
841*6777b538SAndroid Build Coastguard Worker base::Thread client_worker_thread("QueuedReply_ClientListener");
842*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(client_worker_thread.Start());
843*6777b538SAndroid Build Coastguard Worker
844*6777b538SAndroid Build Coastguard Worker Worker* worker;
845*6777b538SAndroid Build Coastguard Worker
846*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe1, pipe2;
847*6777b538SAndroid Build Coastguard Worker worker = new QueuedReplyServer(&server_worker_thread,
848*6777b538SAndroid Build Coastguard Worker std::move(pipe1.handle0), "Got first message");
849*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
850*6777b538SAndroid Build Coastguard Worker
851*6777b538SAndroid Build Coastguard Worker worker = new QueuedReplyServer(
852*6777b538SAndroid Build Coastguard Worker &server_worker_thread, std::move(pipe2.handle0), "Got second message");
853*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
854*6777b538SAndroid Build Coastguard Worker
855*6777b538SAndroid Build Coastguard Worker worker = new QueuedReplyClient(&client_worker_thread,
856*6777b538SAndroid Build Coastguard Worker std::move(pipe1.handle1), "Got first message");
857*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker worker = new QueuedReplyClient(
860*6777b538SAndroid Build Coastguard Worker &client_worker_thread, std::move(pipe2.handle1), "Got second message");
861*6777b538SAndroid Build Coastguard Worker workers.push_back(worker);
862*6777b538SAndroid Build Coastguard Worker
863*6777b538SAndroid Build Coastguard Worker RunTest(workers);
864*6777b538SAndroid Build Coastguard Worker }
865*6777b538SAndroid Build Coastguard Worker
866*6777b538SAndroid Build Coastguard Worker // While a blocking send is in progress, the listener thread might answer other
867*6777b538SAndroid Build Coastguard Worker // synchronous messages. This tests that if during the response to another
868*6777b538SAndroid Build Coastguard Worker // message the reply to the original messages comes, it is queued up correctly
869*6777b538SAndroid Build Coastguard Worker // and the original Send is unblocked later.
TEST_F(IPCSyncChannelTest,QueuedReply)870*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, QueuedReply) {
871*6777b538SAndroid Build Coastguard Worker QueuedReply();
872*6777b538SAndroid Build Coastguard Worker }
873*6777b538SAndroid Build Coastguard Worker
874*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
875*6777b538SAndroid Build Coastguard Worker
876*6777b538SAndroid Build Coastguard Worker class TestSyncMessageFilter : public SyncMessageFilter {
877*6777b538SAndroid Build Coastguard Worker public:
TestSyncMessageFilter(base::WaitableEvent * shutdown_event,Worker * worker,scoped_refptr<base::SingleThreadTaskRunner> task_runner)878*6777b538SAndroid Build Coastguard Worker TestSyncMessageFilter(
879*6777b538SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event,
880*6777b538SAndroid Build Coastguard Worker Worker* worker,
881*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> task_runner)
882*6777b538SAndroid Build Coastguard Worker : SyncMessageFilter(shutdown_event),
883*6777b538SAndroid Build Coastguard Worker worker_(worker),
884*6777b538SAndroid Build Coastguard Worker task_runner_(task_runner) {}
885*6777b538SAndroid Build Coastguard Worker
OnFilterAdded(Channel * channel)886*6777b538SAndroid Build Coastguard Worker void OnFilterAdded(Channel* channel) override {
887*6777b538SAndroid Build Coastguard Worker SyncMessageFilter::OnFilterAdded(channel);
888*6777b538SAndroid Build Coastguard Worker task_runner_->PostTask(
889*6777b538SAndroid Build Coastguard Worker FROM_HERE,
890*6777b538SAndroid Build Coastguard Worker base::BindOnce(&TestSyncMessageFilter::SendMessageOnHelperThread,
891*6777b538SAndroid Build Coastguard Worker this));
892*6777b538SAndroid Build Coastguard Worker }
893*6777b538SAndroid Build Coastguard Worker
SendMessageOnHelperThread()894*6777b538SAndroid Build Coastguard Worker void SendMessageOnHelperThread() {
895*6777b538SAndroid Build Coastguard Worker int answer = 0;
896*6777b538SAndroid Build Coastguard Worker bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
897*6777b538SAndroid Build Coastguard Worker DCHECK(result);
898*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(answer, 42);
899*6777b538SAndroid Build Coastguard Worker
900*6777b538SAndroid Build Coastguard Worker worker_->Done();
901*6777b538SAndroid Build Coastguard Worker }
902*6777b538SAndroid Build Coastguard Worker
903*6777b538SAndroid Build Coastguard Worker private:
904*6777b538SAndroid Build Coastguard Worker ~TestSyncMessageFilter() override = default;
905*6777b538SAndroid Build Coastguard Worker
906*6777b538SAndroid Build Coastguard Worker raw_ptr<Worker> worker_;
907*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
908*6777b538SAndroid Build Coastguard Worker };
909*6777b538SAndroid Build Coastguard Worker
910*6777b538SAndroid Build Coastguard Worker class SyncMessageFilterServer : public Worker {
911*6777b538SAndroid Build Coastguard Worker public:
SyncMessageFilterServer(mojo::ScopedMessagePipeHandle channel_handle)912*6777b538SAndroid Build Coastguard Worker explicit SyncMessageFilterServer(mojo::ScopedMessagePipeHandle channel_handle)
913*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
914*6777b538SAndroid Build Coastguard Worker "sync_message_filter_server",
915*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
916*6777b538SAndroid Build Coastguard Worker thread_("helper_thread") {
917*6777b538SAndroid Build Coastguard Worker base::Thread::Options options;
918*6777b538SAndroid Build Coastguard Worker options.message_pump_type = base::MessagePumpType::DEFAULT;
919*6777b538SAndroid Build Coastguard Worker thread_.StartWithOptions(std::move(options));
920*6777b538SAndroid Build Coastguard Worker filter_ = new TestSyncMessageFilter(shutdown_event(), this,
921*6777b538SAndroid Build Coastguard Worker thread_.task_runner());
922*6777b538SAndroid Build Coastguard Worker }
923*6777b538SAndroid Build Coastguard Worker
Run()924*6777b538SAndroid Build Coastguard Worker void Run() override {
925*6777b538SAndroid Build Coastguard Worker channel()->AddFilter(filter_.get());
926*6777b538SAndroid Build Coastguard Worker }
927*6777b538SAndroid Build Coastguard Worker
928*6777b538SAndroid Build Coastguard Worker base::Thread thread_;
929*6777b538SAndroid Build Coastguard Worker scoped_refptr<TestSyncMessageFilter> filter_;
930*6777b538SAndroid Build Coastguard Worker };
931*6777b538SAndroid Build Coastguard Worker
932*6777b538SAndroid Build Coastguard Worker // This class provides functionality to test the case that a Send on the sync
933*6777b538SAndroid Build Coastguard Worker // channel does not crash after the channel has been closed.
934*6777b538SAndroid Build Coastguard Worker class ServerSendAfterClose : public Worker {
935*6777b538SAndroid Build Coastguard Worker public:
ServerSendAfterClose(mojo::ScopedMessagePipeHandle channel_handle)936*6777b538SAndroid Build Coastguard Worker explicit ServerSendAfterClose(mojo::ScopedMessagePipeHandle channel_handle)
937*6777b538SAndroid Build Coastguard Worker : Worker(Channel::MODE_SERVER,
938*6777b538SAndroid Build Coastguard Worker "simpler_server",
939*6777b538SAndroid Build Coastguard Worker std::move(channel_handle)),
940*6777b538SAndroid Build Coastguard Worker send_result_(true) {}
941*6777b538SAndroid Build Coastguard Worker
SendDummy()942*6777b538SAndroid Build Coastguard Worker bool SendDummy() {
943*6777b538SAndroid Build Coastguard Worker ListenerThread()->task_runner()->PostTask(
944*6777b538SAndroid Build Coastguard Worker FROM_HERE,
945*6777b538SAndroid Build Coastguard Worker base::BindOnce(base::IgnoreResult(&ServerSendAfterClose::Send),
946*6777b538SAndroid Build Coastguard Worker base::Unretained(this), new SyncChannelTestMsg_NoArgs));
947*6777b538SAndroid Build Coastguard Worker return true;
948*6777b538SAndroid Build Coastguard Worker }
949*6777b538SAndroid Build Coastguard Worker
send_result() const950*6777b538SAndroid Build Coastguard Worker bool send_result() const {
951*6777b538SAndroid Build Coastguard Worker return send_result_;
952*6777b538SAndroid Build Coastguard Worker }
953*6777b538SAndroid Build Coastguard Worker
954*6777b538SAndroid Build Coastguard Worker private:
Run()955*6777b538SAndroid Build Coastguard Worker void Run() override {
956*6777b538SAndroid Build Coastguard Worker CloseChannel();
957*6777b538SAndroid Build Coastguard Worker Done();
958*6777b538SAndroid Build Coastguard Worker }
959*6777b538SAndroid Build Coastguard Worker
Send(Message * msg)960*6777b538SAndroid Build Coastguard Worker bool Send(Message* msg) override {
961*6777b538SAndroid Build Coastguard Worker send_result_ = Worker::Send(msg);
962*6777b538SAndroid Build Coastguard Worker Done();
963*6777b538SAndroid Build Coastguard Worker return send_result_;
964*6777b538SAndroid Build Coastguard Worker }
965*6777b538SAndroid Build Coastguard Worker
966*6777b538SAndroid Build Coastguard Worker bool send_result_;
967*6777b538SAndroid Build Coastguard Worker };
968*6777b538SAndroid Build Coastguard Worker
969*6777b538SAndroid Build Coastguard Worker // Tests basic synchronous call
TEST_F(IPCSyncChannelTest,SyncMessageFilter)970*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, SyncMessageFilter) {
971*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
972*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
973*6777b538SAndroid Build Coastguard Worker workers.push_back(new SyncMessageFilterServer(std::move(pipe.handle0)));
974*6777b538SAndroid Build Coastguard Worker workers.push_back(new SimpleClient(std::move(pipe.handle1)));
975*6777b538SAndroid Build Coastguard Worker RunTest(workers);
976*6777b538SAndroid Build Coastguard Worker }
977*6777b538SAndroid Build Coastguard Worker
978*6777b538SAndroid Build Coastguard Worker // Test the case when the channel is closed and a Send is attempted after that.
TEST_F(IPCSyncChannelTest,SendAfterClose)979*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, SendAfterClose) {
980*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe;
981*6777b538SAndroid Build Coastguard Worker ServerSendAfterClose server(std::move(pipe.handle0));
982*6777b538SAndroid Build Coastguard Worker server.Start();
983*6777b538SAndroid Build Coastguard Worker
984*6777b538SAndroid Build Coastguard Worker server.done_event()->Wait();
985*6777b538SAndroid Build Coastguard Worker server.done_event()->Reset();
986*6777b538SAndroid Build Coastguard Worker
987*6777b538SAndroid Build Coastguard Worker server.SendDummy();
988*6777b538SAndroid Build Coastguard Worker server.done_event()->Wait();
989*6777b538SAndroid Build Coastguard Worker
990*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(server.send_result());
991*6777b538SAndroid Build Coastguard Worker
992*6777b538SAndroid Build Coastguard Worker server.Shutdown();
993*6777b538SAndroid Build Coastguard Worker }
994*6777b538SAndroid Build Coastguard Worker
995*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
996*6777b538SAndroid Build Coastguard Worker
997*6777b538SAndroid Build Coastguard Worker class RestrictedDispatchServer : public Worker {
998*6777b538SAndroid Build Coastguard Worker public:
RestrictedDispatchServer(WaitableEvent * sent_ping_event,WaitableEvent * wait_event,mojo::ScopedMessagePipeHandle channel_handle)999*6777b538SAndroid Build Coastguard Worker RestrictedDispatchServer(WaitableEvent* sent_ping_event,
1000*6777b538SAndroid Build Coastguard Worker WaitableEvent* wait_event,
1001*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
1002*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER),
1003*6777b538SAndroid Build Coastguard Worker sent_ping_event_(sent_ping_event),
1004*6777b538SAndroid Build Coastguard Worker wait_event_(wait_event) {}
1005*6777b538SAndroid Build Coastguard Worker
OnDoPing(int ping)1006*6777b538SAndroid Build Coastguard Worker void OnDoPing(int ping) {
1007*6777b538SAndroid Build Coastguard Worker // Send an asynchronous message that unblocks the caller.
1008*6777b538SAndroid Build Coastguard Worker Message* msg = new SyncChannelTestMsg_Ping(ping);
1009*6777b538SAndroid Build Coastguard Worker msg->set_unblock(true);
1010*6777b538SAndroid Build Coastguard Worker Send(msg);
1011*6777b538SAndroid Build Coastguard Worker // Signal the event after the message has been sent on the channel, on the
1012*6777b538SAndroid Build Coastguard Worker // IPC thread.
1013*6777b538SAndroid Build Coastguard Worker ipc_thread().task_runner()->PostTask(
1014*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&RestrictedDispatchServer::OnPingSent,
1015*6777b538SAndroid Build Coastguard Worker base::Unretained(this)));
1016*6777b538SAndroid Build Coastguard Worker }
1017*6777b538SAndroid Build Coastguard Worker
OnPingTTL(int ping,int * out)1018*6777b538SAndroid Build Coastguard Worker void OnPingTTL(int ping, int* out) {
1019*6777b538SAndroid Build Coastguard Worker *out = ping;
1020*6777b538SAndroid Build Coastguard Worker wait_event_->Wait();
1021*6777b538SAndroid Build Coastguard Worker }
1022*6777b538SAndroid Build Coastguard Worker
ListenerThread()1023*6777b538SAndroid Build Coastguard Worker base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1024*6777b538SAndroid Build Coastguard Worker
1025*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1026*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1027*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message)
1028*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1029*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
1030*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1031*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1032*6777b538SAndroid Build Coastguard Worker return true;
1033*6777b538SAndroid Build Coastguard Worker }
1034*6777b538SAndroid Build Coastguard Worker
OnPingSent()1035*6777b538SAndroid Build Coastguard Worker void OnPingSent() {
1036*6777b538SAndroid Build Coastguard Worker sent_ping_event_->Signal();
1037*6777b538SAndroid Build Coastguard Worker }
1038*6777b538SAndroid Build Coastguard Worker
OnNoArgs()1039*6777b538SAndroid Build Coastguard Worker void OnNoArgs() { }
1040*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> sent_ping_event_;
1041*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> wait_event_;
1042*6777b538SAndroid Build Coastguard Worker };
1043*6777b538SAndroid Build Coastguard Worker
1044*6777b538SAndroid Build Coastguard Worker class NonRestrictedDispatchServer : public Worker {
1045*6777b538SAndroid Build Coastguard Worker public:
NonRestrictedDispatchServer(WaitableEvent * signal_event,mojo::ScopedMessagePipeHandle channel_handle)1046*6777b538SAndroid Build Coastguard Worker NonRestrictedDispatchServer(WaitableEvent* signal_event,
1047*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
1048*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER),
1049*6777b538SAndroid Build Coastguard Worker signal_event_(signal_event) {}
1050*6777b538SAndroid Build Coastguard Worker
ListenerThread()1051*6777b538SAndroid Build Coastguard Worker base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1052*6777b538SAndroid Build Coastguard Worker
OnDoPingTTL(int ping)1053*6777b538SAndroid Build Coastguard Worker void OnDoPingTTL(int ping) {
1054*6777b538SAndroid Build Coastguard Worker int value = 0;
1055*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_PingTTL(ping, &value));
1056*6777b538SAndroid Build Coastguard Worker signal_event_->Signal();
1057*6777b538SAndroid Build Coastguard Worker }
1058*6777b538SAndroid Build Coastguard Worker
1059*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1060*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1061*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message)
1062*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1063*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1064*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1065*6777b538SAndroid Build Coastguard Worker return true;
1066*6777b538SAndroid Build Coastguard Worker }
1067*6777b538SAndroid Build Coastguard Worker
OnNoArgs()1068*6777b538SAndroid Build Coastguard Worker void OnNoArgs() { }
1069*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> signal_event_;
1070*6777b538SAndroid Build Coastguard Worker };
1071*6777b538SAndroid Build Coastguard Worker
1072*6777b538SAndroid Build Coastguard Worker class RestrictedDispatchClient : public Worker {
1073*6777b538SAndroid Build Coastguard Worker public:
RestrictedDispatchClient(WaitableEvent * sent_ping_event,RestrictedDispatchServer * server,NonRestrictedDispatchServer * server2,int * success,mojo::ScopedMessagePipeHandle restricted_channel_handle,mojo::ScopedMessagePipeHandle non_restricted_channel_handle)1074*6777b538SAndroid Build Coastguard Worker RestrictedDispatchClient(
1075*6777b538SAndroid Build Coastguard Worker WaitableEvent* sent_ping_event,
1076*6777b538SAndroid Build Coastguard Worker RestrictedDispatchServer* server,
1077*6777b538SAndroid Build Coastguard Worker NonRestrictedDispatchServer* server2,
1078*6777b538SAndroid Build Coastguard Worker int* success,
1079*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle restricted_channel_handle,
1080*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle non_restricted_channel_handle)
1081*6777b538SAndroid Build Coastguard Worker : Worker(std::move(restricted_channel_handle), Channel::MODE_CLIENT),
1082*6777b538SAndroid Build Coastguard Worker ping_(0),
1083*6777b538SAndroid Build Coastguard Worker server_(server),
1084*6777b538SAndroid Build Coastguard Worker server2_(server2),
1085*6777b538SAndroid Build Coastguard Worker success_(success),
1086*6777b538SAndroid Build Coastguard Worker sent_ping_event_(sent_ping_event),
1087*6777b538SAndroid Build Coastguard Worker non_restricted_channel_handle_(
1088*6777b538SAndroid Build Coastguard Worker std::move(non_restricted_channel_handle)) {}
1089*6777b538SAndroid Build Coastguard Worker
Run()1090*6777b538SAndroid Build Coastguard Worker void Run() override {
1091*6777b538SAndroid Build Coastguard Worker // Incoming messages from our channel should only be dispatched when we
1092*6777b538SAndroid Build Coastguard Worker // send a message on that same channel.
1093*6777b538SAndroid Build Coastguard Worker channel()->SetRestrictDispatchChannelGroup(1);
1094*6777b538SAndroid Build Coastguard Worker
1095*6777b538SAndroid Build Coastguard Worker server_->ListenerThread()->task_runner()->PostTask(
1096*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&RestrictedDispatchServer::OnDoPing,
1097*6777b538SAndroid Build Coastguard Worker base::Unretained(server_), 1));
1098*6777b538SAndroid Build Coastguard Worker sent_ping_event_->Wait();
1099*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_NoArgs);
1100*6777b538SAndroid Build Coastguard Worker if (ping_ == 1)
1101*6777b538SAndroid Build Coastguard Worker ++*success_;
1102*6777b538SAndroid Build Coastguard Worker else
1103*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
1104*6777b538SAndroid Build Coastguard Worker
1105*6777b538SAndroid Build Coastguard Worker non_restricted_channel_ = SyncChannel::Create(
1106*6777b538SAndroid Build Coastguard Worker non_restricted_channel_handle_.release(), IPC::Channel::MODE_CLIENT,
1107*6777b538SAndroid Build Coastguard Worker this, ipc_thread().task_runner(),
1108*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault(), true,
1109*6777b538SAndroid Build Coastguard Worker shutdown_event());
1110*6777b538SAndroid Build Coastguard Worker
1111*6777b538SAndroid Build Coastguard Worker server_->ListenerThread()->task_runner()->PostTask(
1112*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&RestrictedDispatchServer::OnDoPing,
1113*6777b538SAndroid Build Coastguard Worker base::Unretained(server_), 2));
1114*6777b538SAndroid Build Coastguard Worker sent_ping_event_->Wait();
1115*6777b538SAndroid Build Coastguard Worker // Check that the incoming message is *not* dispatched when sending on the
1116*6777b538SAndroid Build Coastguard Worker // non restricted channel.
1117*6777b538SAndroid Build Coastguard Worker // TODO(piman): there is a possibility of a false positive race condition
1118*6777b538SAndroid Build Coastguard Worker // here, if the message that was posted on the server-side end of the pipe
1119*6777b538SAndroid Build Coastguard Worker // is not visible yet on the client side, but I don't know how to solve this
1120*6777b538SAndroid Build Coastguard Worker // without hooking into the internals of SyncChannel. I haven't seen it in
1121*6777b538SAndroid Build Coastguard Worker // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause
1122*6777b538SAndroid Build Coastguard Worker // the following to fail).
1123*6777b538SAndroid Build Coastguard Worker non_restricted_channel_->Send(new SyncChannelTestMsg_NoArgs);
1124*6777b538SAndroid Build Coastguard Worker if (ping_ == 1)
1125*6777b538SAndroid Build Coastguard Worker ++*success_;
1126*6777b538SAndroid Build Coastguard Worker else
1127*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Send dispatched message from restricted channel";
1128*6777b538SAndroid Build Coastguard Worker
1129*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_NoArgs);
1130*6777b538SAndroid Build Coastguard Worker if (ping_ == 2)
1131*6777b538SAndroid Build Coastguard Worker ++*success_;
1132*6777b538SAndroid Build Coastguard Worker else
1133*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
1134*6777b538SAndroid Build Coastguard Worker
1135*6777b538SAndroid Build Coastguard Worker // Check that the incoming message on the non-restricted channel is
1136*6777b538SAndroid Build Coastguard Worker // dispatched when sending on the restricted channel.
1137*6777b538SAndroid Build Coastguard Worker server2_->ListenerThread()->task_runner()->PostTask(
1138*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&NonRestrictedDispatchServer::OnDoPingTTL,
1139*6777b538SAndroid Build Coastguard Worker base::Unretained(server2_), 3));
1140*6777b538SAndroid Build Coastguard Worker int value = 0;
1141*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_PingTTL(4, &value));
1142*6777b538SAndroid Build Coastguard Worker if (ping_ == 3 && value == 4)
1143*6777b538SAndroid Build Coastguard Worker ++*success_;
1144*6777b538SAndroid Build Coastguard Worker else
1145*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Send failed to dispatch message from unrestricted channel";
1146*6777b538SAndroid Build Coastguard Worker
1147*6777b538SAndroid Build Coastguard Worker non_restricted_channel_->Send(new SyncChannelTestMsg_Done);
1148*6777b538SAndroid Build Coastguard Worker non_restricted_channel_.reset();
1149*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_Done);
1150*6777b538SAndroid Build Coastguard Worker Done();
1151*6777b538SAndroid Build Coastguard Worker }
1152*6777b538SAndroid Build Coastguard Worker
1153*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1154*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1155*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message)
1156*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing)
1157*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_PingTTL, OnPingTTL)
1158*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1159*6777b538SAndroid Build Coastguard Worker return true;
1160*6777b538SAndroid Build Coastguard Worker }
1161*6777b538SAndroid Build Coastguard Worker
OnPing(int ping)1162*6777b538SAndroid Build Coastguard Worker void OnPing(int ping) {
1163*6777b538SAndroid Build Coastguard Worker ping_ = ping;
1164*6777b538SAndroid Build Coastguard Worker }
1165*6777b538SAndroid Build Coastguard Worker
OnPingTTL(int ping,IPC::Message * reply)1166*6777b538SAndroid Build Coastguard Worker void OnPingTTL(int ping, IPC::Message* reply) {
1167*6777b538SAndroid Build Coastguard Worker ping_ = ping;
1168*6777b538SAndroid Build Coastguard Worker // This message comes from the NonRestrictedDispatchServer, we have to send
1169*6777b538SAndroid Build Coastguard Worker // the reply back manually.
1170*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_PingTTL::WriteReplyParams(reply, ping);
1171*6777b538SAndroid Build Coastguard Worker non_restricted_channel_->Send(reply);
1172*6777b538SAndroid Build Coastguard Worker }
1173*6777b538SAndroid Build Coastguard Worker
1174*6777b538SAndroid Build Coastguard Worker int ping_;
1175*6777b538SAndroid Build Coastguard Worker raw_ptr<RestrictedDispatchServer, DanglingUntriaged> server_;
1176*6777b538SAndroid Build Coastguard Worker raw_ptr<NonRestrictedDispatchServer, DanglingUntriaged> server2_;
1177*6777b538SAndroid Build Coastguard Worker raw_ptr<int> success_;
1178*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> sent_ping_event_;
1179*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SyncChannel> non_restricted_channel_;
1180*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle non_restricted_channel_handle_;
1181*6777b538SAndroid Build Coastguard Worker };
1182*6777b538SAndroid Build Coastguard Worker
TEST_F(IPCSyncChannelTest,RestrictedDispatch)1183*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, RestrictedDispatch) {
1184*6777b538SAndroid Build Coastguard Worker WaitableEvent sent_ping_event(
1185*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::ResetPolicy::AUTOMATIC,
1186*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1187*6777b538SAndroid Build Coastguard Worker WaitableEvent wait_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1188*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1189*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe restricted_pipe, non_restricted_pipe;
1190*6777b538SAndroid Build Coastguard Worker RestrictedDispatchServer* server = new RestrictedDispatchServer(
1191*6777b538SAndroid Build Coastguard Worker &sent_ping_event, &wait_event, std::move(restricted_pipe.handle0));
1192*6777b538SAndroid Build Coastguard Worker NonRestrictedDispatchServer* server2 = new NonRestrictedDispatchServer(
1193*6777b538SAndroid Build Coastguard Worker &wait_event, std::move(non_restricted_pipe.handle0));
1194*6777b538SAndroid Build Coastguard Worker
1195*6777b538SAndroid Build Coastguard Worker int success = 0;
1196*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
1197*6777b538SAndroid Build Coastguard Worker workers.push_back(server);
1198*6777b538SAndroid Build Coastguard Worker workers.push_back(server2);
1199*6777b538SAndroid Build Coastguard Worker workers.push_back(
1200*6777b538SAndroid Build Coastguard Worker new RestrictedDispatchClient(&sent_ping_event, server, server2, &success,
1201*6777b538SAndroid Build Coastguard Worker std::move(restricted_pipe.handle1),
1202*6777b538SAndroid Build Coastguard Worker std::move(non_restricted_pipe.handle1)));
1203*6777b538SAndroid Build Coastguard Worker RunTest(workers);
1204*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(4, success);
1205*6777b538SAndroid Build Coastguard Worker }
1206*6777b538SAndroid Build Coastguard Worker
1207*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
1208*6777b538SAndroid Build Coastguard Worker
1209*6777b538SAndroid Build Coastguard Worker // This test case inspired by crbug.com/108491
1210*6777b538SAndroid Build Coastguard Worker // We create two servers that use the same ListenerThread but have
1211*6777b538SAndroid Build Coastguard Worker // SetRestrictDispatchToSameChannel set to true.
1212*6777b538SAndroid Build Coastguard Worker // We create clients, then use some specific WaitableEvent wait/signalling to
1213*6777b538SAndroid Build Coastguard Worker // ensure that messages get dispatched in a way that causes a deadlock due to
1214*6777b538SAndroid Build Coastguard Worker // a nested dispatch and an eligible message in a higher-level dispatch's
1215*6777b538SAndroid Build Coastguard Worker // delayed_queue. Specifically, we start with client1 about so send an
1216*6777b538SAndroid Build Coastguard Worker // unblocking message to server1, while the shared listener thread for the
1217*6777b538SAndroid Build Coastguard Worker // servers server1 and server2 is about to send a non-unblocking message to
1218*6777b538SAndroid Build Coastguard Worker // client1. At the same time, client2 will be about to send an unblocking
1219*6777b538SAndroid Build Coastguard Worker // message to server2. Server1 will handle the client1->server1 message by
1220*6777b538SAndroid Build Coastguard Worker // telling server2 to send a non-unblocking message to client2.
1221*6777b538SAndroid Build Coastguard Worker // What should happen is that the send to server2 should find the pending,
1222*6777b538SAndroid Build Coastguard Worker // same-context client2->server2 message to dispatch, causing client2 to
1223*6777b538SAndroid Build Coastguard Worker // unblock then handle the server2->client2 message, so that the shared
1224*6777b538SAndroid Build Coastguard Worker // servers' listener thread can then respond to the client1->server1 message.
1225*6777b538SAndroid Build Coastguard Worker // Then client1 can handle the non-unblocking server1->client1 message.
1226*6777b538SAndroid Build Coastguard Worker // The old code would end up in a state where the server2->client2 message is
1227*6777b538SAndroid Build Coastguard Worker // sent, but the client2->server2 message (which is eligible for dispatch, and
1228*6777b538SAndroid Build Coastguard Worker // which is what client2 is waiting for) is stashed in a local delayed_queue
1229*6777b538SAndroid Build Coastguard Worker // that has server1's channel context, causing a deadlock.
1230*6777b538SAndroid Build Coastguard Worker // WaitableEvents in the events array are used to:
1231*6777b538SAndroid Build Coastguard Worker // event 0: indicate to client1 that server listener is in OnDoServerTask
1232*6777b538SAndroid Build Coastguard Worker // event 1: indicate to client1 that client2 listener is in OnDoClient2Task
1233*6777b538SAndroid Build Coastguard Worker // event 2: indicate to server1 that client2 listener is in OnDoClient2Task
1234*6777b538SAndroid Build Coastguard Worker // event 3: indicate to client2 that server listener is in OnDoServerTask
1235*6777b538SAndroid Build Coastguard Worker
1236*6777b538SAndroid Build Coastguard Worker class RestrictedDispatchDeadlockServer : public Worker {
1237*6777b538SAndroid Build Coastguard Worker public:
RestrictedDispatchDeadlockServer(int server_num,WaitableEvent * server_ready_event,WaitableEvent ** events,RestrictedDispatchDeadlockServer * peer,mojo::ScopedMessagePipeHandle channel_handle)1238*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockServer(int server_num,
1239*6777b538SAndroid Build Coastguard Worker WaitableEvent* server_ready_event,
1240*6777b538SAndroid Build Coastguard Worker WaitableEvent** events,
1241*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockServer* peer,
1242*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
1243*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER),
1244*6777b538SAndroid Build Coastguard Worker server_num_(server_num),
1245*6777b538SAndroid Build Coastguard Worker server_ready_event_(server_ready_event),
1246*6777b538SAndroid Build Coastguard Worker events_(events),
1247*6777b538SAndroid Build Coastguard Worker peer_(peer) {}
1248*6777b538SAndroid Build Coastguard Worker
OnDoServerTask()1249*6777b538SAndroid Build Coastguard Worker void OnDoServerTask() {
1250*6777b538SAndroid Build Coastguard Worker events_[3]->Signal();
1251*6777b538SAndroid Build Coastguard Worker events_[2]->Wait();
1252*6777b538SAndroid Build Coastguard Worker events_[0]->Signal();
1253*6777b538SAndroid Build Coastguard Worker SendMessageToClient();
1254*6777b538SAndroid Build Coastguard Worker }
1255*6777b538SAndroid Build Coastguard Worker
Run()1256*6777b538SAndroid Build Coastguard Worker void Run() override {
1257*6777b538SAndroid Build Coastguard Worker channel()->SetRestrictDispatchChannelGroup(1);
1258*6777b538SAndroid Build Coastguard Worker server_ready_event_->Signal();
1259*6777b538SAndroid Build Coastguard Worker }
1260*6777b538SAndroid Build Coastguard Worker
ListenerThread()1261*6777b538SAndroid Build Coastguard Worker base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1262*6777b538SAndroid Build Coastguard Worker
1263*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1264*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1265*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message)
1266*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1267*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1268*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1269*6777b538SAndroid Build Coastguard Worker return true;
1270*6777b538SAndroid Build Coastguard Worker }
1271*6777b538SAndroid Build Coastguard Worker
OnNoArgs()1272*6777b538SAndroid Build Coastguard Worker void OnNoArgs() {
1273*6777b538SAndroid Build Coastguard Worker if (server_num_ == 1) {
1274*6777b538SAndroid Build Coastguard Worker DCHECK(peer_);
1275*6777b538SAndroid Build Coastguard Worker peer_->SendMessageToClient();
1276*6777b538SAndroid Build Coastguard Worker }
1277*6777b538SAndroid Build Coastguard Worker }
1278*6777b538SAndroid Build Coastguard Worker
SendMessageToClient()1279*6777b538SAndroid Build Coastguard Worker void SendMessageToClient() {
1280*6777b538SAndroid Build Coastguard Worker Message* msg = new SyncChannelTestMsg_NoArgs;
1281*6777b538SAndroid Build Coastguard Worker msg->set_unblock(false);
1282*6777b538SAndroid Build Coastguard Worker DCHECK(!msg->should_unblock());
1283*6777b538SAndroid Build Coastguard Worker Send(msg);
1284*6777b538SAndroid Build Coastguard Worker }
1285*6777b538SAndroid Build Coastguard Worker
1286*6777b538SAndroid Build Coastguard Worker int server_num_;
1287*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> server_ready_event_;
1288*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent*, AllowPtrArithmetic> events_;
1289*6777b538SAndroid Build Coastguard Worker raw_ptr<RestrictedDispatchDeadlockServer, DanglingUntriaged> peer_;
1290*6777b538SAndroid Build Coastguard Worker };
1291*6777b538SAndroid Build Coastguard Worker
1292*6777b538SAndroid Build Coastguard Worker class RestrictedDispatchDeadlockClient2 : public Worker {
1293*6777b538SAndroid Build Coastguard Worker public:
RestrictedDispatchDeadlockClient2(RestrictedDispatchDeadlockServer * server,WaitableEvent * server_ready_event,WaitableEvent ** events,mojo::ScopedMessagePipeHandle channel_handle)1294*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockClient2(
1295*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockServer* server,
1296*6777b538SAndroid Build Coastguard Worker WaitableEvent* server_ready_event,
1297*6777b538SAndroid Build Coastguard Worker WaitableEvent** events,
1298*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
1299*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
1300*6777b538SAndroid Build Coastguard Worker server_ready_event_(server_ready_event),
1301*6777b538SAndroid Build Coastguard Worker events_(events),
1302*6777b538SAndroid Build Coastguard Worker received_msg_(false),
1303*6777b538SAndroid Build Coastguard Worker received_noarg_reply_(false),
1304*6777b538SAndroid Build Coastguard Worker done_issued_(false) {}
1305*6777b538SAndroid Build Coastguard Worker
Run()1306*6777b538SAndroid Build Coastguard Worker void Run() override {
1307*6777b538SAndroid Build Coastguard Worker server_ready_event_->Wait();
1308*6777b538SAndroid Build Coastguard Worker }
1309*6777b538SAndroid Build Coastguard Worker
OnDoClient2Task()1310*6777b538SAndroid Build Coastguard Worker void OnDoClient2Task() {
1311*6777b538SAndroid Build Coastguard Worker events_[3]->Wait();
1312*6777b538SAndroid Build Coastguard Worker events_[1]->Signal();
1313*6777b538SAndroid Build Coastguard Worker events_[2]->Signal();
1314*6777b538SAndroid Build Coastguard Worker DCHECK(received_msg_ == false);
1315*6777b538SAndroid Build Coastguard Worker
1316*6777b538SAndroid Build Coastguard Worker Message* message = new SyncChannelTestMsg_NoArgs;
1317*6777b538SAndroid Build Coastguard Worker message->set_unblock(true);
1318*6777b538SAndroid Build Coastguard Worker Send(message);
1319*6777b538SAndroid Build Coastguard Worker received_noarg_reply_ = true;
1320*6777b538SAndroid Build Coastguard Worker }
1321*6777b538SAndroid Build Coastguard Worker
ListenerThread()1322*6777b538SAndroid Build Coastguard Worker base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1323*6777b538SAndroid Build Coastguard Worker
1324*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1325*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1326*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message)
1327*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1328*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1329*6777b538SAndroid Build Coastguard Worker return true;
1330*6777b538SAndroid Build Coastguard Worker }
1331*6777b538SAndroid Build Coastguard Worker
OnNoArgs()1332*6777b538SAndroid Build Coastguard Worker void OnNoArgs() {
1333*6777b538SAndroid Build Coastguard Worker received_msg_ = true;
1334*6777b538SAndroid Build Coastguard Worker PossiblyDone();
1335*6777b538SAndroid Build Coastguard Worker }
1336*6777b538SAndroid Build Coastguard Worker
PossiblyDone()1337*6777b538SAndroid Build Coastguard Worker void PossiblyDone() {
1338*6777b538SAndroid Build Coastguard Worker if (received_noarg_reply_ && received_msg_) {
1339*6777b538SAndroid Build Coastguard Worker DCHECK(done_issued_ == false);
1340*6777b538SAndroid Build Coastguard Worker done_issued_ = true;
1341*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_Done);
1342*6777b538SAndroid Build Coastguard Worker Done();
1343*6777b538SAndroid Build Coastguard Worker }
1344*6777b538SAndroid Build Coastguard Worker }
1345*6777b538SAndroid Build Coastguard Worker
1346*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> server_ready_event_;
1347*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent*, AllowPtrArithmetic> events_;
1348*6777b538SAndroid Build Coastguard Worker bool received_msg_;
1349*6777b538SAndroid Build Coastguard Worker bool received_noarg_reply_;
1350*6777b538SAndroid Build Coastguard Worker bool done_issued_;
1351*6777b538SAndroid Build Coastguard Worker };
1352*6777b538SAndroid Build Coastguard Worker
1353*6777b538SAndroid Build Coastguard Worker class RestrictedDispatchDeadlockClient1 : public Worker {
1354*6777b538SAndroid Build Coastguard Worker public:
RestrictedDispatchDeadlockClient1(RestrictedDispatchDeadlockServer * server,RestrictedDispatchDeadlockClient2 * peer,WaitableEvent * server_ready_event,WaitableEvent ** events,mojo::ScopedMessagePipeHandle channel_handle)1355*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockClient1(
1356*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockServer* server,
1357*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockClient2* peer,
1358*6777b538SAndroid Build Coastguard Worker WaitableEvent* server_ready_event,
1359*6777b538SAndroid Build Coastguard Worker WaitableEvent** events,
1360*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
1361*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
1362*6777b538SAndroid Build Coastguard Worker server_(server),
1363*6777b538SAndroid Build Coastguard Worker peer_(peer),
1364*6777b538SAndroid Build Coastguard Worker server_ready_event_(server_ready_event),
1365*6777b538SAndroid Build Coastguard Worker events_(events),
1366*6777b538SAndroid Build Coastguard Worker received_msg_(false),
1367*6777b538SAndroid Build Coastguard Worker received_noarg_reply_(false),
1368*6777b538SAndroid Build Coastguard Worker done_issued_(false) {}
1369*6777b538SAndroid Build Coastguard Worker
Run()1370*6777b538SAndroid Build Coastguard Worker void Run() override {
1371*6777b538SAndroid Build Coastguard Worker server_ready_event_->Wait();
1372*6777b538SAndroid Build Coastguard Worker server_->ListenerThread()->task_runner()->PostTask(
1373*6777b538SAndroid Build Coastguard Worker FROM_HERE,
1374*6777b538SAndroid Build Coastguard Worker base::BindOnce(&RestrictedDispatchDeadlockServer::OnDoServerTask,
1375*6777b538SAndroid Build Coastguard Worker base::Unretained(server_)));
1376*6777b538SAndroid Build Coastguard Worker peer_->ListenerThread()->task_runner()->PostTask(
1377*6777b538SAndroid Build Coastguard Worker FROM_HERE,
1378*6777b538SAndroid Build Coastguard Worker base::BindOnce(&RestrictedDispatchDeadlockClient2::OnDoClient2Task,
1379*6777b538SAndroid Build Coastguard Worker base::Unretained(peer_)));
1380*6777b538SAndroid Build Coastguard Worker events_[0]->Wait();
1381*6777b538SAndroid Build Coastguard Worker events_[1]->Wait();
1382*6777b538SAndroid Build Coastguard Worker DCHECK(received_msg_ == false);
1383*6777b538SAndroid Build Coastguard Worker
1384*6777b538SAndroid Build Coastguard Worker Message* message = new SyncChannelTestMsg_NoArgs;
1385*6777b538SAndroid Build Coastguard Worker message->set_unblock(true);
1386*6777b538SAndroid Build Coastguard Worker Send(message);
1387*6777b538SAndroid Build Coastguard Worker received_noarg_reply_ = true;
1388*6777b538SAndroid Build Coastguard Worker PossiblyDone();
1389*6777b538SAndroid Build Coastguard Worker }
1390*6777b538SAndroid Build Coastguard Worker
1391*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1392*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1393*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message)
1394*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1395*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1396*6777b538SAndroid Build Coastguard Worker return true;
1397*6777b538SAndroid Build Coastguard Worker }
1398*6777b538SAndroid Build Coastguard Worker
OnNoArgs()1399*6777b538SAndroid Build Coastguard Worker void OnNoArgs() {
1400*6777b538SAndroid Build Coastguard Worker received_msg_ = true;
1401*6777b538SAndroid Build Coastguard Worker PossiblyDone();
1402*6777b538SAndroid Build Coastguard Worker }
1403*6777b538SAndroid Build Coastguard Worker
PossiblyDone()1404*6777b538SAndroid Build Coastguard Worker void PossiblyDone() {
1405*6777b538SAndroid Build Coastguard Worker if (received_noarg_reply_ && received_msg_) {
1406*6777b538SAndroid Build Coastguard Worker DCHECK(done_issued_ == false);
1407*6777b538SAndroid Build Coastguard Worker done_issued_ = true;
1408*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_Done);
1409*6777b538SAndroid Build Coastguard Worker Done();
1410*6777b538SAndroid Build Coastguard Worker }
1411*6777b538SAndroid Build Coastguard Worker }
1412*6777b538SAndroid Build Coastguard Worker
1413*6777b538SAndroid Build Coastguard Worker raw_ptr<RestrictedDispatchDeadlockServer, DanglingUntriaged> server_;
1414*6777b538SAndroid Build Coastguard Worker raw_ptr<RestrictedDispatchDeadlockClient2, DanglingUntriaged> peer_;
1415*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> server_ready_event_;
1416*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent*, AllowPtrArithmetic> events_;
1417*6777b538SAndroid Build Coastguard Worker bool received_msg_;
1418*6777b538SAndroid Build Coastguard Worker bool received_noarg_reply_;
1419*6777b538SAndroid Build Coastguard Worker bool done_issued_;
1420*6777b538SAndroid Build Coastguard Worker };
1421*6777b538SAndroid Build Coastguard Worker
TEST_F(IPCSyncChannelTest,RestrictedDispatchDeadlock)1422*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) {
1423*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
1424*6777b538SAndroid Build Coastguard Worker
1425*6777b538SAndroid Build Coastguard Worker // A shared worker thread so that server1 and server2 run on one thread.
1426*6777b538SAndroid Build Coastguard Worker base::Thread worker_thread("RestrictedDispatchDeadlock");
1427*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(worker_thread.Start());
1428*6777b538SAndroid Build Coastguard Worker
1429*6777b538SAndroid Build Coastguard Worker WaitableEvent server1_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1430*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1431*6777b538SAndroid Build Coastguard Worker WaitableEvent server2_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1432*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1433*6777b538SAndroid Build Coastguard Worker
1434*6777b538SAndroid Build Coastguard Worker WaitableEvent event0(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1435*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1436*6777b538SAndroid Build Coastguard Worker WaitableEvent event1(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1437*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1438*6777b538SAndroid Build Coastguard Worker WaitableEvent event2(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1439*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1440*6777b538SAndroid Build Coastguard Worker WaitableEvent event3(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1441*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1442*6777b538SAndroid Build Coastguard Worker WaitableEvent* events[4] = {&event0, &event1, &event2, &event3};
1443*6777b538SAndroid Build Coastguard Worker
1444*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockServer* server1;
1445*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockServer* server2;
1446*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockClient1* client1;
1447*6777b538SAndroid Build Coastguard Worker RestrictedDispatchDeadlockClient2* client2;
1448*6777b538SAndroid Build Coastguard Worker
1449*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe1, pipe2;
1450*6777b538SAndroid Build Coastguard Worker server2 = new RestrictedDispatchDeadlockServer(
1451*6777b538SAndroid Build Coastguard Worker 2, &server2_ready, events, nullptr, std::move(pipe2.handle0));
1452*6777b538SAndroid Build Coastguard Worker server2->OverrideThread(&worker_thread);
1453*6777b538SAndroid Build Coastguard Worker workers.push_back(server2);
1454*6777b538SAndroid Build Coastguard Worker
1455*6777b538SAndroid Build Coastguard Worker client2 = new RestrictedDispatchDeadlockClient2(
1456*6777b538SAndroid Build Coastguard Worker server2, &server2_ready, events, std::move(pipe2.handle1));
1457*6777b538SAndroid Build Coastguard Worker workers.push_back(client2);
1458*6777b538SAndroid Build Coastguard Worker
1459*6777b538SAndroid Build Coastguard Worker server1 = new RestrictedDispatchDeadlockServer(
1460*6777b538SAndroid Build Coastguard Worker 1, &server1_ready, events, server2, std::move(pipe1.handle0));
1461*6777b538SAndroid Build Coastguard Worker server1->OverrideThread(&worker_thread);
1462*6777b538SAndroid Build Coastguard Worker workers.push_back(server1);
1463*6777b538SAndroid Build Coastguard Worker
1464*6777b538SAndroid Build Coastguard Worker client1 = new RestrictedDispatchDeadlockClient1(
1465*6777b538SAndroid Build Coastguard Worker server1, client2, &server1_ready, events, std::move(pipe1.handle1));
1466*6777b538SAndroid Build Coastguard Worker workers.push_back(client1);
1467*6777b538SAndroid Build Coastguard Worker
1468*6777b538SAndroid Build Coastguard Worker RunTest(workers);
1469*6777b538SAndroid Build Coastguard Worker }
1470*6777b538SAndroid Build Coastguard Worker
1471*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
1472*6777b538SAndroid Build Coastguard Worker
1473*6777b538SAndroid Build Coastguard Worker // This test case inspired by crbug.com/120530
1474*6777b538SAndroid Build Coastguard Worker // We create 4 workers that pipe to each other W1->W2->W3->W4->W1 then we send a
1475*6777b538SAndroid Build Coastguard Worker // message that recurses through 3, 4 or 5 steps to make sure, say, W1 can
1476*6777b538SAndroid Build Coastguard Worker // re-enter when called from W4 while it's sending a message to W2.
1477*6777b538SAndroid Build Coastguard Worker // The first worker drives the whole test so it must be treated specially.
1478*6777b538SAndroid Build Coastguard Worker
1479*6777b538SAndroid Build Coastguard Worker class RestrictedDispatchPipeWorker : public Worker {
1480*6777b538SAndroid Build Coastguard Worker public:
RestrictedDispatchPipeWorker(mojo::ScopedMessagePipeHandle channel_handle1,WaitableEvent * event1,mojo::ScopedMessagePipeHandle channel_handle2,WaitableEvent * event2,int group,int * success)1481*6777b538SAndroid Build Coastguard Worker RestrictedDispatchPipeWorker(mojo::ScopedMessagePipeHandle channel_handle1,
1482*6777b538SAndroid Build Coastguard Worker WaitableEvent* event1,
1483*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle2,
1484*6777b538SAndroid Build Coastguard Worker WaitableEvent* event2,
1485*6777b538SAndroid Build Coastguard Worker int group,
1486*6777b538SAndroid Build Coastguard Worker int* success)
1487*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle1), Channel::MODE_SERVER),
1488*6777b538SAndroid Build Coastguard Worker event1_(event1),
1489*6777b538SAndroid Build Coastguard Worker event2_(event2),
1490*6777b538SAndroid Build Coastguard Worker other_channel_handle_(std::move(channel_handle2)),
1491*6777b538SAndroid Build Coastguard Worker group_(group),
1492*6777b538SAndroid Build Coastguard Worker success_(success) {}
1493*6777b538SAndroid Build Coastguard Worker
OnPingTTL(int ping,int * ret)1494*6777b538SAndroid Build Coastguard Worker void OnPingTTL(int ping, int* ret) {
1495*6777b538SAndroid Build Coastguard Worker *ret = 0;
1496*6777b538SAndroid Build Coastguard Worker if (!ping)
1497*6777b538SAndroid Build Coastguard Worker return;
1498*6777b538SAndroid Build Coastguard Worker other_channel_->Send(new SyncChannelTestMsg_PingTTL(ping - 1, ret));
1499*6777b538SAndroid Build Coastguard Worker ++*ret;
1500*6777b538SAndroid Build Coastguard Worker }
1501*6777b538SAndroid Build Coastguard Worker
OnDone()1502*6777b538SAndroid Build Coastguard Worker void OnDone() {
1503*6777b538SAndroid Build Coastguard Worker if (is_first())
1504*6777b538SAndroid Build Coastguard Worker return;
1505*6777b538SAndroid Build Coastguard Worker other_channel_->Send(new SyncChannelTestMsg_Done);
1506*6777b538SAndroid Build Coastguard Worker other_channel_.reset();
1507*6777b538SAndroid Build Coastguard Worker Done();
1508*6777b538SAndroid Build Coastguard Worker }
1509*6777b538SAndroid Build Coastguard Worker
Run()1510*6777b538SAndroid Build Coastguard Worker void Run() override {
1511*6777b538SAndroid Build Coastguard Worker channel()->SetRestrictDispatchChannelGroup(group_);
1512*6777b538SAndroid Build Coastguard Worker if (is_first())
1513*6777b538SAndroid Build Coastguard Worker event1_->Signal();
1514*6777b538SAndroid Build Coastguard Worker event2_->Wait();
1515*6777b538SAndroid Build Coastguard Worker other_channel_ = SyncChannel::Create(
1516*6777b538SAndroid Build Coastguard Worker other_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
1517*6777b538SAndroid Build Coastguard Worker ipc_thread().task_runner(),
1518*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault(), true,
1519*6777b538SAndroid Build Coastguard Worker shutdown_event());
1520*6777b538SAndroid Build Coastguard Worker other_channel_->SetRestrictDispatchChannelGroup(group_);
1521*6777b538SAndroid Build Coastguard Worker if (!is_first()) {
1522*6777b538SAndroid Build Coastguard Worker event1_->Signal();
1523*6777b538SAndroid Build Coastguard Worker return;
1524*6777b538SAndroid Build Coastguard Worker }
1525*6777b538SAndroid Build Coastguard Worker *success_ = 0;
1526*6777b538SAndroid Build Coastguard Worker int value = 0;
1527*6777b538SAndroid Build Coastguard Worker OnPingTTL(3, &value);
1528*6777b538SAndroid Build Coastguard Worker *success_ += (value == 3);
1529*6777b538SAndroid Build Coastguard Worker OnPingTTL(4, &value);
1530*6777b538SAndroid Build Coastguard Worker *success_ += (value == 4);
1531*6777b538SAndroid Build Coastguard Worker OnPingTTL(5, &value);
1532*6777b538SAndroid Build Coastguard Worker *success_ += (value == 5);
1533*6777b538SAndroid Build Coastguard Worker other_channel_->Send(new SyncChannelTestMsg_Done);
1534*6777b538SAndroid Build Coastguard Worker other_channel_.reset();
1535*6777b538SAndroid Build Coastguard Worker Done();
1536*6777b538SAndroid Build Coastguard Worker }
1537*6777b538SAndroid Build Coastguard Worker
is_first()1538*6777b538SAndroid Build Coastguard Worker bool is_first() { return !!success_; }
1539*6777b538SAndroid Build Coastguard Worker
1540*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1541*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1542*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchPipeWorker, message)
1543*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
1544*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, OnDone)
1545*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1546*6777b538SAndroid Build Coastguard Worker return true;
1547*6777b538SAndroid Build Coastguard Worker }
1548*6777b538SAndroid Build Coastguard Worker
1549*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SyncChannel> other_channel_;
1550*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> event1_;
1551*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> event2_;
1552*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle other_channel_handle_;
1553*6777b538SAndroid Build Coastguard Worker int group_;
1554*6777b538SAndroid Build Coastguard Worker raw_ptr<int> success_;
1555*6777b538SAndroid Build Coastguard Worker };
1556*6777b538SAndroid Build Coastguard Worker
1557*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
1558*6777b538SAndroid Build Coastguard Worker #define MAYBE_RestrictedDispatch4WayDeadlock \
1559*6777b538SAndroid Build Coastguard Worker DISABLED_RestrictedDispatch4WayDeadlock
1560*6777b538SAndroid Build Coastguard Worker #else
1561*6777b538SAndroid Build Coastguard Worker #define MAYBE_RestrictedDispatch4WayDeadlock RestrictedDispatch4WayDeadlock
1562*6777b538SAndroid Build Coastguard Worker #endif
TEST_F(IPCSyncChannelTest,MAYBE_RestrictedDispatch4WayDeadlock)1563*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, MAYBE_RestrictedDispatch4WayDeadlock) {
1564*6777b538SAndroid Build Coastguard Worker int success = 0;
1565*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
1566*6777b538SAndroid Build Coastguard Worker WaitableEvent event0(base::WaitableEvent::ResetPolicy::MANUAL,
1567*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1568*6777b538SAndroid Build Coastguard Worker WaitableEvent event1(base::WaitableEvent::ResetPolicy::MANUAL,
1569*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1570*6777b538SAndroid Build Coastguard Worker WaitableEvent event2(base::WaitableEvent::ResetPolicy::MANUAL,
1571*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1572*6777b538SAndroid Build Coastguard Worker WaitableEvent event3(base::WaitableEvent::ResetPolicy::MANUAL,
1573*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1574*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe0, pipe1, pipe2, pipe3;
1575*6777b538SAndroid Build Coastguard Worker workers.push_back(new RestrictedDispatchPipeWorker(
1576*6777b538SAndroid Build Coastguard Worker std::move(pipe0.handle0), &event0, std::move(pipe1.handle1), &event1, 1,
1577*6777b538SAndroid Build Coastguard Worker &success));
1578*6777b538SAndroid Build Coastguard Worker workers.push_back(new RestrictedDispatchPipeWorker(
1579*6777b538SAndroid Build Coastguard Worker std::move(pipe1.handle0), &event1, std::move(pipe2.handle1), &event2, 2,
1580*6777b538SAndroid Build Coastguard Worker nullptr));
1581*6777b538SAndroid Build Coastguard Worker workers.push_back(new RestrictedDispatchPipeWorker(
1582*6777b538SAndroid Build Coastguard Worker std::move(pipe2.handle0), &event2, std::move(pipe3.handle1), &event3, 3,
1583*6777b538SAndroid Build Coastguard Worker nullptr));
1584*6777b538SAndroid Build Coastguard Worker workers.push_back(new RestrictedDispatchPipeWorker(
1585*6777b538SAndroid Build Coastguard Worker std::move(pipe3.handle0), &event3, std::move(pipe0.handle1), &event0, 4,
1586*6777b538SAndroid Build Coastguard Worker nullptr));
1587*6777b538SAndroid Build Coastguard Worker RunTest(workers);
1588*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(3, success);
1589*6777b538SAndroid Build Coastguard Worker }
1590*6777b538SAndroid Build Coastguard Worker
1591*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
1592*6777b538SAndroid Build Coastguard Worker
1593*6777b538SAndroid Build Coastguard Worker // This test case inspired by crbug.com/122443
1594*6777b538SAndroid Build Coastguard Worker // We want to make sure a reply message with the unblock flag set correctly
1595*6777b538SAndroid Build Coastguard Worker // behaves as a reply, not a regular message.
1596*6777b538SAndroid Build Coastguard Worker // We have 3 workers. Server1 will send a message to Server2 (which will block),
1597*6777b538SAndroid Build Coastguard Worker // during which it will dispatch a message comming from Client, at which point
1598*6777b538SAndroid Build Coastguard Worker // it will send another message to Server2. While sending that second message it
1599*6777b538SAndroid Build Coastguard Worker // will receive a reply from Server1 with the unblock flag.
1600*6777b538SAndroid Build Coastguard Worker
1601*6777b538SAndroid Build Coastguard Worker class ReentrantReplyServer1 : public Worker {
1602*6777b538SAndroid Build Coastguard Worker public:
ReentrantReplyServer1(WaitableEvent * server_ready,mojo::ScopedMessagePipeHandle channel_handle1,mojo::ScopedMessagePipeHandle channel_handle2)1603*6777b538SAndroid Build Coastguard Worker ReentrantReplyServer1(WaitableEvent* server_ready,
1604*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle1,
1605*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle2)
1606*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle1), Channel::MODE_SERVER),
1607*6777b538SAndroid Build Coastguard Worker server_ready_(server_ready),
1608*6777b538SAndroid Build Coastguard Worker other_channel_handle_(std::move(channel_handle2)) {}
1609*6777b538SAndroid Build Coastguard Worker
Run()1610*6777b538SAndroid Build Coastguard Worker void Run() override {
1611*6777b538SAndroid Build Coastguard Worker server2_channel_ = SyncChannel::Create(
1612*6777b538SAndroid Build Coastguard Worker other_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
1613*6777b538SAndroid Build Coastguard Worker ipc_thread().task_runner(),
1614*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault(), true,
1615*6777b538SAndroid Build Coastguard Worker shutdown_event());
1616*6777b538SAndroid Build Coastguard Worker server_ready_->Signal();
1617*6777b538SAndroid Build Coastguard Worker Message* msg = new SyncChannelTestMsg_Reentrant1();
1618*6777b538SAndroid Build Coastguard Worker server2_channel_->Send(msg);
1619*6777b538SAndroid Build Coastguard Worker server2_channel_.reset();
1620*6777b538SAndroid Build Coastguard Worker Done();
1621*6777b538SAndroid Build Coastguard Worker }
1622*6777b538SAndroid Build Coastguard Worker
1623*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1624*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1625*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer1, message)
1626*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant2, OnReentrant2)
1627*6777b538SAndroid Build Coastguard Worker IPC_REPLY_HANDLER(OnReply)
1628*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1629*6777b538SAndroid Build Coastguard Worker return true;
1630*6777b538SAndroid Build Coastguard Worker }
1631*6777b538SAndroid Build Coastguard Worker
OnReentrant2()1632*6777b538SAndroid Build Coastguard Worker void OnReentrant2() {
1633*6777b538SAndroid Build Coastguard Worker Message* msg = new SyncChannelTestMsg_Reentrant3();
1634*6777b538SAndroid Build Coastguard Worker server2_channel_->Send(msg);
1635*6777b538SAndroid Build Coastguard Worker }
1636*6777b538SAndroid Build Coastguard Worker
OnReply(const Message & message)1637*6777b538SAndroid Build Coastguard Worker void OnReply(const Message& message) {
1638*6777b538SAndroid Build Coastguard Worker // If we get here, the Send() will never receive the reply (thus would
1639*6777b538SAndroid Build Coastguard Worker // hang), so abort instead.
1640*6777b538SAndroid Build Coastguard Worker LOG(FATAL) << "Reply message was dispatched";
1641*6777b538SAndroid Build Coastguard Worker }
1642*6777b538SAndroid Build Coastguard Worker
1643*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> server_ready_;
1644*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SyncChannel> server2_channel_;
1645*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle other_channel_handle_;
1646*6777b538SAndroid Build Coastguard Worker };
1647*6777b538SAndroid Build Coastguard Worker
1648*6777b538SAndroid Build Coastguard Worker class ReentrantReplyServer2 : public Worker {
1649*6777b538SAndroid Build Coastguard Worker public:
ReentrantReplyServer2(mojo::ScopedMessagePipeHandle channel_handle)1650*6777b538SAndroid Build Coastguard Worker ReentrantReplyServer2(mojo::ScopedMessagePipeHandle channel_handle)
1651*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_SERVER),
1652*6777b538SAndroid Build Coastguard Worker reply_(nullptr) {}
1653*6777b538SAndroid Build Coastguard Worker
1654*6777b538SAndroid Build Coastguard Worker private:
OnMessageReceived(const Message & message)1655*6777b538SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& message) override {
1656*6777b538SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer2, message)
1657*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER_DELAY_REPLY(
1658*6777b538SAndroid Build Coastguard Worker SyncChannelTestMsg_Reentrant1, OnReentrant1)
1659*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant3, OnReentrant3)
1660*6777b538SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
1661*6777b538SAndroid Build Coastguard Worker return true;
1662*6777b538SAndroid Build Coastguard Worker }
1663*6777b538SAndroid Build Coastguard Worker
OnReentrant1(Message * reply)1664*6777b538SAndroid Build Coastguard Worker void OnReentrant1(Message* reply) {
1665*6777b538SAndroid Build Coastguard Worker DCHECK(!reply_);
1666*6777b538SAndroid Build Coastguard Worker reply_ = reply;
1667*6777b538SAndroid Build Coastguard Worker }
1668*6777b538SAndroid Build Coastguard Worker
OnReentrant3()1669*6777b538SAndroid Build Coastguard Worker void OnReentrant3() {
1670*6777b538SAndroid Build Coastguard Worker DCHECK(reply_);
1671*6777b538SAndroid Build Coastguard Worker Message* reply = reply_;
1672*6777b538SAndroid Build Coastguard Worker reply_ = nullptr;
1673*6777b538SAndroid Build Coastguard Worker reply->set_unblock(true);
1674*6777b538SAndroid Build Coastguard Worker Send(reply);
1675*6777b538SAndroid Build Coastguard Worker Done();
1676*6777b538SAndroid Build Coastguard Worker }
1677*6777b538SAndroid Build Coastguard Worker
1678*6777b538SAndroid Build Coastguard Worker raw_ptr<Message> reply_;
1679*6777b538SAndroid Build Coastguard Worker };
1680*6777b538SAndroid Build Coastguard Worker
1681*6777b538SAndroid Build Coastguard Worker class ReentrantReplyClient : public Worker {
1682*6777b538SAndroid Build Coastguard Worker public:
ReentrantReplyClient(WaitableEvent * server_ready,mojo::ScopedMessagePipeHandle channel_handle)1683*6777b538SAndroid Build Coastguard Worker ReentrantReplyClient(WaitableEvent* server_ready,
1684*6777b538SAndroid Build Coastguard Worker mojo::ScopedMessagePipeHandle channel_handle)
1685*6777b538SAndroid Build Coastguard Worker : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
1686*6777b538SAndroid Build Coastguard Worker server_ready_(server_ready) {}
1687*6777b538SAndroid Build Coastguard Worker
Run()1688*6777b538SAndroid Build Coastguard Worker void Run() override {
1689*6777b538SAndroid Build Coastguard Worker server_ready_->Wait();
1690*6777b538SAndroid Build Coastguard Worker Send(new SyncChannelTestMsg_Reentrant2());
1691*6777b538SAndroid Build Coastguard Worker Done();
1692*6777b538SAndroid Build Coastguard Worker }
1693*6777b538SAndroid Build Coastguard Worker
1694*6777b538SAndroid Build Coastguard Worker private:
1695*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> server_ready_;
1696*6777b538SAndroid Build Coastguard Worker };
1697*6777b538SAndroid Build Coastguard Worker
TEST_F(IPCSyncChannelTest,ReentrantReply)1698*6777b538SAndroid Build Coastguard Worker TEST_F(IPCSyncChannelTest, ReentrantReply) {
1699*6777b538SAndroid Build Coastguard Worker std::vector<Worker*> workers;
1700*6777b538SAndroid Build Coastguard Worker WaitableEvent server_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1701*6777b538SAndroid Build Coastguard Worker base::WaitableEvent::InitialState::NOT_SIGNALED);
1702*6777b538SAndroid Build Coastguard Worker mojo::MessagePipe pipe1, pipe2;
1703*6777b538SAndroid Build Coastguard Worker workers.push_back(new ReentrantReplyServer2(std::move(pipe2.handle0)));
1704*6777b538SAndroid Build Coastguard Worker workers.push_back(new ReentrantReplyServer1(
1705*6777b538SAndroid Build Coastguard Worker &server_ready, std::move(pipe1.handle0), std::move(pipe2.handle1)));
1706*6777b538SAndroid Build Coastguard Worker workers.push_back(
1707*6777b538SAndroid Build Coastguard Worker new ReentrantReplyClient(&server_ready, std::move(pipe1.handle1)));
1708*6777b538SAndroid Build Coastguard Worker RunTest(workers);
1709*6777b538SAndroid Build Coastguard Worker }
1710*6777b538SAndroid Build Coastguard Worker
1711*6777b538SAndroid Build Coastguard Worker } // namespace
1712*6777b538SAndroid Build Coastguard Worker } // namespace IPC
1713