blob: 55c571149c947128d8a9946afcc99680ad002d02 [file] [log] [blame]
[email protected]522cc10d2012-01-11 22:39:541// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]22b42c52010-12-20 06:59:235#include "ipc/ipc_sync_channel.h"
6
avi246998d82015-12-22 02:39:047#include <stddef.h>
8
danakj03de39b22016-04-23 04:21:099#include <memory>
initial.commit09911bf2008-07-26 23:55:2910#include <string>
sammc4bcc4ed62016-10-27 10:13:5911#include <utility>
initial.commit09911bf2008-07-26 23:55:2912#include <vector>
13
[email protected]72b6f8e22011-11-12 21:16:4114#include "base/bind.h"
skyostile687bdff2015-05-12 11:29:2115#include "base/location.h"
initial.commit09911bf2008-07-26 23:55:2916#include "base/logging.h"
tfarina4da82752015-09-16 09:56:2117#include "base/macros.h"
[email protected]e66ef602013-07-24 05:15:2418#include "base/process/process_handle.h"
[email protected]2d6e6a72013-02-08 20:11:0219#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2120#include "base/single_thread_task_runner.h"
[email protected]4aa794a12013-06-11 06:32:1821#include "base/strings/string_util.h"
22#include "base/synchronization/waitable_event.h"
[email protected]f214f8792011-01-01 02:17:0823#include "base/threading/platform_thread.h"
[email protected]34b99632011-01-01 01:01:0624#include "base/threading/thread.h"
gabf08ccc02016-05-11 18:51:1125#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0426#include "build/build_config.h"
[email protected]57319ce2012-06-11 22:35:2627#include "ipc/ipc_listener.h"
[email protected]946d1b22009-07-22 23:57:2128#include "ipc/ipc_message.h"
[email protected]57319ce2012-06-11 22:35:2629#include "ipc/ipc_sender.h"
[email protected]1e9499c2010-04-06 20:33:3630#include "ipc/ipc_sync_message_filter.h"
[email protected]21fa3a12010-12-08 23:34:1631#include "ipc/ipc_sync_message_unittest.h"
sammc4bcc4ed62016-10-27 10:13:5932#include "mojo/public/cpp/system/message_pipe.h"
initial.commit09911bf2008-07-26 23:55:2933#include "testing/gtest/include/gtest/gtest.h"
34
[email protected]aa96ae772009-01-20 22:08:1535using base::WaitableEvent;
[email protected]c9e0c7332011-05-13 22:42:4136
[email protected]2d6e6a72013-02-08 20:11:0237namespace IPC {
[email protected]dd3eac22008-08-26 07:28:3438namespace {
39
initial.commit09911bf2008-07-26 23:55:2940// Base class for a "process" with listener and IPC threads.
[email protected]57319ce2012-06-11 22:35:2641class Worker : public Listener, public Sender {
initial.commit09911bf2008-07-26 23:55:2942 public:
43 // Will create a channel without a name.
erikchen99fbfc662016-04-08 22:37:4844 Worker(Channel::Mode mode,
45 const std::string& thread_name,
sammc4bcc4ed62016-10-27 10:13:5946 mojo::ScopedMessagePipeHandle channel_handle)
gab90c2c5c2016-06-01 20:34:0647 : done_(
48 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
49 base::WaitableEvent::InitialState::NOT_SIGNALED)),
50 channel_created_(
51 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
52 base::WaitableEvent::InitialState::NOT_SIGNALED)),
sammc4bcc4ed62016-10-27 10:13:5953 channel_handle_(std::move(channel_handle)),
initial.commit09911bf2008-07-26 23:55:2954 mode_(mode),
55 ipc_thread_((thread_name + "_ipc").c_str()),
56 listener_thread_((thread_name + "_listener").c_str()),
[email protected]8930d472009-02-21 08:05:2857 overrided_thread_(NULL),
gab90c2c5c2016-06-01 20:34:0658 shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
59 base::WaitableEvent::InitialState::NOT_SIGNALED),
erikchen99fbfc662016-04-08 22:37:4860 is_shutdown_(false) {}
initial.commit09911bf2008-07-26 23:55:2961
62 // Will create a named channel and use this name for the threads' name.
sammc4bcc4ed62016-10-27 10:13:5963 Worker(mojo::ScopedMessagePipeHandle channel_handle, Channel::Mode mode)
gab90c2c5c2016-06-01 20:34:0664 : done_(
65 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
66 base::WaitableEvent::InitialState::NOT_SIGNALED)),
67 channel_created_(
68 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
69 base::WaitableEvent::InitialState::NOT_SIGNALED)),
sammc4bcc4ed62016-10-27 10:13:5970 channel_handle_(std::move(channel_handle)),
initial.commit09911bf2008-07-26 23:55:2971 mode_(mode),
sammc4bcc4ed62016-10-27 10:13:5972 ipc_thread_("ipc thread"),
73 listener_thread_("listener thread"),
[email protected]8930d472009-02-21 08:05:2874 overrided_thread_(NULL),
gab90c2c5c2016-06-01 20:34:0675 shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
76 base::WaitableEvent::InitialState::NOT_SIGNALED),
77 is_shutdown_(false) {}
initial.commit09911bf2008-07-26 23:55:2978
dchengfe61fca2014-10-22 02:29:5279 ~Worker() override {
[email protected]bf2a9092013-01-08 06:09:0780 // Shutdown() must be called before destruction.
81 CHECK(is_shutdown_);
initial.commit09911bf2008-07-26 23:55:2982 }
83 void AddRef() { }
84 void Release() { }
dchengfe61fca2014-10-22 02:29:5285 bool Send(Message* msg) override { return channel_->Send(msg); }
[email protected]aa96ae772009-01-20 22:08:1586 void WaitForChannelCreation() { channel_created_->Wait(); }
[email protected]3cdb7af812008-10-24 19:21:1387 void CloseChannel() {
fdoraybcb9b322016-06-20 20:23:3288 DCHECK(ListenerThread()->task_runner()->BelongsToCurrentThread());
[email protected]3cdb7af812008-10-24 19:21:1389 channel_->Close();
90 }
initial.commit09911bf2008-07-26 23:55:2991 void Start() {
[email protected]fd0a773a2013-04-30 20:55:0392 StartThread(&listener_thread_, base::MessageLoop::TYPE_DEFAULT);
skyostile687bdff2015-05-12 11:29:2193 ListenerThread()->task_runner()->PostTask(
[email protected]72b6f8e22011-11-12 21:16:4194 FROM_HERE, base::Bind(&Worker::OnStart, this));
initial.commit09911bf2008-07-26 23:55:2995 }
[email protected]bf2a9092013-01-08 06:09:0796 void Shutdown() {
97 // The IPC thread needs to outlive SyncChannel. We can't do this in
98 // ~Worker(), since that'll reset the vtable pointer (to Worker's), which
99 // may result in a race conditions. See http://crbug.com/25841.
gab90c2c5c2016-06-01 20:34:06100 WaitableEvent listener_done(
101 base::WaitableEvent::ResetPolicy::AUTOMATIC,
102 base::WaitableEvent::InitialState::NOT_SIGNALED),
103 ipc_done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
104 base::WaitableEvent::InitialState::NOT_SIGNALED);
skyostile687bdff2015-05-12 11:29:21105 ListenerThread()->task_runner()->PostTask(
[email protected]bf2a9092013-01-08 06:09:07106 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this,
107 &listener_done, &ipc_done));
108 listener_done.Wait();
109 ipc_done.Wait();
110 ipc_thread_.Stop();
111 listener_thread_.Stop();
112 is_shutdown_ = true;
113 }
[email protected]ab820df2008-08-26 05:55:10114 void OverrideThread(base::Thread* overrided_thread) {
initial.commit09911bf2008-07-26 23:55:29115 DCHECK(overrided_thread_ == NULL);
116 overrided_thread_ = overrided_thread;
117 }
[email protected]5855f1d2014-04-16 16:50:43118 bool SendAnswerToLife(bool pump, bool succeed) {
[email protected]4df10d612008-11-12 00:38:26119 int answer = 0;
120 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
121 if (pump)
122 msg->EnableMessagePumping();
[email protected]5855f1d2014-04-16 16:50:43123 bool result = Send(msg);
[email protected]9eec2252009-12-01 02:34:18124 DCHECK_EQ(result, succeed);
125 DCHECK_EQ(answer, (succeed ? 42 : 0));
[email protected]4df10d612008-11-12 00:38:26126 return result;
127 }
128 bool SendDouble(bool pump, bool succeed) {
129 int answer = 0;
130 SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
131 if (pump)
132 msg->EnableMessagePumping();
133 bool result = Send(msg);
[email protected]9eec2252009-12-01 02:34:18134 DCHECK_EQ(result, succeed);
135 DCHECK_EQ(answer, (succeed ? 10 : 0));
[email protected]4df10d612008-11-12 00:38:26136 return result;
137 }
sammc4bcc4ed62016-10-27 10:13:59138 mojo::MessagePipeHandle TakeChannelHandle() {
139 DCHECK(channel_handle_.is_valid());
140 return channel_handle_.release();
141 }
initial.commit09911bf2008-07-26 23:55:29142 Channel::Mode mode() { return mode_; }
[email protected]aa96ae772009-01-20 22:08:15143 WaitableEvent* done_event() { return done_.get(); }
[email protected]1e9499c2010-04-06 20:33:36144 WaitableEvent* shutdown_event() { return &shutdown_event_; }
[email protected]9eec2252009-12-01 02:34:18145 void ResetChannel() { channel_.reset(); }
initial.commit09911bf2008-07-26 23:55:29146 // Derived classes need to call this when they've completed their part of
147 // the test.
[email protected]aa96ae772009-01-20 22:08:15148 void Done() { done_->Signal(); }
[email protected]1e9499c2010-04-06 20:33:36149
150 protected:
[email protected]c9e0c7332011-05-13 22:42:41151 SyncChannel* channel() { return channel_.get(); }
thakisb25789fb2015-04-23 05:40:02152 // Functions for derived classes to implement if they wish.
initial.commit09911bf2008-07-26 23:55:29153 virtual void Run() { }
initial.commit09911bf2008-07-26 23:55:29154 virtual void OnAnswer(int* answer) { NOTREACHED(); }
155 virtual void OnAnswerDelay(Message* reply_msg) {
156 // The message handler map below can only take one entry for
157 // SyncChannelTestMsg_AnswerToLife, so since some classes want
158 // the normal version while other want the delayed reply, we
159 // call the normal version if the derived class didn't override
160 // this function.
161 int answer;
162 OnAnswer(&answer);
163 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
164 Send(reply_msg);
165 }
[email protected]3cdb7af812008-10-24 19:21:13166 virtual void OnDouble(int in, int* out) { NOTREACHED(); }
167 virtual void OnDoubleDelay(int in, Message* reply_msg) {
168 int result;
169 OnDouble(in, &result);
170 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
171 Send(reply_msg);
172 }
initial.commit09911bf2008-07-26 23:55:29173
[email protected]ac0efda2009-10-14 16:22:02174 virtual void OnNestedTestMsg(Message* reply_msg) {
175 NOTREACHED();
176 }
177
[email protected]952394af2011-11-16 01:06:46178 virtual SyncChannel* CreateChannel() {
sammc4bcc4ed62016-10-27 10:13:59179 std::unique_ptr<SyncChannel> channel =
180 SyncChannel::Create(TakeChannelHandle(), mode_, this,
181 ipc_thread_.task_runner(), true, &shutdown_event_);
[email protected]fca876a12014-06-05 16:15:38182 return channel.release();
[email protected]952394af2011-11-16 01:06:46183 }
184
[email protected]3cdb7af812008-10-24 19:21:13185 base::Thread* ListenerThread() {
186 return overrided_thread_ ? overrided_thread_ : &listener_thread_;
187 }
[email protected]87339f02010-09-02 21:45:50188
[email protected]54af05f2011-04-08 03:38:21189 const base::Thread& ipc_thread() const { return ipc_thread_; }
190
[email protected]87339f02010-09-02 21:45:50191 private:
initial.commit09911bf2008-07-26 23:55:29192 // Called on the listener thread to create the sync channel.
193 void OnStart() {
initial.commit09911bf2008-07-26 23:55:29194 // Link ipc_thread_, listener_thread_ and channel_ altogether.
[email protected]fd0a773a2013-04-30 20:55:03195 StartThread(&ipc_thread_, base::MessageLoop::TYPE_IO);
[email protected]952394af2011-11-16 01:06:46196 channel_.reset(CreateChannel());
[email protected]aa96ae772009-01-20 22:08:15197 channel_created_->Signal();
initial.commit09911bf2008-07-26 23:55:29198 Run();
199 }
200
[email protected]9d4ff5ed2009-03-03 00:21:56201 void OnListenerThreadShutdown1(WaitableEvent* listener_event,
202 WaitableEvent* ipc_event) {
[email protected]3cdb7af812008-10-24 19:21:13203 // SyncChannel needs to be destructed on the thread that it was created on.
204 channel_.reset();
[email protected]9d4ff5ed2009-03-03 00:21:56205
[email protected]2d6e6a72013-02-08 20:11:02206 base::RunLoop().RunUntilIdle();
[email protected]aa96ae772009-01-20 22:08:15207
fdoray8e32586852016-06-22 19:56:16208 ipc_thread_.task_runner()->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41209 FROM_HERE, base::Bind(&Worker::OnIPCThreadShutdown, this,
210 listener_event, ipc_event));
[email protected]3cdb7af812008-10-24 19:21:13211 }
212
[email protected]9d4ff5ed2009-03-03 00:21:56213 void OnIPCThreadShutdown(WaitableEvent* listener_event,
214 WaitableEvent* ipc_event) {
[email protected]2d6e6a72013-02-08 20:11:02215 base::RunLoop().RunUntilIdle();
[email protected]aa96ae772009-01-20 22:08:15216 ipc_event->Signal();
[email protected]9d4ff5ed2009-03-03 00:21:56217
skyostile687bdff2015-05-12 11:29:21218 listener_thread_.task_runner()->PostTask(
219 FROM_HERE,
220 base::Bind(&Worker::OnListenerThreadShutdown2, this, listener_event));
[email protected]9d4ff5ed2009-03-03 00:21:56221 }
222
223 void OnListenerThreadShutdown2(WaitableEvent* listener_event) {
[email protected]2d6e6a72013-02-08 20:11:02224 base::RunLoop().RunUntilIdle();
[email protected]9d4ff5ed2009-03-03 00:21:56225 listener_event->Signal();
[email protected]3cdb7af812008-10-24 19:21:13226 }
227
dchengfe61fca2014-10-22 02:29:52228 bool OnMessageReceived(const Message& message) override {
initial.commit09911bf2008-07-26 23:55:29229 IPC_BEGIN_MESSAGE_MAP(Worker, message)
[email protected]3cdb7af812008-10-24 19:21:13230 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
initial.commit09911bf2008-07-26 23:55:29231 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
232 OnAnswerDelay)
[email protected]ac0efda2009-10-14 16:22:02233 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String,
234 OnNestedTestMsg)
initial.commit09911bf2008-07-26 23:55:29235 IPC_END_MESSAGE_MAP()
[email protected]a95986a82010-12-24 06:19:28236 return true;
initial.commit09911bf2008-07-26 23:55:29237 }
238
[email protected]fd0a773a2013-04-30 20:55:03239 void StartThread(base::Thread* thread, base::MessageLoop::Type type) {
[email protected]ab820df2008-08-26 05:55:10240 base::Thread::Options options;
[email protected]17b89142008-11-07 21:52:15241 options.message_loop_type = type;
[email protected]ab820df2008-08-26 05:55:10242 thread->StartWithOptions(options);
243 }
244
danakj03de39b22016-04-23 04:21:09245 std::unique_ptr<WaitableEvent> done_;
246 std::unique_ptr<WaitableEvent> channel_created_;
sammc4bcc4ed62016-10-27 10:13:59247 mojo::ScopedMessagePipeHandle channel_handle_;
initial.commit09911bf2008-07-26 23:55:29248 Channel::Mode mode_;
danakj03de39b22016-04-23 04:21:09249 std::unique_ptr<SyncChannel> channel_;
[email protected]ab820df2008-08-26 05:55:10250 base::Thread ipc_thread_;
251 base::Thread listener_thread_;
252 base::Thread* overrided_thread_;
initial.commit09911bf2008-07-26 23:55:29253
[email protected]8930d472009-02-21 08:05:28254 base::WaitableEvent shutdown_event_;
255
[email protected]bf2a9092013-01-08 06:09:07256 bool is_shutdown_;
257
[email protected]73a797fb2010-06-07 02:10:18258 DISALLOW_COPY_AND_ASSIGN(Worker);
initial.commit09911bf2008-07-26 23:55:29259};
260
261
262// Starts the test with the given workers. This function deletes the workers
263// when it's done.
264void RunTest(std::vector<Worker*> workers) {
initial.commit09911bf2008-07-26 23:55:29265 // First we create the workers that are channel servers, or else the other
266 // workers' channel initialization might fail because the pipe isn't created..
267 for (size_t i = 0; i < workers.size(); ++i) {
[email protected]1707726c2011-02-03 20:35:09268 if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) {
initial.commit09911bf2008-07-26 23:55:29269 workers[i]->Start();
270 workers[i]->WaitForChannelCreation();
271 }
272 }
273
274 // now create the clients
275 for (size_t i = 0; i < workers.size(); ++i) {
[email protected]1707726c2011-02-03 20:35:09276 if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG)
initial.commit09911bf2008-07-26 23:55:29277 workers[i]->Start();
278 }
279
280 // wait for all the workers to finish
initial.commit09911bf2008-07-26 23:55:29281 for (size_t i = 0; i < workers.size(); ++i)
[email protected]aa96ae772009-01-20 22:08:15282 workers[i]->done_event()->Wait();
initial.commit09911bf2008-07-26 23:55:29283
[email protected]bf2a9092013-01-08 06:09:07284 for (size_t i = 0; i < workers.size(); ++i) {
285 workers[i]->Shutdown();
286 delete workers[i];
287 }
initial.commit09911bf2008-07-26 23:55:29288}
289
[email protected]9629c0e2009-02-04 23:16:29290class IPCSyncChannelTest : public testing::Test {
291 private:
[email protected]fd0a773a2013-04-30 20:55:03292 base::MessageLoop message_loop_;
[email protected]9629c0e2009-02-04 23:16:29293};
294
[email protected]2a3aa7b52013-01-11 20:56:22295//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34296
initial.commit09911bf2008-07-26 23:55:29297class SimpleServer : public Worker {
298 public:
sammc4bcc4ed62016-10-27 10:13:59299 SimpleServer(bool pump_during_send,
300 mojo::ScopedMessagePipeHandle channel_handle)
301 : Worker(Channel::MODE_SERVER,
302 "simpler_server",
303 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48304 pump_during_send_(pump_during_send) {}
dchengfe61fca2014-10-22 02:29:52305 void Run() override {
[email protected]5855f1d2014-04-16 16:50:43306 SendAnswerToLife(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29307 Done();
308 }
[email protected]3cdb7af812008-10-24 19:21:13309
310 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29311};
312
313class SimpleClient : public Worker {
314 public:
sammc4bcc4ed62016-10-27 10:13:59315 explicit SimpleClient(mojo::ScopedMessagePipeHandle channel_handle)
316 : Worker(Channel::MODE_CLIENT,
317 "simple_client",
318 std::move(channel_handle)) {}
initial.commit09911bf2008-07-26 23:55:29319
dchengfe61fca2014-10-22 02:29:52320 void OnAnswer(int* answer) override {
initial.commit09911bf2008-07-26 23:55:29321 *answer = 42;
322 Done();
323 }
324};
325
[email protected]3cdb7af812008-10-24 19:21:13326void Simple(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29327 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59328 mojo::MessagePipe pipe;
329 workers.push_back(
330 new SimpleServer(pump_during_send, std::move(pipe.handle0)));
331 workers.push_back(new SimpleClient(std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29332 RunTest(workers);
333}
334
tfarina8514f0d2015-07-28 14:41:47335#if defined(OS_ANDROID)
336#define MAYBE_Simple DISABLED_Simple
337#else
338#define MAYBE_Simple Simple
339#endif
[email protected]3cdb7af812008-10-24 19:21:13340// Tests basic synchronous call
tfarina8514f0d2015-07-28 14:41:47341TEST_F(IPCSyncChannelTest, MAYBE_Simple) {
[email protected]3cdb7af812008-10-24 19:21:13342 Simple(false);
343 Simple(true);
344}
initial.commit09911bf2008-07-26 23:55:29345
[email protected]2a3aa7b52013-01-11 20:56:22346//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34347
[email protected]952394af2011-11-16 01:06:46348// Worker classes which override how the sync channel is created to use the
349// two-step initialization (calling the lightweight constructor and then
350// ChannelProxy::Init separately) process.
351class TwoStepServer : public Worker {
352 public:
sammc4bcc4ed62016-10-27 10:13:59353 TwoStepServer(bool create_pipe_now,
354 mojo::ScopedMessagePipeHandle channel_handle)
355 : Worker(Channel::MODE_SERVER,
356 "simpler_server",
357 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48358 create_pipe_now_(create_pipe_now) {}
[email protected]952394af2011-11-16 01:06:46359
dchengfe61fca2014-10-22 02:29:52360 void Run() override {
[email protected]5855f1d2014-04-16 16:50:43361 SendAnswerToLife(false, true);
[email protected]952394af2011-11-16 01:06:46362 Done();
363 }
364
dchengfe61fca2014-10-22 02:29:52365 SyncChannel* CreateChannel() override {
[email protected]fca876a12014-06-05 16:15:38366 SyncChannel* channel =
sammc4bcc4ed62016-10-27 10:13:59367 SyncChannel::Create(TakeChannelHandle(), mode(), this,
368 ipc_thread().task_runner(), create_pipe_now_,
erikchen30dc2812015-09-24 03:26:38369 shutdown_event())
370 .release();
[email protected]952394af2011-11-16 01:06:46371 return channel;
372 }
373
374 bool create_pipe_now_;
375};
376
377class TwoStepClient : public Worker {
378 public:
sammc4bcc4ed62016-10-27 10:13:59379 TwoStepClient(bool create_pipe_now,
380 mojo::ScopedMessagePipeHandle channel_handle)
381 : Worker(Channel::MODE_CLIENT,
382 "simple_client",
383 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48384 create_pipe_now_(create_pipe_now) {}
[email protected]952394af2011-11-16 01:06:46385
dchengfe61fca2014-10-22 02:29:52386 void OnAnswer(int* answer) override {
[email protected]952394af2011-11-16 01:06:46387 *answer = 42;
388 Done();
389 }
390
dchengfe61fca2014-10-22 02:29:52391 SyncChannel* CreateChannel() override {
[email protected]fca876a12014-06-05 16:15:38392 SyncChannel* channel =
sammc4bcc4ed62016-10-27 10:13:59393 SyncChannel::Create(TakeChannelHandle(), mode(), this,
394 ipc_thread().task_runner(), create_pipe_now_,
erikchen30dc2812015-09-24 03:26:38395 shutdown_event())
396 .release();
[email protected]952394af2011-11-16 01:06:46397 return channel;
398 }
399
400 bool create_pipe_now_;
401};
402
403void TwoStep(bool create_server_pipe_now, bool create_client_pipe_now) {
404 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59405 mojo::MessagePipe pipe;
406 workers.push_back(
407 new TwoStepServer(create_server_pipe_now, std::move(pipe.handle0)));
408 workers.push_back(
409 new TwoStepClient(create_client_pipe_now, std::move(pipe.handle1)));
[email protected]952394af2011-11-16 01:06:46410 RunTest(workers);
411}
412
[email protected]952394af2011-11-16 01:06:46413// Tests basic two-step initialization, where you call the lightweight
414// constructor then Init.
415TEST_F(IPCSyncChannelTest, TwoStepInitialization) {
416 TwoStep(false, false);
417 TwoStep(false, true);
418 TwoStep(true, false);
419 TwoStep(true, true);
420}
421
[email protected]2a3aa7b52013-01-11 20:56:22422//------------------------------------------------------------------------------
[email protected]952394af2011-11-16 01:06:46423
initial.commit09911bf2008-07-26 23:55:29424class DelayClient : public Worker {
425 public:
sammc4bcc4ed62016-10-27 10:13:59426 explicit DelayClient(mojo::ScopedMessagePipeHandle channel_handle)
427 : Worker(Channel::MODE_CLIENT,
428 "delay_client",
429 std::move(channel_handle)) {}
initial.commit09911bf2008-07-26 23:55:29430
dchengfe61fca2014-10-22 02:29:52431 void OnAnswerDelay(Message* reply_msg) override {
initial.commit09911bf2008-07-26 23:55:29432 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
433 Send(reply_msg);
434 Done();
435 }
436};
437
[email protected]3cdb7af812008-10-24 19:21:13438void DelayReply(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29439 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59440 mojo::MessagePipe pipe;
441 workers.push_back(
442 new SimpleServer(pump_during_send, std::move(pipe.handle0)));
443 workers.push_back(new DelayClient(std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29444 RunTest(workers);
445}
446
[email protected]3cdb7af812008-10-24 19:21:13447// Tests that asynchronous replies work
448TEST_F(IPCSyncChannelTest, DelayReply) {
449 DelayReply(false);
450 DelayReply(true);
451}
initial.commit09911bf2008-07-26 23:55:29452
[email protected]2a3aa7b52013-01-11 20:56:22453//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34454
initial.commit09911bf2008-07-26 23:55:29455class NoHangServer : public Worker {
456 public:
erikchen99fbfc662016-04-08 22:37:48457 NoHangServer(WaitableEvent* got_first_reply,
458 bool pump_during_send,
sammc4bcc4ed62016-10-27 10:13:59459 mojo::ScopedMessagePipeHandle channel_handle)
460 : Worker(Channel::MODE_SERVER,
461 "no_hang_server",
462 std::move(channel_handle)),
[email protected]3cdb7af812008-10-24 19:21:13463 got_first_reply_(got_first_reply),
erikchen99fbfc662016-04-08 22:37:48464 pump_during_send_(pump_during_send) {}
dchengfe61fca2014-10-22 02:29:52465 void Run() override {
[email protected]5855f1d2014-04-16 16:50:43466 SendAnswerToLife(pump_during_send_, true);
[email protected]aa96ae772009-01-20 22:08:15467 got_first_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29468
[email protected]5855f1d2014-04-16 16:50:43469 SendAnswerToLife(pump_during_send_, false);
initial.commit09911bf2008-07-26 23:55:29470 Done();
471 }
472
[email protected]aa96ae772009-01-20 22:08:15473 WaitableEvent* got_first_reply_;
[email protected]3cdb7af812008-10-24 19:21:13474 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29475};
476
477class NoHangClient : public Worker {
478 public:
sammc4bcc4ed62016-10-27 10:13:59479 NoHangClient(WaitableEvent* got_first_reply,
480 mojo::ScopedMessagePipeHandle channel_handle)
481 : Worker(Channel::MODE_CLIENT,
482 "no_hang_client",
483 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48484 got_first_reply_(got_first_reply) {}
initial.commit09911bf2008-07-26 23:55:29485
dchengfe61fca2014-10-22 02:29:52486 void OnAnswerDelay(Message* reply_msg) override {
initial.commit09911bf2008-07-26 23:55:29487 // Use the DELAY_REPLY macro so that we can force the reply to be sent
488 // before this function returns (when the channel will be reset).
489 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
490 Send(reply_msg);
491 got_first_reply_->Wait();
492 CloseChannel();
493 Done();
494 }
495
[email protected]aa96ae772009-01-20 22:08:15496 WaitableEvent* got_first_reply_;
initial.commit09911bf2008-07-26 23:55:29497};
498
[email protected]3cdb7af812008-10-24 19:21:13499void NoHang(bool pump_during_send) {
gab90c2c5c2016-06-01 20:34:06500 WaitableEvent got_first_reply(
501 base::WaitableEvent::ResetPolicy::AUTOMATIC,
502 base::WaitableEvent::InitialState::NOT_SIGNALED);
initial.commit09911bf2008-07-26 23:55:29503 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59504 mojo::MessagePipe pipe;
505 workers.push_back(new NoHangServer(&got_first_reply, pump_during_send,
506 std::move(pipe.handle0)));
erikchen99fbfc662016-04-08 22:37:48507 workers.push_back(
sammc4bcc4ed62016-10-27 10:13:59508 new NoHangClient(&got_first_reply, std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29509 RunTest(workers);
510}
511
[email protected]3cdb7af812008-10-24 19:21:13512// Tests that caller doesn't hang if receiver dies
513TEST_F(IPCSyncChannelTest, NoHang) {
514 NoHang(false);
515 NoHang(true);
516}
initial.commit09911bf2008-07-26 23:55:29517
[email protected]2a3aa7b52013-01-11 20:56:22518//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34519
[email protected]3cdb7af812008-10-24 19:21:13520class UnblockServer : public Worker {
initial.commit09911bf2008-07-26 23:55:29521 public:
erikchen99fbfc662016-04-08 22:37:48522 UnblockServer(bool pump_during_send,
523 bool delete_during_send,
sammc4bcc4ed62016-10-27 10:13:59524 mojo::ScopedMessagePipeHandle channel_handle)
525 : Worker(Channel::MODE_SERVER,
526 "unblock_server",
527 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48528 pump_during_send_(pump_during_send),
529 delete_during_send_(delete_during_send) {}
dchengfe61fca2014-10-22 02:29:52530 void Run() override {
[email protected]9eec2252009-12-01 02:34:18531 if (delete_during_send_) {
532 // Use custom code since race conditions mean the answer may or may not be
533 // available.
534 int answer = 0;
535 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
536 if (pump_during_send_)
537 msg->EnableMessagePumping();
538 Send(msg);
539 } else {
[email protected]5855f1d2014-04-16 16:50:43540 SendAnswerToLife(pump_during_send_, true);
[email protected]9eec2252009-12-01 02:34:18541 }
initial.commit09911bf2008-07-26 23:55:29542 Done();
543 }
544
dchengfe61fca2014-10-22 02:29:52545 void OnDoubleDelay(int in, Message* reply_msg) override {
[email protected]9eec2252009-12-01 02:34:18546 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
547 Send(reply_msg);
548 if (delete_during_send_)
549 ResetChannel();
initial.commit09911bf2008-07-26 23:55:29550 }
[email protected]3cdb7af812008-10-24 19:21:13551
552 bool pump_during_send_;
[email protected]9eec2252009-12-01 02:34:18553 bool delete_during_send_;
initial.commit09911bf2008-07-26 23:55:29554};
555
[email protected]3cdb7af812008-10-24 19:21:13556class UnblockClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29557 public:
sammc4bcc4ed62016-10-27 10:13:59558 UnblockClient(bool pump_during_send,
559 mojo::ScopedMessagePipeHandle channel_handle)
560 : Worker(Channel::MODE_CLIENT,
561 "unblock_client",
562 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48563 pump_during_send_(pump_during_send) {}
initial.commit09911bf2008-07-26 23:55:29564
dchengfe61fca2014-10-22 02:29:52565 void OnAnswer(int* answer) override {
[email protected]4df10d612008-11-12 00:38:26566 SendDouble(pump_during_send_, true);
567 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29568 Done();
569 }
[email protected]3cdb7af812008-10-24 19:21:13570
571 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29572};
573
[email protected]9eec2252009-12-01 02:34:18574void Unblock(bool server_pump, bool client_pump, bool delete_during_send) {
[email protected]3cdb7af812008-10-24 19:21:13575 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59576 mojo::MessagePipe pipe;
577 workers.push_back(new UnblockServer(server_pump, delete_during_send,
578 std::move(pipe.handle0)));
579 workers.push_back(new UnblockClient(client_pump, std::move(pipe.handle1)));
[email protected]3cdb7af812008-10-24 19:21:13580 RunTest(workers);
581}
582
initial.commit09911bf2008-07-26 23:55:29583// Tests that the caller unblocks to answer a sync message from the receiver.
[email protected]3cdb7af812008-10-24 19:21:13584TEST_F(IPCSyncChannelTest, Unblock) {
[email protected]9eec2252009-12-01 02:34:18585 Unblock(false, false, false);
586 Unblock(false, true, false);
587 Unblock(true, false, false);
588 Unblock(true, true, false);
589}
590
[email protected]2a3aa7b52013-01-11 20:56:22591//------------------------------------------------------------------------------
[email protected]9eec2252009-12-01 02:34:18592
tfarina8514f0d2015-07-28 14:41:47593#if defined(OS_ANDROID)
594#define MAYBE_ChannelDeleteDuringSend DISABLED_ChannelDeleteDuringSend
595#else
596#define MAYBE_ChannelDeleteDuringSend ChannelDeleteDuringSend
597#endif
[email protected]c9e0c7332011-05-13 22:42:41598// Tests that the the SyncChannel object can be deleted during a Send.
tfarina8514f0d2015-07-28 14:41:47599TEST_F(IPCSyncChannelTest, MAYBE_ChannelDeleteDuringSend) {
[email protected]9eec2252009-12-01 02:34:18600 Unblock(false, false, true);
601 Unblock(false, true, true);
602 Unblock(true, false, true);
603 Unblock(true, true, true);
[email protected]3cdb7af812008-10-24 19:21:13604}
605
[email protected]2a3aa7b52013-01-11 20:56:22606//------------------------------------------------------------------------------
[email protected]3cdb7af812008-10-24 19:21:13607
608class RecursiveServer : public Worker {
609 public:
erikchen99fbfc662016-04-08 22:37:48610 RecursiveServer(bool expected_send_result,
611 bool pump_first,
612 bool pump_second,
sammc4bcc4ed62016-10-27 10:13:59613 mojo::ScopedMessagePipeHandle channel_handle)
614 : Worker(Channel::MODE_SERVER,
615 "recursive_server",
616 std::move(channel_handle)),
[email protected]e7e38032011-07-26 17:25:25617 expected_send_result_(expected_send_result),
erikchen99fbfc662016-04-08 22:37:48618 pump_first_(pump_first),
619 pump_second_(pump_second) {}
dchengfe61fca2014-10-22 02:29:52620 void Run() override {
[email protected]4df10d612008-11-12 00:38:26621 SendDouble(pump_first_, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13622 Done();
623 }
624
dchengfe61fca2014-10-22 02:29:52625 void OnDouble(int in, int* out) override {
[email protected]4df10d612008-11-12 00:38:26626 *out = in * 2;
[email protected]5855f1d2014-04-16 16:50:43627 SendAnswerToLife(pump_second_, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13628 }
629
630 bool expected_send_result_, pump_first_, pump_second_;
631};
632
633class RecursiveClient : public Worker {
634 public:
erikchen99fbfc662016-04-08 22:37:48635 RecursiveClient(bool pump_during_send,
636 bool close_channel,
sammc4bcc4ed62016-10-27 10:13:59637 mojo::ScopedMessagePipeHandle channel_handle)
638 : Worker(Channel::MODE_CLIENT,
639 "recursive_client",
640 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48641 pump_during_send_(pump_during_send),
642 close_channel_(close_channel) {}
[email protected]3cdb7af812008-10-24 19:21:13643
dchengfe61fca2014-10-22 02:29:52644 void OnDoubleDelay(int in, Message* reply_msg) override {
[email protected]4df10d612008-11-12 00:38:26645 SendDouble(pump_during_send_, !close_channel_);
[email protected]c690a182008-10-24 23:10:32646 if (close_channel_) {
647 delete reply_msg;
648 } else {
[email protected]3cdb7af812008-10-24 19:21:13649 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
650 Send(reply_msg);
651 }
652 Done();
653 }
654
dchengfe61fca2014-10-22 02:29:52655 void OnAnswerDelay(Message* reply_msg) override {
[email protected]3cdb7af812008-10-24 19:21:13656 if (close_channel_) {
[email protected]c690a182008-10-24 23:10:32657 delete reply_msg;
[email protected]3cdb7af812008-10-24 19:21:13658 CloseChannel();
659 } else {
660 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
661 Send(reply_msg);
662 }
663 }
664
665 bool pump_during_send_, close_channel_;
666};
667
668void Recursive(
669 bool server_pump_first, bool server_pump_second, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29670 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59671 mojo::MessagePipe pipe;
672 workers.push_back(new RecursiveServer(
673 true, server_pump_first, server_pump_second, std::move(pipe.handle0)));
674 workers.push_back(
675 new RecursiveClient(client_pump, false, std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29676 RunTest(workers);
677}
678
[email protected]3cdb7af812008-10-24 19:21:13679// Tests a server calling Send while another Send is pending.
680TEST_F(IPCSyncChannelTest, Recursive) {
681 Recursive(false, false, false);
682 Recursive(false, false, true);
683 Recursive(false, true, false);
684 Recursive(false, true, true);
685 Recursive(true, false, false);
686 Recursive(true, false, true);
687 Recursive(true, true, false);
688 Recursive(true, true, true);
689}
690
[email protected]2a3aa7b52013-01-11 20:56:22691//------------------------------------------------------------------------------
[email protected]3cdb7af812008-10-24 19:21:13692
693void RecursiveNoHang(
694 bool server_pump_first, bool server_pump_second, bool client_pump) {
695 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59696 mojo::MessagePipe pipe;
697 workers.push_back(new RecursiveServer(
698 false, server_pump_first, server_pump_second, std::move(pipe.handle0)));
699 workers.push_back(
700 new RecursiveClient(client_pump, true, std::move(pipe.handle1)));
[email protected]3cdb7af812008-10-24 19:21:13701 RunTest(workers);
702}
703
[email protected]3cdb7af812008-10-24 19:21:13704// Tests that if a caller makes a sync call during an existing sync call and
705// the receiver dies, neither of the Send() calls hang.
706TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
707 RecursiveNoHang(false, false, false);
708 RecursiveNoHang(false, false, true);
709 RecursiveNoHang(false, true, false);
710 RecursiveNoHang(false, true, true);
711 RecursiveNoHang(true, false, false);
712 RecursiveNoHang(true, false, true);
713 RecursiveNoHang(true, true, false);
714 RecursiveNoHang(true, true, true);
715}
initial.commit09911bf2008-07-26 23:55:29716
[email protected]2a3aa7b52013-01-11 20:56:22717//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34718
initial.commit09911bf2008-07-26 23:55:29719class MultipleServer1 : public Worker {
720 public:
sammc4bcc4ed62016-10-27 10:13:59721 MultipleServer1(bool pump_during_send,
722 mojo::ScopedMessagePipeHandle channel_handle)
723 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
724 pump_during_send_(pump_during_send) {}
[email protected]3cdb7af812008-10-24 19:21:13725
dchengfe61fca2014-10-22 02:29:52726 void Run() override {
[email protected]4df10d612008-11-12 00:38:26727 SendDouble(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29728 Done();
729 }
[email protected]3cdb7af812008-10-24 19:21:13730
731 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29732};
733
734class MultipleClient1 : public Worker {
735 public:
[email protected]aa96ae772009-01-20 22:08:15736 MultipleClient1(WaitableEvent* client1_msg_received,
sammc4bcc4ed62016-10-27 10:13:59737 WaitableEvent* client1_can_reply,
738 mojo::ScopedMessagePipeHandle channel_handle)
739 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
740 client1_msg_received_(client1_msg_received),
741 client1_can_reply_(client1_can_reply) {}
initial.commit09911bf2008-07-26 23:55:29742
dchengfe61fca2014-10-22 02:29:52743 void OnDouble(int in, int* out) override {
[email protected]aa96ae772009-01-20 22:08:15744 client1_msg_received_->Signal();
initial.commit09911bf2008-07-26 23:55:29745 *out = in * 2;
746 client1_can_reply_->Wait();
747 Done();
748 }
749
750 private:
[email protected]aa96ae772009-01-20 22:08:15751 WaitableEvent *client1_msg_received_, *client1_can_reply_;
initial.commit09911bf2008-07-26 23:55:29752};
753
754class MultipleServer2 : public Worker {
755 public:
sammc4bcc4ed62016-10-27 10:13:59756 explicit MultipleServer2(mojo::ScopedMessagePipeHandle channel_handle)
757 : Worker(std::move(channel_handle), Channel::MODE_SERVER) {}
initial.commit09911bf2008-07-26 23:55:29758
dchengfe61fca2014-10-22 02:29:52759 void OnAnswer(int* result) override {
initial.commit09911bf2008-07-26 23:55:29760 *result = 42;
761 Done();
762 }
763};
764
765class MultipleClient2 : public Worker {
766 public:
sammc4bcc4ed62016-10-27 10:13:59767 MultipleClient2(WaitableEvent* client1_msg_received,
768 WaitableEvent* client1_can_reply,
769 bool pump_during_send,
770 mojo::ScopedMessagePipeHandle channel_handle)
771 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
772 client1_msg_received_(client1_msg_received),
773 client1_can_reply_(client1_can_reply),
774 pump_during_send_(pump_during_send) {}
initial.commit09911bf2008-07-26 23:55:29775
dchengfe61fca2014-10-22 02:29:52776 void Run() override {
initial.commit09911bf2008-07-26 23:55:29777 client1_msg_received_->Wait();
[email protected]5855f1d2014-04-16 16:50:43778 SendAnswerToLife(pump_during_send_, true);
[email protected]aa96ae772009-01-20 22:08:15779 client1_can_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29780 Done();
781 }
782
783 private:
[email protected]aa96ae772009-01-20 22:08:15784 WaitableEvent *client1_msg_received_, *client1_can_reply_;
[email protected]3cdb7af812008-10-24 19:21:13785 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29786};
787
[email protected]3cdb7af812008-10-24 19:21:13788void Multiple(bool server_pump, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29789 std::vector<Worker*> workers;
790
791 // A shared worker thread so that server1 and server2 run on one thread.
[email protected]ab820df2008-08-26 05:55:10792 base::Thread worker_thread("Multiple");
[email protected]6314e6f62009-07-15 16:07:14793 ASSERT_TRUE(worker_thread.Start());
initial.commit09911bf2008-07-26 23:55:29794
795 // Server1 sends a sync msg to client1, which blocks the reply until
796 // server2 (which runs on the same worker thread as server1) responds
797 // to a sync msg from client2.
gab90c2c5c2016-06-01 20:34:06798 WaitableEvent client1_msg_received(
799 base::WaitableEvent::ResetPolicy::AUTOMATIC,
800 base::WaitableEvent::InitialState::NOT_SIGNALED);
801 WaitableEvent client1_can_reply(
802 base::WaitableEvent::ResetPolicy::AUTOMATIC,
803 base::WaitableEvent::InitialState::NOT_SIGNALED);
initial.commit09911bf2008-07-26 23:55:29804
805 Worker* worker;
806
sammc4bcc4ed62016-10-27 10:13:59807 mojo::MessagePipe pipe1, pipe2;
808 worker = new MultipleServer2(std::move(pipe2.handle0));
initial.commit09911bf2008-07-26 23:55:29809 worker->OverrideThread(&worker_thread);
810 workers.push_back(worker);
811
sammc4bcc4ed62016-10-27 10:13:59812 worker = new MultipleClient2(&client1_msg_received, &client1_can_reply,
813 client_pump, std::move(pipe2.handle1));
initial.commit09911bf2008-07-26 23:55:29814 workers.push_back(worker);
815
sammc4bcc4ed62016-10-27 10:13:59816 worker = new MultipleServer1(server_pump, std::move(pipe1.handle0));
initial.commit09911bf2008-07-26 23:55:29817 worker->OverrideThread(&worker_thread);
818 workers.push_back(worker);
819
sammc4bcc4ed62016-10-27 10:13:59820 worker = new MultipleClient1(&client1_msg_received, &client1_can_reply,
821 std::move(pipe1.handle1));
initial.commit09911bf2008-07-26 23:55:29822 workers.push_back(worker);
823
824 RunTest(workers);
825}
826
[email protected]3cdb7af812008-10-24 19:21:13827// Tests that multiple SyncObjects on the same listener thread can unblock each
828// other.
829TEST_F(IPCSyncChannelTest, Multiple) {
830 Multiple(false, false);
831 Multiple(false, true);
832 Multiple(true, false);
833 Multiple(true, true);
834}
initial.commit09911bf2008-07-26 23:55:29835
[email protected]2a3aa7b52013-01-11 20:56:22836//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34837
[email protected]ac0efda2009-10-14 16:22:02838// This class provides server side functionality to test the case where
839// multiple sync channels are in use on the same thread on the client and
840// nested calls are issued.
841class QueuedReplyServer : public Worker {
initial.commit09911bf2008-07-26 23:55:29842 public:
[email protected]b7243c42010-07-23 05:23:13843 QueuedReplyServer(base::Thread* listener_thread,
sammc4bcc4ed62016-10-27 10:13:59844 mojo::ScopedMessagePipeHandle channel_handle,
[email protected]b7243c42010-07-23 05:23:13845 const std::string& reply_text)
sammc4bcc4ed62016-10-27 10:13:59846 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]ac0efda2009-10-14 16:22:02847 reply_text_(reply_text) {
848 Worker::OverrideThread(listener_thread);
initial.commit09911bf2008-07-26 23:55:29849 }
[email protected]3cdb7af812008-10-24 19:21:13850
dchengfe61fca2014-10-22 02:29:52851 void OnNestedTestMsg(Message* reply_msg) override {
[email protected]2a9d601b2010-10-19 23:50:00852 VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
853 SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
[email protected]ac0efda2009-10-14 16:22:02854 Send(reply_msg);
initial.commit09911bf2008-07-26 23:55:29855 Done();
856 }
857
858 private:
[email protected]ac0efda2009-10-14 16:22:02859 std::string reply_text_;
initial.commit09911bf2008-07-26 23:55:29860};
861
[email protected]ac0efda2009-10-14 16:22:02862// The QueuedReplyClient class provides functionality to test the case where
863// multiple sync channels are in use on the same thread and they make nested
864// sync calls, i.e. while the first channel waits for a response it makes a
865// sync call on another channel.
866// The callstack should unwind correctly, i.e. the outermost call should
867// complete first, and so on.
868class QueuedReplyClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29869 public:
[email protected]ac0efda2009-10-14 16:22:02870 QueuedReplyClient(base::Thread* listener_thread,
sammc4bcc4ed62016-10-27 10:13:59871 mojo::ScopedMessagePipeHandle channel_handle,
[email protected]ac0efda2009-10-14 16:22:02872 const std::string& expected_text,
873 bool pump_during_send)
sammc4bcc4ed62016-10-27 10:13:59874 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
[email protected]7ee1a44c2010-07-23 14:18:59875 pump_during_send_(pump_during_send),
876 expected_text_(expected_text) {
[email protected]ac0efda2009-10-14 16:22:02877 Worker::OverrideThread(listener_thread);
878 }
initial.commit09911bf2008-07-26 23:55:29879
dchengfe61fca2014-10-22 02:29:52880 void Run() override {
[email protected]ac0efda2009-10-14 16:22:02881 std::string response;
882 SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
883 if (pump_during_send_)
884 msg->EnableMessagePumping();
885 bool result = Send(msg);
886 DCHECK(result);
[email protected]9eec2252009-12-01 02:34:18887 DCHECK_EQ(response, expected_text_);
initial.commit09911bf2008-07-26 23:55:29888
[email protected]2a9d601b2010-10-19 23:50:00889 VLOG(1) << __FUNCTION__ << " Received reply: " << response;
initial.commit09911bf2008-07-26 23:55:29890 Done();
891 }
892
[email protected]ac0efda2009-10-14 16:22:02893 private:
[email protected]3cdb7af812008-10-24 19:21:13894 bool pump_during_send_;
[email protected]ac0efda2009-10-14 16:22:02895 std::string expected_text_;
initial.commit09911bf2008-07-26 23:55:29896};
897
[email protected]ac0efda2009-10-14 16:22:02898void QueuedReply(bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29899 std::vector<Worker*> workers;
900
[email protected]ac0efda2009-10-14 16:22:02901 // A shared worker thread for servers
902 base::Thread server_worker_thread("QueuedReply_ServerListener");
903 ASSERT_TRUE(server_worker_thread.Start());
initial.commit09911bf2008-07-26 23:55:29904
[email protected]ac0efda2009-10-14 16:22:02905 base::Thread client_worker_thread("QueuedReply_ClientListener");
906 ASSERT_TRUE(client_worker_thread.Start());
initial.commit09911bf2008-07-26 23:55:29907
908 Worker* worker;
909
sammc4bcc4ed62016-10-27 10:13:59910 mojo::MessagePipe pipe1, pipe2;
[email protected]ac0efda2009-10-14 16:22:02911 worker = new QueuedReplyServer(&server_worker_thread,
sammc4bcc4ed62016-10-27 10:13:59912 std::move(pipe1.handle0), "Got first message");
initial.commit09911bf2008-07-26 23:55:29913 workers.push_back(worker);
914
sammc4bcc4ed62016-10-27 10:13:59915 worker = new QueuedReplyServer(
916 &server_worker_thread, std::move(pipe2.handle0), "Got second message");
initial.commit09911bf2008-07-26 23:55:29917 workers.push_back(worker);
918
sammc4bcc4ed62016-10-27 10:13:59919 worker =
920 new QueuedReplyClient(&client_worker_thread, std::move(pipe1.handle1),
921 "Got first message", client_pump);
initial.commit09911bf2008-07-26 23:55:29922 workers.push_back(worker);
923
sammc4bcc4ed62016-10-27 10:13:59924 worker =
925 new QueuedReplyClient(&client_worker_thread, std::move(pipe2.handle1),
926 "Got second message", client_pump);
initial.commit09911bf2008-07-26 23:55:29927 workers.push_back(worker);
928
929 RunTest(workers);
930}
931
[email protected]3cdb7af812008-10-24 19:21:13932// While a blocking send is in progress, the listener thread might answer other
933// synchronous messages. This tests that if during the response to another
934// message the reply to the original messages comes, it is queued up correctly
935// and the original Send is unblocked later.
[email protected]ac0efda2009-10-14 16:22:02936// We also test that the send call stacks unwind correctly when the channel
937// pumps messages while waiting for a response.
[email protected]3cdb7af812008-10-24 19:21:13938TEST_F(IPCSyncChannelTest, QueuedReply) {
[email protected]ac0efda2009-10-14 16:22:02939 QueuedReply(false);
940 QueuedReply(true);
[email protected]3cdb7af812008-10-24 19:21:13941}
initial.commit09911bf2008-07-26 23:55:29942
[email protected]2a3aa7b52013-01-11 20:56:22943//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34944
[email protected]3cdb7af812008-10-24 19:21:13945class ChattyClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29946 public:
sammc4bcc4ed62016-10-27 10:13:59947 explicit ChattyClient(mojo::ScopedMessagePipeHandle channel_handle)
948 : Worker(Channel::MODE_CLIENT,
949 "chatty_client",
950 std::move(channel_handle)) {}
initial.commit09911bf2008-07-26 23:55:29951
dchengfe61fca2014-10-22 02:29:52952 void OnAnswer(int* answer) override {
initial.commit09911bf2008-07-26 23:55:29953 // The PostMessage limit is 10k. Send 20% more than that.
954 const int kMessageLimit = 10000;
955 const int kMessagesToSend = kMessageLimit * 120 / 100;
956 for (int i = 0; i < kMessagesToSend; ++i) {
[email protected]4df10d612008-11-12 00:38:26957 if (!SendDouble(false, true))
initial.commit09911bf2008-07-26 23:55:29958 break;
959 }
[email protected]4df10d612008-11-12 00:38:26960 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29961 Done();
962 }
963};
964
[email protected]3cdb7af812008-10-24 19:21:13965void ChattyServer(bool pump_during_send) {
966 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59967 mojo::MessagePipe pipe;
968 workers.push_back(
969 new UnblockServer(pump_during_send, false, std::move(pipe.handle0)));
970 workers.push_back(new ChattyClient(std::move(pipe.handle1)));
[email protected]3cdb7af812008-10-24 19:21:13971 RunTest(workers);
972}
973
tfarina8514f0d2015-07-28 14:41:47974#if defined(OS_ANDROID)
975// Times out.
976#define MAYBE_ChattyServer DISABLED_ChattyServer
977#else
978#define MAYBE_ChattyServer ChattyServer
979#endif
[email protected]4df10d612008-11-12 00:38:26980// Tests http://b/1093251 - that sending lots of sync messages while
initial.commit09911bf2008-07-26 23:55:29981// the receiver is waiting for a sync reply does not overflow the PostMessage
982// queue.
tfarina8514f0d2015-07-28 14:41:47983TEST_F(IPCSyncChannelTest, MAYBE_ChattyServer) {
[email protected]3cdb7af812008-10-24 19:21:13984 ChattyServer(false);
sammc4bcc4ed62016-10-27 10:13:59985}
986
987#if defined(OS_ANDROID)
988// Times out.
989#define MAYBE_ChattyServerPumpDuringSend DISABLED_ChattyServerPumpDuringSend
990#else
991#define MAYBE_ChattyServerPumpDuringSend ChattyServerPumpDuringSend
992#endif
993TEST_F(IPCSyncChannelTest, MAYBE_ChattyServerPumpDuringSend) {
[email protected]3cdb7af812008-10-24 19:21:13994 ChattyServer(true);
initial.commit09911bf2008-07-26 23:55:29995}
[email protected]d65cab7a2008-08-12 01:25:41996
[email protected]d65cab7a2008-08-12 01:25:41997//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34998
[email protected]0633e3152011-11-28 18:35:39999void NestedCallback(Worker* server) {
1000 // Sleep a bit so that we wake up after the reply has been received.
[email protected]b5393332012-01-13 00:11:011001 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(250));
[email protected]5855f1d2014-04-16 16:50:431002 server->SendAnswerToLife(true, true);
[email protected]0633e3152011-11-28 18:35:391003}
[email protected]4df10d612008-11-12 00:38:261004
[email protected]0633e3152011-11-28 18:35:391005bool timeout_occurred = false;
[email protected]4df10d612008-11-12 00:38:261006
[email protected]0633e3152011-11-28 18:35:391007void TimeoutCallback() {
1008 timeout_occurred = true;
1009}
[email protected]4df10d612008-11-12 00:38:261010
1011class DoneEventRaceServer : public Worker {
1012 public:
sammc4bcc4ed62016-10-27 10:13:591013 explicit DoneEventRaceServer(mojo::ScopedMessagePipeHandle channel_handle)
1014 : Worker(Channel::MODE_SERVER,
1015 "done_event_race_server",
1016 std::move(channel_handle)) {}
[email protected]4df10d612008-11-12 00:38:261017
dchengfe61fca2014-10-22 02:29:521018 void Run() override {
skyostile687bdff2015-05-12 11:29:211019 base::ThreadTaskRunnerHandle::Get()->PostTask(
1020 FROM_HERE, base::Bind(&NestedCallback, this));
1021 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1022 FROM_HERE, base::Bind(&TimeoutCallback),
[email protected]5896fa042012-03-07 04:41:401023 base::TimeDelta::FromSeconds(9));
[email protected]4df10d612008-11-12 00:38:261024 // Even though we have a timeout on the Send, it will succeed since for this
1025 // bug, the reply message comes back and is deserialized, however the done
1026 // event wasn't set. So we indirectly use the timeout task to notice if a
1027 // timeout occurred.
[email protected]5855f1d2014-04-16 16:50:431028 SendAnswerToLife(true, true);
[email protected]0633e3152011-11-28 18:35:391029 DCHECK(!timeout_occurred);
[email protected]4df10d612008-11-12 00:38:261030 Done();
1031 }
1032};
1033
tfarina8514f0d2015-07-28 14:41:471034#if defined(OS_ANDROID)
1035#define MAYBE_DoneEventRace DISABLED_DoneEventRace
1036#else
1037#define MAYBE_DoneEventRace DoneEventRace
1038#endif
[email protected]4df10d612008-11-12 00:38:261039// Tests http://b/1474092 - that if after the done_event is set but before
1040// OnObjectSignaled is called another message is sent out, then after its
1041// reply comes back OnObjectSignaled will be called for the first message.
tfarina8514f0d2015-07-28 14:41:471042TEST_F(IPCSyncChannelTest, MAYBE_DoneEventRace) {
[email protected]4df10d612008-11-12 00:38:261043 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:591044 mojo::MessagePipe pipe;
1045 workers.push_back(new DoneEventRaceServer(std::move(pipe.handle0)));
1046 workers.push_back(new SimpleClient(std::move(pipe.handle1)));
[email protected]4df10d612008-11-12 00:38:261047 RunTest(workers);
1048}
[email protected]1e9499c2010-04-06 20:33:361049
[email protected]2a3aa7b52013-01-11 20:56:221050//------------------------------------------------------------------------------
[email protected]1e9499c2010-04-06 20:33:361051
[email protected]c9e0c7332011-05-13 22:42:411052class TestSyncMessageFilter : public SyncMessageFilter {
[email protected]1e9499c2010-04-06 20:33:361053 public:
skyostile687bdff2015-05-12 11:29:211054 TestSyncMessageFilter(
1055 base::WaitableEvent* shutdown_event,
1056 Worker* worker,
1057 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
rockotb97e3d32016-09-16 17:39:031058 : SyncMessageFilter(shutdown_event),
[email protected]1e9499c2010-04-06 20:33:361059 worker_(worker),
skyostile687bdff2015-05-12 11:29:211060 task_runner_(task_runner) {}
[email protected]1e9499c2010-04-06 20:33:361061
rockote0072ebd2016-09-16 23:40:301062 void OnFilterAdded(Channel* channel) override {
1063 SyncMessageFilter::OnFilterAdded(channel);
skyostile687bdff2015-05-12 11:29:211064 task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:411065 FROM_HERE,
1066 base::Bind(&TestSyncMessageFilter::SendMessageOnHelperThread, this));
[email protected]1e9499c2010-04-06 20:33:361067 }
1068
1069 void SendMessageOnHelperThread() {
1070 int answer = 0;
1071 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
1072 DCHECK(result);
1073 DCHECK_EQ(answer, 42);
1074
1075 worker_->Done();
1076 }
1077
[email protected]f729d15a2012-04-28 02:12:001078 private:
dchengfe61fca2014-10-22 02:29:521079 ~TestSyncMessageFilter() override {}
[email protected]f729d15a2012-04-28 02:12:001080
[email protected]1e9499c2010-04-06 20:33:361081 Worker* worker_;
skyostile687bdff2015-05-12 11:29:211082 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
[email protected]1e9499c2010-04-06 20:33:361083};
1084
1085class SyncMessageFilterServer : public Worker {
1086 public:
sammc4bcc4ed62016-10-27 10:13:591087 explicit SyncMessageFilterServer(mojo::ScopedMessagePipeHandle channel_handle)
erikchen99fbfc662016-04-08 22:37:481088 : Worker(Channel::MODE_SERVER,
1089 "sync_message_filter_server",
sammc4bcc4ed62016-10-27 10:13:591090 std::move(channel_handle)),
[email protected]d4fc4d6a2012-09-08 01:24:491091 thread_("helper_thread") {
1092 base::Thread::Options options;
[email protected]fd0a773a2013-04-30 20:55:031093 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
[email protected]d4fc4d6a2012-09-08 01:24:491094 thread_.StartWithOptions(options);
1095 filter_ = new TestSyncMessageFilter(shutdown_event(), this,
skyostile687bdff2015-05-12 11:29:211096 thread_.task_runner());
[email protected]1e9499c2010-04-06 20:33:361097 }
1098
dchengfe61fca2014-10-22 02:29:521099 void Run() override {
dchengf3076af2014-10-21 18:02:421100 channel()->AddFilter(filter_.get());
1101 }
[email protected]1e9499c2010-04-06 20:33:361102
[email protected]d4fc4d6a2012-09-08 01:24:491103 base::Thread thread_;
[email protected]1e9499c2010-04-06 20:33:361104 scoped_refptr<TestSyncMessageFilter> filter_;
1105};
1106
[email protected]87339f02010-09-02 21:45:501107// This class provides functionality to test the case that a Send on the sync
1108// channel does not crash after the channel has been closed.
1109class ServerSendAfterClose : public Worker {
1110 public:
sammc4bcc4ed62016-10-27 10:13:591111 explicit ServerSendAfterClose(mojo::ScopedMessagePipeHandle channel_handle)
1112 : Worker(Channel::MODE_SERVER,
1113 "simpler_server",
1114 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:481115 send_result_(true) {}
[email protected]87339f02010-09-02 21:45:501116
1117 bool SendDummy() {
skyostile687bdff2015-05-12 11:29:211118 ListenerThread()->task_runner()->PostTask(
[email protected]dcde7672012-01-06 02:37:171119 FROM_HERE, base::Bind(base::IgnoreResult(&ServerSendAfterClose::Send),
1120 this, new SyncChannelTestMsg_NoArgs));
[email protected]87339f02010-09-02 21:45:501121 return true;
1122 }
1123
1124 bool send_result() const {
1125 return send_result_;
1126 }
1127
1128 private:
dchengfe61fca2014-10-22 02:29:521129 void Run() override {
[email protected]87339f02010-09-02 21:45:501130 CloseChannel();
1131 Done();
1132 }
1133
dchengfe61fca2014-10-22 02:29:521134 bool Send(Message* msg) override {
[email protected]87339f02010-09-02 21:45:501135 send_result_ = Worker::Send(msg);
1136 Done();
1137 return send_result_;
1138 }
1139
1140 bool send_result_;
1141};
1142
[email protected]1e9499c2010-04-06 20:33:361143// Tests basic synchronous call
1144TEST_F(IPCSyncChannelTest, SyncMessageFilter) {
1145 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:591146 mojo::MessagePipe pipe;
1147 workers.push_back(new SyncMessageFilterServer(std::move(pipe.handle0)));
1148 workers.push_back(new SimpleClient(std::move(pipe.handle1)));
[email protected]1e9499c2010-04-06 20:33:361149 RunTest(workers);
1150}
[email protected]87339f02010-09-02 21:45:501151
1152// Test the case when the channel is closed and a Send is attempted after that.
1153TEST_F(IPCSyncChannelTest, SendAfterClose) {
sammc4bcc4ed62016-10-27 10:13:591154 mojo::MessagePipe pipe;
1155 ServerSendAfterClose server(std::move(pipe.handle0));
[email protected]87339f02010-09-02 21:45:501156 server.Start();
1157
1158 server.done_event()->Wait();
1159 server.done_event()->Reset();
1160
1161 server.SendDummy();
1162 server.done_event()->Wait();
1163
1164 EXPECT_FALSE(server.send_result());
[email protected]bf2a9092013-01-08 06:09:071165
1166 server.Shutdown();
[email protected]87339f02010-09-02 21:45:501167}
1168
[email protected]2a3aa7b52013-01-11 20:56:221169//------------------------------------------------------------------------------
[email protected]54af05f2011-04-08 03:38:211170
1171class RestrictedDispatchServer : public Worker {
1172 public:
[email protected]298ee7d2012-03-30 21:29:301173 RestrictedDispatchServer(WaitableEvent* sent_ping_event,
sammc4bcc4ed62016-10-27 10:13:591174 WaitableEvent* wait_event,
1175 mojo::ScopedMessagePipeHandle channel_handle)
1176 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]298ee7d2012-03-30 21:29:301177 sent_ping_event_(sent_ping_event),
sammc4bcc4ed62016-10-27 10:13:591178 wait_event_(wait_event) {}
[email protected]54af05f2011-04-08 03:38:211179
1180 void OnDoPing(int ping) {
1181 // Send an asynchronous message that unblocks the caller.
[email protected]c9e0c7332011-05-13 22:42:411182 Message* msg = new SyncChannelTestMsg_Ping(ping);
[email protected]54af05f2011-04-08 03:38:211183 msg->set_unblock(true);
1184 Send(msg);
1185 // Signal the event after the message has been sent on the channel, on the
1186 // IPC thread.
skyostile687bdff2015-05-12 11:29:211187 ipc_thread().task_runner()->PostTask(
[email protected]72b6f8e22011-11-12 21:16:411188 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent, this));
[email protected]54af05f2011-04-08 03:38:211189 }
1190
[email protected]298ee7d2012-03-30 21:29:301191 void OnPingTTL(int ping, int* out) {
1192 *out = ping;
1193 wait_event_->Wait();
1194 }
1195
[email protected]54af05f2011-04-08 03:38:211196 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1197
1198 private:
dchengfe61fca2014-10-22 02:29:521199 bool OnMessageReceived(const Message& message) override {
[email protected]54af05f2011-04-08 03:38:211200 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message)
1201 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
[email protected]298ee7d2012-03-30 21:29:301202 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
[email protected]54af05f2011-04-08 03:38:211203 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1204 IPC_END_MESSAGE_MAP()
1205 return true;
1206 }
1207
1208 void OnPingSent() {
1209 sent_ping_event_->Signal();
1210 }
1211
1212 void OnNoArgs() { }
1213 WaitableEvent* sent_ping_event_;
[email protected]298ee7d2012-03-30 21:29:301214 WaitableEvent* wait_event_;
[email protected]54af05f2011-04-08 03:38:211215};
1216
1217class NonRestrictedDispatchServer : public Worker {
1218 public:
sammc4bcc4ed62016-10-27 10:13:591219 NonRestrictedDispatchServer(WaitableEvent* signal_event,
1220 mojo::ScopedMessagePipeHandle channel_handle)
1221 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]298ee7d2012-03-30 21:29:301222 signal_event_(signal_event) {}
1223
1224 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1225
1226 void OnDoPingTTL(int ping) {
1227 int value = 0;
1228 Send(new SyncChannelTestMsg_PingTTL(ping, &value));
1229 signal_event_->Signal();
1230 }
[email protected]54af05f2011-04-08 03:38:211231
1232 private:
dchengfe61fca2014-10-22 02:29:521233 bool OnMessageReceived(const Message& message) override {
[email protected]54af05f2011-04-08 03:38:211234 IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message)
1235 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1236 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1237 IPC_END_MESSAGE_MAP()
1238 return true;
1239 }
1240
1241 void OnNoArgs() { }
[email protected]298ee7d2012-03-30 21:29:301242 WaitableEvent* signal_event_;
[email protected]54af05f2011-04-08 03:38:211243};
1244
1245class RestrictedDispatchClient : public Worker {
1246 public:
sammc4bcc4ed62016-10-27 10:13:591247 RestrictedDispatchClient(
1248 WaitableEvent* sent_ping_event,
1249 RestrictedDispatchServer* server,
1250 NonRestrictedDispatchServer* server2,
1251 int* success,
1252 mojo::ScopedMessagePipeHandle restricted_channel_handle,
1253 mojo::ScopedMessagePipeHandle non_restricted_channel_handle)
1254 : Worker(std::move(restricted_channel_handle), Channel::MODE_CLIENT),
[email protected]54af05f2011-04-08 03:38:211255 ping_(0),
1256 server_(server),
[email protected]298ee7d2012-03-30 21:29:301257 server2_(server2),
[email protected]54af05f2011-04-08 03:38:211258 success_(success),
sammc4bcc4ed62016-10-27 10:13:591259 sent_ping_event_(sent_ping_event),
1260 non_restricted_channel_handle_(
1261 std::move(non_restricted_channel_handle)) {}
[email protected]54af05f2011-04-08 03:38:211262
dchengfe61fca2014-10-22 02:29:521263 void Run() override {
[email protected]54af05f2011-04-08 03:38:211264 // Incoming messages from our channel should only be dispatched when we
1265 // send a message on that same channel.
[email protected]298ee7d2012-03-30 21:29:301266 channel()->SetRestrictDispatchChannelGroup(1);
[email protected]54af05f2011-04-08 03:38:211267
skyostile687bdff2015-05-12 11:29:211268 server_->ListenerThread()->task_runner()->PostTask(
[email protected]72b6f8e22011-11-12 21:16:411269 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 1));
[email protected]54af05f2011-04-08 03:38:211270 sent_ping_event_->Wait();
1271 Send(new SyncChannelTestMsg_NoArgs);
1272 if (ping_ == 1)
1273 ++*success_;
1274 else
1275 LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
1276
skyostile687bdff2015-05-12 11:29:211277 non_restricted_channel_ = SyncChannel::Create(
sammc4bcc4ed62016-10-27 10:13:591278 non_restricted_channel_handle_.release(), IPC::Channel::MODE_CLIENT,
1279 this, ipc_thread().task_runner(), true, shutdown_event());
[email protected]54af05f2011-04-08 03:38:211280
skyostile687bdff2015-05-12 11:29:211281 server_->ListenerThread()->task_runner()->PostTask(
[email protected]72b6f8e22011-11-12 21:16:411282 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 2));
[email protected]54af05f2011-04-08 03:38:211283 sent_ping_event_->Wait();
1284 // Check that the incoming message is *not* dispatched when sending on the
1285 // non restricted channel.
1286 // TODO(piman): there is a possibility of a false positive race condition
1287 // here, if the message that was posted on the server-side end of the pipe
1288 // is not visible yet on the client side, but I don't know how to solve this
1289 // without hooking into the internals of SyncChannel. I haven't seen it in
1290 // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause
1291 // the following to fail).
[email protected]298ee7d2012-03-30 21:29:301292 non_restricted_channel_->Send(new SyncChannelTestMsg_NoArgs);
[email protected]54af05f2011-04-08 03:38:211293 if (ping_ == 1)
1294 ++*success_;
1295 else
1296 LOG(ERROR) << "Send dispatched message from restricted channel";
1297
1298 Send(new SyncChannelTestMsg_NoArgs);
1299 if (ping_ == 2)
1300 ++*success_;
1301 else
1302 LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
1303
[email protected]298ee7d2012-03-30 21:29:301304 // Check that the incoming message on the non-restricted channel is
1305 // dispatched when sending on the restricted channel.
skyostile687bdff2015-05-12 11:29:211306 server2_->ListenerThread()->task_runner()->PostTask(
[email protected]298ee7d2012-03-30 21:29:301307 FROM_HERE,
1308 base::Bind(&NonRestrictedDispatchServer::OnDoPingTTL, server2_, 3));
1309 int value = 0;
1310 Send(new SyncChannelTestMsg_PingTTL(4, &value));
1311 if (ping_ == 3 && value == 4)
1312 ++*success_;
1313 else
1314 LOG(ERROR) << "Send failed to dispatch message from unrestricted channel";
1315
1316 non_restricted_channel_->Send(new SyncChannelTestMsg_Done);
1317 non_restricted_channel_.reset();
[email protected]54af05f2011-04-08 03:38:211318 Send(new SyncChannelTestMsg_Done);
1319 Done();
1320 }
1321
1322 private:
dchengfe61fca2014-10-22 02:29:521323 bool OnMessageReceived(const Message& message) override {
[email protected]54af05f2011-04-08 03:38:211324 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message)
1325 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing)
[email protected]298ee7d2012-03-30 21:29:301326 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_PingTTL, OnPingTTL)
[email protected]54af05f2011-04-08 03:38:211327 IPC_END_MESSAGE_MAP()
1328 return true;
1329 }
1330
1331 void OnPing(int ping) {
1332 ping_ = ping;
1333 }
1334
[email protected]298ee7d2012-03-30 21:29:301335 void OnPingTTL(int ping, IPC::Message* reply) {
1336 ping_ = ping;
1337 // This message comes from the NonRestrictedDispatchServer, we have to send
1338 // the reply back manually.
1339 SyncChannelTestMsg_PingTTL::WriteReplyParams(reply, ping);
1340 non_restricted_channel_->Send(reply);
1341 }
1342
[email protected]54af05f2011-04-08 03:38:211343 int ping_;
1344 RestrictedDispatchServer* server_;
[email protected]298ee7d2012-03-30 21:29:301345 NonRestrictedDispatchServer* server2_;
[email protected]54af05f2011-04-08 03:38:211346 int* success_;
1347 WaitableEvent* sent_ping_event_;
danakj03de39b22016-04-23 04:21:091348 std::unique_ptr<SyncChannel> non_restricted_channel_;
sammc4bcc4ed62016-10-27 10:13:591349 mojo::ScopedMessagePipeHandle non_restricted_channel_handle_;
[email protected]54af05f2011-04-08 03:38:211350};
1351
[email protected]54af05f2011-04-08 03:38:211352TEST_F(IPCSyncChannelTest, RestrictedDispatch) {
gab90c2c5c2016-06-01 20:34:061353 WaitableEvent sent_ping_event(
1354 base::WaitableEvent::ResetPolicy::AUTOMATIC,
1355 base::WaitableEvent::InitialState::NOT_SIGNALED);
1356 WaitableEvent wait_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1357 base::WaitableEvent::InitialState::NOT_SIGNALED);
sammc4bcc4ed62016-10-27 10:13:591358 mojo::MessagePipe restricted_pipe, non_restricted_pipe;
1359 RestrictedDispatchServer* server = new RestrictedDispatchServer(
1360 &sent_ping_event, &wait_event, std::move(restricted_pipe.handle0));
1361 NonRestrictedDispatchServer* server2 = new NonRestrictedDispatchServer(
1362 &wait_event, std::move(non_restricted_pipe.handle0));
[email protected]298ee7d2012-03-30 21:29:301363
[email protected]54af05f2011-04-08 03:38:211364 int success = 0;
1365 std::vector<Worker*> workers;
[email protected]54af05f2011-04-08 03:38:211366 workers.push_back(server);
[email protected]298ee7d2012-03-30 21:29:301367 workers.push_back(server2);
sammc4bcc4ed62016-10-27 10:13:591368 workers.push_back(
1369 new RestrictedDispatchClient(&sent_ping_event, server, server2, &success,
1370 std::move(restricted_pipe.handle1),
1371 std::move(non_restricted_pipe.handle1)));
[email protected]54af05f2011-04-08 03:38:211372 RunTest(workers);
[email protected]298ee7d2012-03-30 21:29:301373 EXPECT_EQ(4, success);
[email protected]54af05f2011-04-08 03:38:211374}
[email protected]c9e0c7332011-05-13 22:42:411375
[email protected]2a3aa7b52013-01-11 20:56:221376//------------------------------------------------------------------------------
[email protected]522cc10d2012-01-11 22:39:541377
1378// This test case inspired by crbug.com/108491
1379// We create two servers that use the same ListenerThread but have
1380// SetRestrictDispatchToSameChannel set to true.
1381// We create clients, then use some specific WaitableEvent wait/signalling to
1382// ensure that messages get dispatched in a way that causes a deadlock due to
1383// a nested dispatch and an eligible message in a higher-level dispatch's
1384// delayed_queue. Specifically, we start with client1 about so send an
1385// unblocking message to server1, while the shared listener thread for the
1386// servers server1 and server2 is about to send a non-unblocking message to
1387// client1. At the same time, client2 will be about to send an unblocking
1388// message to server2. Server1 will handle the client1->server1 message by
1389// telling server2 to send a non-unblocking message to client2.
1390// What should happen is that the send to server2 should find the pending,
1391// same-context client2->server2 message to dispatch, causing client2 to
1392// unblock then handle the server2->client2 message, so that the shared
1393// servers' listener thread can then respond to the client1->server1 message.
1394// Then client1 can handle the non-unblocking server1->client1 message.
1395// The old code would end up in a state where the server2->client2 message is
1396// sent, but the client2->server2 message (which is eligible for dispatch, and
1397// which is what client2 is waiting for) is stashed in a local delayed_queue
1398// that has server1's channel context, causing a deadlock.
1399// WaitableEvents in the events array are used to:
1400// event 0: indicate to client1 that server listener is in OnDoServerTask
1401// event 1: indicate to client1 that client2 listener is in OnDoClient2Task
1402// event 2: indicate to server1 that client2 listener is in OnDoClient2Task
1403// event 3: indicate to client2 that server listener is in OnDoServerTask
1404
[email protected]522cc10d2012-01-11 22:39:541405class RestrictedDispatchDeadlockServer : public Worker {
1406 public:
1407 RestrictedDispatchDeadlockServer(int server_num,
1408 WaitableEvent* server_ready_event,
1409 WaitableEvent** events,
sammc4bcc4ed62016-10-27 10:13:591410 RestrictedDispatchDeadlockServer* peer,
1411 mojo::ScopedMessagePipeHandle channel_handle)
1412 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]522cc10d2012-01-11 22:39:541413 server_num_(server_num),
1414 server_ready_event_(server_ready_event),
1415 events_(events),
sammc4bcc4ed62016-10-27 10:13:591416 peer_(peer) {}
[email protected]522cc10d2012-01-11 22:39:541417
1418 void OnDoServerTask() {
1419 events_[3]->Signal();
1420 events_[2]->Wait();
1421 events_[0]->Signal();
1422 SendMessageToClient();
1423 }
1424
dchengfe61fca2014-10-22 02:29:521425 void Run() override {
[email protected]298ee7d2012-03-30 21:29:301426 channel()->SetRestrictDispatchChannelGroup(1);
[email protected]522cc10d2012-01-11 22:39:541427 server_ready_event_->Signal();
1428 }
1429
1430 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1431
1432 private:
dchengfe61fca2014-10-22 02:29:521433 bool OnMessageReceived(const Message& message) override {
[email protected]522cc10d2012-01-11 22:39:541434 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message)
1435 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1436 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1437 IPC_END_MESSAGE_MAP()
1438 return true;
1439 }
1440
1441 void OnNoArgs() {
1442 if (server_num_ == 1) {
1443 DCHECK(peer_ != NULL);
1444 peer_->SendMessageToClient();
1445 }
1446 }
1447
1448 void SendMessageToClient() {
1449 Message* msg = new SyncChannelTestMsg_NoArgs;
1450 msg->set_unblock(false);
1451 DCHECK(!msg->should_unblock());
1452 Send(msg);
1453 }
1454
1455 int server_num_;
1456 WaitableEvent* server_ready_event_;
1457 WaitableEvent** events_;
1458 RestrictedDispatchDeadlockServer* peer_;
[email protected]522cc10d2012-01-11 22:39:541459};
1460
1461class RestrictedDispatchDeadlockClient2 : public Worker {
1462 public:
sammc4bcc4ed62016-10-27 10:13:591463 RestrictedDispatchDeadlockClient2(
1464 RestrictedDispatchDeadlockServer* server,
1465 WaitableEvent* server_ready_event,
1466 WaitableEvent** events,
1467 mojo::ScopedMessagePipeHandle channel_handle)
1468 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
[email protected]522cc10d2012-01-11 22:39:541469 server_ready_event_(server_ready_event),
1470 events_(events),
1471 received_msg_(false),
1472 received_noarg_reply_(false),
1473 done_issued_(false) {}
1474
dchengfe61fca2014-10-22 02:29:521475 void Run() override {
dchengf3076af2014-10-21 18:02:421476 server_ready_event_->Wait();
1477 }
[email protected]522cc10d2012-01-11 22:39:541478
1479 void OnDoClient2Task() {
1480 events_[3]->Wait();
1481 events_[1]->Signal();
1482 events_[2]->Signal();
1483 DCHECK(received_msg_ == false);
1484
1485 Message* message = new SyncChannelTestMsg_NoArgs;
1486 message->set_unblock(true);
1487 Send(message);
1488 received_noarg_reply_ = true;
1489 }
1490
1491 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1492 private:
dchengfe61fca2014-10-22 02:29:521493 bool OnMessageReceived(const Message& message) override {
[email protected]522cc10d2012-01-11 22:39:541494 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message)
1495 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1496 IPC_END_MESSAGE_MAP()
1497 return true;
1498 }
1499
1500 void OnNoArgs() {
1501 received_msg_ = true;
1502 PossiblyDone();
1503 }
1504
1505 void PossiblyDone() {
1506 if (received_noarg_reply_ && received_msg_) {
1507 DCHECK(done_issued_ == false);
1508 done_issued_ = true;
1509 Send(new SyncChannelTestMsg_Done);
1510 Done();
1511 }
1512 }
1513
[email protected]522cc10d2012-01-11 22:39:541514 WaitableEvent* server_ready_event_;
1515 WaitableEvent** events_;
1516 bool received_msg_;
1517 bool received_noarg_reply_;
1518 bool done_issued_;
1519};
1520
1521class RestrictedDispatchDeadlockClient1 : public Worker {
1522 public:
sammc4bcc4ed62016-10-27 10:13:591523 RestrictedDispatchDeadlockClient1(
1524 RestrictedDispatchDeadlockServer* server,
1525 RestrictedDispatchDeadlockClient2* peer,
1526 WaitableEvent* server_ready_event,
1527 WaitableEvent** events,
1528 mojo::ScopedMessagePipeHandle channel_handle)
1529 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
[email protected]522cc10d2012-01-11 22:39:541530 server_(server),
1531 peer_(peer),
1532 server_ready_event_(server_ready_event),
1533 events_(events),
1534 received_msg_(false),
1535 received_noarg_reply_(false),
1536 done_issued_(false) {}
1537
dchengfe61fca2014-10-22 02:29:521538 void Run() override {
[email protected]522cc10d2012-01-11 22:39:541539 server_ready_event_->Wait();
skyostile687bdff2015-05-12 11:29:211540 server_->ListenerThread()->task_runner()->PostTask(
[email protected]522cc10d2012-01-11 22:39:541541 FROM_HERE,
1542 base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, server_));
skyostile687bdff2015-05-12 11:29:211543 peer_->ListenerThread()->task_runner()->PostTask(
[email protected]522cc10d2012-01-11 22:39:541544 FROM_HERE,
1545 base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, peer_));
1546 events_[0]->Wait();
1547 events_[1]->Wait();
1548 DCHECK(received_msg_ == false);
1549
1550 Message* message = new SyncChannelTestMsg_NoArgs;
1551 message->set_unblock(true);
1552 Send(message);
1553 received_noarg_reply_ = true;
1554 PossiblyDone();
1555 }
1556
[email protected]522cc10d2012-01-11 22:39:541557 private:
dchengfe61fca2014-10-22 02:29:521558 bool OnMessageReceived(const Message& message) override {
[email protected]522cc10d2012-01-11 22:39:541559 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message)
1560 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1561 IPC_END_MESSAGE_MAP()
1562 return true;
1563 }
1564
1565 void OnNoArgs() {
1566 received_msg_ = true;
1567 PossiblyDone();
1568 }
1569
1570 void PossiblyDone() {
1571 if (received_noarg_reply_ && received_msg_) {
1572 DCHECK(done_issued_ == false);
1573 done_issued_ = true;
1574 Send(new SyncChannelTestMsg_Done);
1575 Done();
1576 }
1577 }
1578
1579 RestrictedDispatchDeadlockServer* server_;
1580 RestrictedDispatchDeadlockClient2* peer_;
1581 WaitableEvent* server_ready_event_;
1582 WaitableEvent** events_;
1583 bool received_msg_;
1584 bool received_noarg_reply_;
1585 bool done_issued_;
1586};
1587
[email protected]522cc10d2012-01-11 22:39:541588TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) {
1589 std::vector<Worker*> workers;
1590
1591 // A shared worker thread so that server1 and server2 run on one thread.
1592 base::Thread worker_thread("RestrictedDispatchDeadlock");
1593 ASSERT_TRUE(worker_thread.Start());
1594
gab90c2c5c2016-06-01 20:34:061595 WaitableEvent server1_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1596 base::WaitableEvent::InitialState::NOT_SIGNALED);
1597 WaitableEvent server2_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1598 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]522cc10d2012-01-11 22:39:541599
gab90c2c5c2016-06-01 20:34:061600 WaitableEvent event0(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1601 base::WaitableEvent::InitialState::NOT_SIGNALED);
1602 WaitableEvent event1(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1603 base::WaitableEvent::InitialState::NOT_SIGNALED);
1604 WaitableEvent event2(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1605 base::WaitableEvent::InitialState::NOT_SIGNALED);
1606 WaitableEvent event3(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1607 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]522cc10d2012-01-11 22:39:541608 WaitableEvent* events[4] = {&event0, &event1, &event2, &event3};
1609
1610 RestrictedDispatchDeadlockServer* server1;
1611 RestrictedDispatchDeadlockServer* server2;
1612 RestrictedDispatchDeadlockClient1* client1;
1613 RestrictedDispatchDeadlockClient2* client2;
1614
sammc4bcc4ed62016-10-27 10:13:591615 mojo::MessagePipe pipe1, pipe2;
1616 server2 = new RestrictedDispatchDeadlockServer(
1617 2, &server2_ready, events, NULL, std::move(pipe2.handle0));
[email protected]522cc10d2012-01-11 22:39:541618 server2->OverrideThread(&worker_thread);
1619 workers.push_back(server2);
1620
sammc4bcc4ed62016-10-27 10:13:591621 client2 = new RestrictedDispatchDeadlockClient2(
1622 server2, &server2_ready, events, std::move(pipe2.handle1));
[email protected]522cc10d2012-01-11 22:39:541623 workers.push_back(client2);
1624
sammc4bcc4ed62016-10-27 10:13:591625 server1 = new RestrictedDispatchDeadlockServer(
1626 1, &server1_ready, events, server2, std::move(pipe1.handle0));
[email protected]522cc10d2012-01-11 22:39:541627 server1->OverrideThread(&worker_thread);
1628 workers.push_back(server1);
1629
sammc4bcc4ed62016-10-27 10:13:591630 client1 = new RestrictedDispatchDeadlockClient1(
1631 server1, client2, &server1_ready, events, std::move(pipe1.handle1));
[email protected]522cc10d2012-01-11 22:39:541632 workers.push_back(client1);
1633
1634 RunTest(workers);
1635}
1636
[email protected]2a3aa7b52013-01-11 20:56:221637//------------------------------------------------------------------------------
[email protected]5c41e6e12012-03-17 02:20:461638
[email protected]298ee7d2012-03-30 21:29:301639// This test case inspired by crbug.com/120530
1640// We create 4 workers that pipe to each other W1->W2->W3->W4->W1 then we send a
1641// message that recurses through 3, 4 or 5 steps to make sure, say, W1 can
1642// re-enter when called from W4 while it's sending a message to W2.
1643// The first worker drives the whole test so it must be treated specially.
[email protected]298ee7d2012-03-30 21:29:301644
1645class RestrictedDispatchPipeWorker : public Worker {
1646 public:
sammc4bcc4ed62016-10-27 10:13:591647 RestrictedDispatchPipeWorker(mojo::ScopedMessagePipeHandle channel_handle1,
1648 WaitableEvent* event1,
1649 mojo::ScopedMessagePipeHandle channel_handle2,
1650 WaitableEvent* event2,
1651 int group,
1652 int* success)
1653 : Worker(std::move(channel_handle1), Channel::MODE_SERVER),
[email protected]298ee7d2012-03-30 21:29:301654 event1_(event1),
1655 event2_(event2),
sammc4bcc4ed62016-10-27 10:13:591656 other_channel_handle_(std::move(channel_handle2)),
[email protected]298ee7d2012-03-30 21:29:301657 group_(group),
sammc4bcc4ed62016-10-27 10:13:591658 success_(success) {}
[email protected]298ee7d2012-03-30 21:29:301659
1660 void OnPingTTL(int ping, int* ret) {
1661 *ret = 0;
1662 if (!ping)
1663 return;
1664 other_channel_->Send(new SyncChannelTestMsg_PingTTL(ping - 1, ret));
1665 ++*ret;
1666 }
1667
1668 void OnDone() {
1669 if (is_first())
1670 return;
1671 other_channel_->Send(new SyncChannelTestMsg_Done);
1672 other_channel_.reset();
1673 Done();
1674 }
1675
dchengfe61fca2014-10-22 02:29:521676 void Run() override {
[email protected]298ee7d2012-03-30 21:29:301677 channel()->SetRestrictDispatchChannelGroup(group_);
1678 if (is_first())
1679 event1_->Signal();
1680 event2_->Wait();
skyostile687bdff2015-05-12 11:29:211681 other_channel_ = SyncChannel::Create(
sammc4bcc4ed62016-10-27 10:13:591682 other_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
1683 ipc_thread().task_runner(), true, shutdown_event());
[email protected]298ee7d2012-03-30 21:29:301684 other_channel_->SetRestrictDispatchChannelGroup(group_);
1685 if (!is_first()) {
1686 event1_->Signal();
1687 return;
1688 }
1689 *success_ = 0;
1690 int value = 0;
1691 OnPingTTL(3, &value);
1692 *success_ += (value == 3);
1693 OnPingTTL(4, &value);
1694 *success_ += (value == 4);
1695 OnPingTTL(5, &value);
1696 *success_ += (value == 5);
1697 other_channel_->Send(new SyncChannelTestMsg_Done);
1698 other_channel_.reset();
1699 Done();
1700 }
1701
1702 bool is_first() { return !!success_; }
1703
1704 private:
dchengfe61fca2014-10-22 02:29:521705 bool OnMessageReceived(const Message& message) override {
[email protected]298ee7d2012-03-30 21:29:301706 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchPipeWorker, message)
1707 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
1708 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, OnDone)
1709 IPC_END_MESSAGE_MAP()
1710 return true;
1711 }
1712
danakj03de39b22016-04-23 04:21:091713 std::unique_ptr<SyncChannel> other_channel_;
[email protected]298ee7d2012-03-30 21:29:301714 WaitableEvent* event1_;
1715 WaitableEvent* event2_;
sammc4bcc4ed62016-10-27 10:13:591716 mojo::ScopedMessagePipeHandle other_channel_handle_;
[email protected]298ee7d2012-03-30 21:29:301717 int group_;
1718 int* success_;
1719};
1720
tfarina8514f0d2015-07-28 14:41:471721#if defined(OS_ANDROID)
1722#define MAYBE_RestrictedDispatch4WayDeadlock \
1723 DISABLED_RestrictedDispatch4WayDeadlock
1724#else
1725#define MAYBE_RestrictedDispatch4WayDeadlock RestrictedDispatch4WayDeadlock
1726#endif
1727TEST_F(IPCSyncChannelTest, MAYBE_RestrictedDispatch4WayDeadlock) {
[email protected]298ee7d2012-03-30 21:29:301728 int success = 0;
1729 std::vector<Worker*> workers;
gab90c2c5c2016-06-01 20:34:061730 WaitableEvent event0(base::WaitableEvent::ResetPolicy::MANUAL,
1731 base::WaitableEvent::InitialState::NOT_SIGNALED);
1732 WaitableEvent event1(base::WaitableEvent::ResetPolicy::MANUAL,
1733 base::WaitableEvent::InitialState::NOT_SIGNALED);
1734 WaitableEvent event2(base::WaitableEvent::ResetPolicy::MANUAL,
1735 base::WaitableEvent::InitialState::NOT_SIGNALED);
1736 WaitableEvent event3(base::WaitableEvent::ResetPolicy::MANUAL,
1737 base::WaitableEvent::InitialState::NOT_SIGNALED);
sammc4bcc4ed62016-10-27 10:13:591738 mojo::MessagePipe pipe0, pipe1, pipe2, pipe3;
[email protected]298ee7d2012-03-30 21:29:301739 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591740 std::move(pipe0.handle0), &event0, std::move(pipe1.handle1), &event1, 1,
1741 &success));
[email protected]298ee7d2012-03-30 21:29:301742 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591743 std::move(pipe1.handle0), &event1, std::move(pipe2.handle1), &event2, 2,
1744 NULL));
[email protected]298ee7d2012-03-30 21:29:301745 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591746 std::move(pipe2.handle0), &event2, std::move(pipe3.handle1), &event3, 3,
1747 NULL));
[email protected]298ee7d2012-03-30 21:29:301748 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591749 std::move(pipe3.handle0), &event3, std::move(pipe0.handle1), &event0, 4,
1750 NULL));
[email protected]298ee7d2012-03-30 21:29:301751 RunTest(workers);
1752 EXPECT_EQ(3, success);
1753}
1754
[email protected]2a3aa7b52013-01-11 20:56:221755//------------------------------------------------------------------------------
[email protected]9134cce6d2012-04-10 20:07:531756
[email protected]9134cce6d2012-04-10 20:07:531757// This test case inspired by crbug.com/122443
1758// We want to make sure a reply message with the unblock flag set correctly
1759// behaves as a reply, not a regular message.
1760// We have 3 workers. Server1 will send a message to Server2 (which will block),
1761// during which it will dispatch a message comming from Client, at which point
1762// it will send another message to Server2. While sending that second message it
1763// will receive a reply from Server1 with the unblock flag.
1764
[email protected]9134cce6d2012-04-10 20:07:531765class ReentrantReplyServer1 : public Worker {
1766 public:
sammc4bcc4ed62016-10-27 10:13:591767 ReentrantReplyServer1(WaitableEvent* server_ready,
1768 mojo::ScopedMessagePipeHandle channel_handle1,
1769 mojo::ScopedMessagePipeHandle channel_handle2)
1770 : Worker(std::move(channel_handle1), Channel::MODE_SERVER),
1771 server_ready_(server_ready),
1772 other_channel_handle_(std::move(channel_handle2)) {}
[email protected]9134cce6d2012-04-10 20:07:531773
dchengfe61fca2014-10-22 02:29:521774 void Run() override {
skyostile687bdff2015-05-12 11:29:211775 server2_channel_ = SyncChannel::Create(
sammc4bcc4ed62016-10-27 10:13:591776 other_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
1777 ipc_thread().task_runner(), true, shutdown_event());
[email protected]9134cce6d2012-04-10 20:07:531778 server_ready_->Signal();
1779 Message* msg = new SyncChannelTestMsg_Reentrant1();
1780 server2_channel_->Send(msg);
1781 server2_channel_.reset();
1782 Done();
1783 }
1784
1785 private:
dchengfe61fca2014-10-22 02:29:521786 bool OnMessageReceived(const Message& message) override {
[email protected]9134cce6d2012-04-10 20:07:531787 IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer1, message)
1788 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant2, OnReentrant2)
1789 IPC_REPLY_HANDLER(OnReply)
1790 IPC_END_MESSAGE_MAP()
1791 return true;
1792 }
1793
1794 void OnReentrant2() {
1795 Message* msg = new SyncChannelTestMsg_Reentrant3();
1796 server2_channel_->Send(msg);
1797 }
1798
1799 void OnReply(const Message& message) {
1800 // If we get here, the Send() will never receive the reply (thus would
1801 // hang), so abort instead.
1802 LOG(FATAL) << "Reply message was dispatched";
1803 }
1804
1805 WaitableEvent* server_ready_;
danakj03de39b22016-04-23 04:21:091806 std::unique_ptr<SyncChannel> server2_channel_;
sammc4bcc4ed62016-10-27 10:13:591807 mojo::ScopedMessagePipeHandle other_channel_handle_;
[email protected]9134cce6d2012-04-10 20:07:531808};
1809
1810class ReentrantReplyServer2 : public Worker {
1811 public:
sammc4bcc4ed62016-10-27 10:13:591812 ReentrantReplyServer2(mojo::ScopedMessagePipeHandle channel_handle)
1813 : Worker(std::move(channel_handle), Channel::MODE_SERVER), reply_(NULL) {}
[email protected]9134cce6d2012-04-10 20:07:531814
1815 private:
dchengfe61fca2014-10-22 02:29:521816 bool OnMessageReceived(const Message& message) override {
[email protected]9134cce6d2012-04-10 20:07:531817 IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer2, message)
1818 IPC_MESSAGE_HANDLER_DELAY_REPLY(
1819 SyncChannelTestMsg_Reentrant1, OnReentrant1)
1820 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant3, OnReentrant3)
1821 IPC_END_MESSAGE_MAP()
1822 return true;
1823 }
1824
1825 void OnReentrant1(Message* reply) {
1826 DCHECK(!reply_);
1827 reply_ = reply;
1828 }
1829
1830 void OnReentrant3() {
1831 DCHECK(reply_);
1832 Message* reply = reply_;
1833 reply_ = NULL;
1834 reply->set_unblock(true);
1835 Send(reply);
1836 Done();
1837 }
1838
1839 Message* reply_;
1840};
1841
1842class ReentrantReplyClient : public Worker {
1843 public:
sammc4bcc4ed62016-10-27 10:13:591844 ReentrantReplyClient(WaitableEvent* server_ready,
1845 mojo::ScopedMessagePipeHandle channel_handle)
1846 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
1847 server_ready_(server_ready) {}
[email protected]9134cce6d2012-04-10 20:07:531848
dchengfe61fca2014-10-22 02:29:521849 void Run() override {
[email protected]9134cce6d2012-04-10 20:07:531850 server_ready_->Wait();
1851 Send(new SyncChannelTestMsg_Reentrant2());
1852 Done();
1853 }
1854
1855 private:
1856 WaitableEvent* server_ready_;
1857};
1858
[email protected]9134cce6d2012-04-10 20:07:531859TEST_F(IPCSyncChannelTest, ReentrantReply) {
1860 std::vector<Worker*> workers;
gab90c2c5c2016-06-01 20:34:061861 WaitableEvent server_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1862 base::WaitableEvent::InitialState::NOT_SIGNALED);
sammc4bcc4ed62016-10-27 10:13:591863 mojo::MessagePipe pipe1, pipe2;
1864 workers.push_back(new ReentrantReplyServer2(std::move(pipe2.handle0)));
1865 workers.push_back(new ReentrantReplyServer1(
1866 &server_ready, std::move(pipe1.handle0), std::move(pipe2.handle1)));
1867 workers.push_back(
1868 new ReentrantReplyClient(&server_ready, std::move(pipe1.handle1)));
[email protected]9134cce6d2012-04-10 20:07:531869 RunTest(workers);
1870}
1871
[email protected]2a3aa7b52013-01-11 20:56:221872} // namespace
[email protected]2d6e6a72013-02-08 20:11:021873} // namespace IPC