blob: f59ccedd018e4458ce2bdd32efad970d30be2e15 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// 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//
5// Unit test for SyncChannel.
6
initial.commit09911bf2008-07-26 23:55:297#include <string>
8#include <vector>
9
10#include "base/basictypes.h"
11#include "base/logging.h"
12#include "base/message_loop.h"
[email protected]aa96ae772009-01-20 22:08:1513#include "base/platform_thread.h"
initial.commit09911bf2008-07-26 23:55:2914#include "base/string_util.h"
15#include "base/thread.h"
[email protected]aa96ae772009-01-20 22:08:1516#include "base/waitable_event.h"
initial.commit09911bf2008-07-26 23:55:2917#include "chrome/common/ipc_message.h"
18#include "chrome/common/ipc_sync_channel.h"
19#include "chrome/common/stl_util-inl.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
initial.commit09911bf2008-07-26 23:55:2922
[email protected]f91cb992009-02-04 20:10:1223#define MESSAGES_INTERNAL_FILE "chrome/common/ipc_sync_message_unittest.h"
24#include "chrome/common/ipc_message_macros.h"
initial.commit09911bf2008-07-26 23:55:2925
26using namespace IPC;
[email protected]aa96ae772009-01-20 22:08:1527using base::WaitableEvent;
initial.commit09911bf2008-07-26 23:55:2928
[email protected]dd3eac22008-08-26 07:28:3429namespace {
30
initial.commit09911bf2008-07-26 23:55:2931// Base class for a "process" with listener and IPC threads.
32class Worker : public Channel::Listener, public Message::Sender {
33 public:
34 // Will create a channel without a name.
35 Worker(Channel::Mode mode, const std::string& thread_name)
[email protected]aa96ae772009-01-20 22:08:1536 : done_(new WaitableEvent(false, false)),
37 channel_created_(new WaitableEvent(false, false)),
initial.commit09911bf2008-07-26 23:55:2938 mode_(mode),
39 ipc_thread_((thread_name + "_ipc").c_str()),
40 listener_thread_((thread_name + "_listener").c_str()),
[email protected]8930d472009-02-21 08:05:2841 overrided_thread_(NULL),
42 shutdown_event_(true, false) { }
initial.commit09911bf2008-07-26 23:55:2943
44 // Will create a named channel and use this name for the threads' name.
45 Worker(const std::wstring& channel_name, Channel::Mode mode)
[email protected]aa96ae772009-01-20 22:08:1546 : done_(new WaitableEvent(false, false)),
47 channel_created_(new WaitableEvent(false, false)),
48 channel_name_(channel_name),
initial.commit09911bf2008-07-26 23:55:2949 mode_(mode),
50 ipc_thread_((WideToUTF8(channel_name) + "_ipc").c_str()),
51 listener_thread_((WideToUTF8(channel_name) + "_listener").c_str()),
[email protected]8930d472009-02-21 08:05:2852 overrided_thread_(NULL),
53 shutdown_event_(true, false) { }
initial.commit09911bf2008-07-26 23:55:2954
55 // The IPC thread needs to outlive SyncChannel, so force the correct order of
56 // destruction.
57 virtual ~Worker() {
[email protected]aa96ae772009-01-20 22:08:1558 WaitableEvent listener_done(false, false), ipc_done(false, false);
[email protected]3cdb7af812008-10-24 19:21:1359 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]aa96ae772009-01-20 22:08:1560 this, &Worker::OnListenerThreadShutdown, &listener_done,
61 &ipc_done));
62 listener_done.Wait();
63 ipc_done.Wait();
initial.commit09911bf2008-07-26 23:55:2964 ipc_thread_.Stop();
65 listener_thread_.Stop();
initial.commit09911bf2008-07-26 23:55:2966 }
67 void AddRef() { }
68 void Release() { }
69 bool Send(Message* msg) { return channel_->Send(msg); }
[email protected]d65cab7a2008-08-12 01:25:4170 bool SendWithTimeout(Message* msg, int timeout_ms) {
71 return channel_->SendWithTimeout(msg, timeout_ms);
72 }
[email protected]aa96ae772009-01-20 22:08:1573 void WaitForChannelCreation() { channel_created_->Wait(); }
[email protected]3cdb7af812008-10-24 19:21:1374 void CloseChannel() {
75 DCHECK(MessageLoop::current() == ListenerThread()->message_loop());
76 channel_->Close();
77 }
initial.commit09911bf2008-07-26 23:55:2978 void Start() {
[email protected]17b89142008-11-07 21:52:1579 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT);
[email protected]3cdb7af812008-10-24 19:21:1380 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
initial.commit09911bf2008-07-26 23:55:2981 this, &Worker::OnStart));
82 }
[email protected]ab820df2008-08-26 05:55:1083 void OverrideThread(base::Thread* overrided_thread) {
initial.commit09911bf2008-07-26 23:55:2984 DCHECK(overrided_thread_ == NULL);
85 overrided_thread_ = overrided_thread;
86 }
[email protected]4df10d612008-11-12 00:38:2687 bool SendAnswerToLife(bool pump, int timeout, bool succeed) {
88 int answer = 0;
89 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
90 if (pump)
91 msg->EnableMessagePumping();
92 bool result = SendWithTimeout(msg, timeout);
93 DCHECK(result == succeed);
94 DCHECK(answer == (succeed ? 42 : 0));
95 return result;
96 }
97 bool SendDouble(bool pump, bool succeed) {
98 int answer = 0;
99 SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
100 if (pump)
101 msg->EnableMessagePumping();
102 bool result = Send(msg);
103 DCHECK(result == succeed);
104 DCHECK(answer == (succeed ? 10 : 0));
105 return result;
106 }
initial.commit09911bf2008-07-26 23:55:29107 Channel::Mode mode() { return mode_; }
[email protected]aa96ae772009-01-20 22:08:15108 WaitableEvent* done_event() { return done_.get(); }
initial.commit09911bf2008-07-26 23:55:29109
110 protected:
111 // Derived classes need to call this when they've completed their part of
112 // the test.
[email protected]aa96ae772009-01-20 22:08:15113 void Done() { done_->Signal(); }
initial.commit09911bf2008-07-26 23:55:29114 // Functions for dervied classes to implement if they wish.
115 virtual void Run() { }
initial.commit09911bf2008-07-26 23:55:29116 virtual void OnAnswer(int* answer) { NOTREACHED(); }
117 virtual void OnAnswerDelay(Message* reply_msg) {
118 // The message handler map below can only take one entry for
119 // SyncChannelTestMsg_AnswerToLife, so since some classes want
120 // the normal version while other want the delayed reply, we
121 // call the normal version if the derived class didn't override
122 // this function.
123 int answer;
124 OnAnswer(&answer);
125 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
126 Send(reply_msg);
127 }
[email protected]3cdb7af812008-10-24 19:21:13128 virtual void OnDouble(int in, int* out) { NOTREACHED(); }
129 virtual void OnDoubleDelay(int in, Message* reply_msg) {
130 int result;
131 OnDouble(in, &result);
132 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
133 Send(reply_msg);
134 }
initial.commit09911bf2008-07-26 23:55:29135
136 private:
[email protected]3cdb7af812008-10-24 19:21:13137 base::Thread* ListenerThread() {
138 return overrided_thread_ ? overrided_thread_ : &listener_thread_;
139 }
initial.commit09911bf2008-07-26 23:55:29140 // Called on the listener thread to create the sync channel.
141 void OnStart() {
initial.commit09911bf2008-07-26 23:55:29142 // Link ipc_thread_, listener_thread_ and channel_ altogether.
[email protected]17b89142008-11-07 21:52:15143 StartThread(&ipc_thread_, MessageLoop::TYPE_IO);
initial.commit09911bf2008-07-26 23:55:29144 channel_.reset(new SyncChannel(
[email protected]d65cab7a2008-08-12 01:25:41145 channel_name_, mode_, this, NULL, ipc_thread_.message_loop(), true,
[email protected]8930d472009-02-21 08:05:28146 &shutdown_event_));
[email protected]aa96ae772009-01-20 22:08:15147 channel_created_->Signal();
initial.commit09911bf2008-07-26 23:55:29148 Run();
149 }
150
[email protected]aa96ae772009-01-20 22:08:15151 void OnListenerThreadShutdown(WaitableEvent* listener_event,
152 WaitableEvent* ipc_event) {
[email protected]3cdb7af812008-10-24 19:21:13153 // SyncChannel needs to be destructed on the thread that it was created on.
154 channel_.reset();
[email protected]aa96ae772009-01-20 22:08:15155 listener_event->Signal();
156
[email protected]3cdb7af812008-10-24 19:21:13157 ipc_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
158 this, &Worker::OnIPCThreadShutdown, ipc_event));
159 }
160
[email protected]aa96ae772009-01-20 22:08:15161 void OnIPCThreadShutdown(WaitableEvent* ipc_event) {
162 ipc_event->Signal();
[email protected]3cdb7af812008-10-24 19:21:13163 }
164
initial.commit09911bf2008-07-26 23:55:29165 void OnMessageReceived(const Message& message) {
166 IPC_BEGIN_MESSAGE_MAP(Worker, message)
[email protected]3cdb7af812008-10-24 19:21:13167 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
initial.commit09911bf2008-07-26 23:55:29168 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
169 OnAnswerDelay)
170 IPC_END_MESSAGE_MAP()
171 }
172
[email protected]17b89142008-11-07 21:52:15173 void StartThread(base::Thread* thread, MessageLoop::Type type) {
[email protected]ab820df2008-08-26 05:55:10174 base::Thread::Options options;
[email protected]17b89142008-11-07 21:52:15175 options.message_loop_type = type;
[email protected]ab820df2008-08-26 05:55:10176 thread->StartWithOptions(options);
177 }
178
[email protected]aa96ae772009-01-20 22:08:15179 scoped_ptr<WaitableEvent> done_;
180 scoped_ptr<WaitableEvent> channel_created_;
initial.commit09911bf2008-07-26 23:55:29181 std::wstring channel_name_;
182 Channel::Mode mode_;
183 scoped_ptr<SyncChannel> channel_;
[email protected]ab820df2008-08-26 05:55:10184 base::Thread ipc_thread_;
185 base::Thread listener_thread_;
186 base::Thread* overrided_thread_;
initial.commit09911bf2008-07-26 23:55:29187
[email protected]8930d472009-02-21 08:05:28188 base::WaitableEvent shutdown_event_;
189
initial.commit09911bf2008-07-26 23:55:29190 DISALLOW_EVIL_CONSTRUCTORS(Worker);
191};
192
193
194// Starts the test with the given workers. This function deletes the workers
195// when it's done.
196void RunTest(std::vector<Worker*> workers) {
initial.commit09911bf2008-07-26 23:55:29197 // First we create the workers that are channel servers, or else the other
198 // workers' channel initialization might fail because the pipe isn't created..
199 for (size_t i = 0; i < workers.size(); ++i) {
200 if (workers[i]->mode() == Channel::MODE_SERVER) {
201 workers[i]->Start();
202 workers[i]->WaitForChannelCreation();
203 }
204 }
205
206 // now create the clients
207 for (size_t i = 0; i < workers.size(); ++i) {
208 if (workers[i]->mode() == Channel::MODE_CLIENT)
209 workers[i]->Start();
210 }
211
212 // wait for all the workers to finish
initial.commit09911bf2008-07-26 23:55:29213 for (size_t i = 0; i < workers.size(); ++i)
[email protected]aa96ae772009-01-20 22:08:15214 workers[i]->done_event()->Wait();
initial.commit09911bf2008-07-26 23:55:29215
initial.commit09911bf2008-07-26 23:55:29216 STLDeleteContainerPointers(workers.begin(), workers.end());
217}
218
[email protected]dd3eac22008-08-26 07:28:34219} // namespace
220
[email protected]9629c0e2009-02-04 23:16:29221class IPCSyncChannelTest : public testing::Test {
222 private:
223 MessageLoop message_loop_;
224};
225
initial.commit09911bf2008-07-26 23:55:29226//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34227
228namespace {
229
initial.commit09911bf2008-07-26 23:55:29230class SimpleServer : public Worker {
231 public:
[email protected]3cdb7af812008-10-24 19:21:13232 SimpleServer(bool pump_during_send)
233 : Worker(Channel::MODE_SERVER, "simpler_server"),
234 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29235 void Run() {
[email protected]aa96ae772009-01-20 22:08:15236 SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
initial.commit09911bf2008-07-26 23:55:29237 Done();
238 }
[email protected]3cdb7af812008-10-24 19:21:13239
240 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29241};
242
243class SimpleClient : public Worker {
244 public:
245 SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { }
246
247 void OnAnswer(int* answer) {
248 *answer = 42;
249 Done();
250 }
251};
252
[email protected]3cdb7af812008-10-24 19:21:13253void Simple(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29254 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13255 workers.push_back(new SimpleServer(pump_during_send));
initial.commit09911bf2008-07-26 23:55:29256 workers.push_back(new SimpleClient());
257 RunTest(workers);
258}
259
[email protected]3cdb7af812008-10-24 19:21:13260} // namespace
261
262// Tests basic synchronous call
263TEST_F(IPCSyncChannelTest, Simple) {
264 Simple(false);
265 Simple(true);
266}
initial.commit09911bf2008-07-26 23:55:29267
268//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34269
270namespace {
271
initial.commit09911bf2008-07-26 23:55:29272class DelayClient : public Worker {
273 public:
274 DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { }
275
276 void OnAnswerDelay(Message* reply_msg) {
277 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
278 Send(reply_msg);
279 Done();
280 }
281};
282
[email protected]3cdb7af812008-10-24 19:21:13283void DelayReply(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29284 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13285 workers.push_back(new SimpleServer(pump_during_send));
initial.commit09911bf2008-07-26 23:55:29286 workers.push_back(new DelayClient());
287 RunTest(workers);
288}
289
[email protected]3cdb7af812008-10-24 19:21:13290} // namespace
291
292// Tests that asynchronous replies work
293TEST_F(IPCSyncChannelTest, DelayReply) {
294 DelayReply(false);
295 DelayReply(true);
296}
initial.commit09911bf2008-07-26 23:55:29297
298//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34299
300namespace {
301
initial.commit09911bf2008-07-26 23:55:29302class NoHangServer : public Worker {
303 public:
[email protected]aa96ae772009-01-20 22:08:15304 explicit NoHangServer(WaitableEvent* got_first_reply, bool pump_during_send)
[email protected]3cdb7af812008-10-24 19:21:13305 : Worker(Channel::MODE_SERVER, "no_hang_server"),
306 got_first_reply_(got_first_reply),
307 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29308 void Run() {
[email protected]aa96ae772009-01-20 22:08:15309 SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
310 got_first_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29311
[email protected]aa96ae772009-01-20 22:08:15312 SendAnswerToLife(pump_during_send_, base::kNoTimeout, false);
initial.commit09911bf2008-07-26 23:55:29313 Done();
314 }
315
[email protected]aa96ae772009-01-20 22:08:15316 WaitableEvent* got_first_reply_;
[email protected]3cdb7af812008-10-24 19:21:13317 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29318};
319
320class NoHangClient : public Worker {
321 public:
[email protected]aa96ae772009-01-20 22:08:15322 explicit NoHangClient(WaitableEvent* got_first_reply)
initial.commit09911bf2008-07-26 23:55:29323 : Worker(Channel::MODE_CLIENT, "no_hang_client"),
324 got_first_reply_(got_first_reply) { }
325
326 virtual void OnAnswerDelay(Message* reply_msg) {
327 // Use the DELAY_REPLY macro so that we can force the reply to be sent
328 // before this function returns (when the channel will be reset).
329 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
330 Send(reply_msg);
331 got_first_reply_->Wait();
332 CloseChannel();
333 Done();
334 }
335
[email protected]aa96ae772009-01-20 22:08:15336 WaitableEvent* got_first_reply_;
initial.commit09911bf2008-07-26 23:55:29337};
338
[email protected]3cdb7af812008-10-24 19:21:13339void NoHang(bool pump_during_send) {
[email protected]aa96ae772009-01-20 22:08:15340 WaitableEvent got_first_reply(false, false);
initial.commit09911bf2008-07-26 23:55:29341 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13342 workers.push_back(new NoHangServer(&got_first_reply, pump_during_send));
initial.commit09911bf2008-07-26 23:55:29343 workers.push_back(new NoHangClient(&got_first_reply));
344 RunTest(workers);
345}
346
[email protected]3cdb7af812008-10-24 19:21:13347} // namespace
348
349// Tests that caller doesn't hang if receiver dies
350TEST_F(IPCSyncChannelTest, NoHang) {
351 NoHang(false);
352 NoHang(true);
353}
initial.commit09911bf2008-07-26 23:55:29354
355//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34356
357namespace {
358
[email protected]3cdb7af812008-10-24 19:21:13359class UnblockServer : public Worker {
initial.commit09911bf2008-07-26 23:55:29360 public:
[email protected]3cdb7af812008-10-24 19:21:13361 UnblockServer(bool pump_during_send)
362 : Worker(Channel::MODE_SERVER, "unblock_server"),
363 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29364 void Run() {
[email protected]aa96ae772009-01-20 22:08:15365 SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
initial.commit09911bf2008-07-26 23:55:29366 Done();
367 }
368
369 void OnDouble(int in, int* out) {
370 *out = in * 2;
371 }
[email protected]3cdb7af812008-10-24 19:21:13372
373 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29374};
375
[email protected]3cdb7af812008-10-24 19:21:13376class UnblockClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29377 public:
[email protected]3cdb7af812008-10-24 19:21:13378 UnblockClient(bool pump_during_send)
379 : Worker(Channel::MODE_CLIENT, "unblock_client"),
380 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29381
382 void OnAnswer(int* answer) {
[email protected]4df10d612008-11-12 00:38:26383 SendDouble(pump_during_send_, true);
384 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29385 Done();
386 }
[email protected]3cdb7af812008-10-24 19:21:13387
388 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29389};
390
[email protected]3cdb7af812008-10-24 19:21:13391void Unblock(bool server_pump, bool client_pump) {
392 std::vector<Worker*> workers;
393 workers.push_back(new UnblockServer(server_pump));
394 workers.push_back(new UnblockClient(client_pump));
395 RunTest(workers);
396}
397
[email protected]dd3eac22008-08-26 07:28:34398} // namespace
399
initial.commit09911bf2008-07-26 23:55:29400// Tests that the caller unblocks to answer a sync message from the receiver.
[email protected]3cdb7af812008-10-24 19:21:13401TEST_F(IPCSyncChannelTest, Unblock) {
402 Unblock(false, false);
403 Unblock(false, true);
404 Unblock(true, false);
405 Unblock(true, true);
406}
407
408//-----------------------------------------------------------------------------
409
410namespace {
411
412class RecursiveServer : public Worker {
413 public:
414 explicit RecursiveServer(
415 bool expected_send_result, bool pump_first, bool pump_second)
416 : Worker(Channel::MODE_SERVER, "recursive_server"),
417 expected_send_result_(expected_send_result),
418 pump_first_(pump_first), pump_second_(pump_second) { }
419 void Run() {
[email protected]4df10d612008-11-12 00:38:26420 SendDouble(pump_first_, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13421 Done();
422 }
423
424 void OnDouble(int in, int* out) {
[email protected]4df10d612008-11-12 00:38:26425 *out = in * 2;
[email protected]aa96ae772009-01-20 22:08:15426 SendAnswerToLife(pump_second_, base::kNoTimeout, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13427 }
428
429 bool expected_send_result_, pump_first_, pump_second_;
430};
431
432class RecursiveClient : public Worker {
433 public:
434 explicit RecursiveClient(bool pump_during_send, bool close_channel)
435 : Worker(Channel::MODE_CLIENT, "recursive_client"),
436 pump_during_send_(pump_during_send), close_channel_(close_channel) { }
437
438 void OnDoubleDelay(int in, Message* reply_msg) {
[email protected]4df10d612008-11-12 00:38:26439 SendDouble(pump_during_send_, !close_channel_);
[email protected]c690a182008-10-24 23:10:32440 if (close_channel_) {
441 delete reply_msg;
442 } else {
[email protected]3cdb7af812008-10-24 19:21:13443 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
444 Send(reply_msg);
445 }
446 Done();
447 }
448
449 void OnAnswerDelay(Message* reply_msg) {
450 if (close_channel_) {
[email protected]c690a182008-10-24 23:10:32451 delete reply_msg;
[email protected]3cdb7af812008-10-24 19:21:13452 CloseChannel();
453 } else {
454 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
455 Send(reply_msg);
456 }
457 }
458
459 bool pump_during_send_, close_channel_;
460};
461
462void Recursive(
463 bool server_pump_first, bool server_pump_second, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29464 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13465 workers.push_back(
466 new RecursiveServer(true, server_pump_first, server_pump_second));
467 workers.push_back(new RecursiveClient(client_pump, false));
initial.commit09911bf2008-07-26 23:55:29468 RunTest(workers);
469}
470
[email protected]3cdb7af812008-10-24 19:21:13471} // namespace
472
473// Tests a server calling Send while another Send is pending.
474TEST_F(IPCSyncChannelTest, Recursive) {
475 Recursive(false, false, false);
476 Recursive(false, false, true);
477 Recursive(false, true, false);
478 Recursive(false, true, true);
479 Recursive(true, false, false);
480 Recursive(true, false, true);
481 Recursive(true, true, false);
482 Recursive(true, true, true);
483}
484
485//-----------------------------------------------------------------------------
486
487namespace {
488
489void RecursiveNoHang(
490 bool server_pump_first, bool server_pump_second, bool client_pump) {
491 std::vector<Worker*> workers;
492 workers.push_back(
493 new RecursiveServer(false, server_pump_first, server_pump_second));
494 workers.push_back(new RecursiveClient(client_pump, true));
495 RunTest(workers);
496}
497
498} // namespace
499
500// Tests that if a caller makes a sync call during an existing sync call and
501// the receiver dies, neither of the Send() calls hang.
502TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
503 RecursiveNoHang(false, false, false);
504 RecursiveNoHang(false, false, true);
505 RecursiveNoHang(false, true, false);
506 RecursiveNoHang(false, true, true);
507 RecursiveNoHang(true, false, false);
508 RecursiveNoHang(true, false, true);
509 RecursiveNoHang(true, true, false);
510 RecursiveNoHang(true, true, true);
511}
initial.commit09911bf2008-07-26 23:55:29512
513//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34514
515namespace {
516
initial.commit09911bf2008-07-26 23:55:29517class MultipleServer1 : public Worker {
518 public:
[email protected]3cdb7af812008-10-24 19:21:13519 MultipleServer1(bool pump_during_send)
520 : Worker(L"test_channel1", Channel::MODE_SERVER),
521 pump_during_send_(pump_during_send) { }
522
initial.commit09911bf2008-07-26 23:55:29523 void Run() {
[email protected]4df10d612008-11-12 00:38:26524 SendDouble(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29525 Done();
526 }
[email protected]3cdb7af812008-10-24 19:21:13527
528 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29529};
530
531class MultipleClient1 : public Worker {
532 public:
[email protected]aa96ae772009-01-20 22:08:15533 MultipleClient1(WaitableEvent* client1_msg_received,
534 WaitableEvent* client1_can_reply) :
initial.commit09911bf2008-07-26 23:55:29535 Worker(L"test_channel1", Channel::MODE_CLIENT),
536 client1_msg_received_(client1_msg_received),
537 client1_can_reply_(client1_can_reply) { }
538
539 void OnDouble(int in, int* out) {
[email protected]aa96ae772009-01-20 22:08:15540 client1_msg_received_->Signal();
initial.commit09911bf2008-07-26 23:55:29541 *out = in * 2;
542 client1_can_reply_->Wait();
543 Done();
544 }
545
546 private:
[email protected]aa96ae772009-01-20 22:08:15547 WaitableEvent *client1_msg_received_, *client1_can_reply_;
initial.commit09911bf2008-07-26 23:55:29548};
549
550class MultipleServer2 : public Worker {
551 public:
552 MultipleServer2() : Worker(L"test_channel2", Channel::MODE_SERVER) { }
553
554 void OnAnswer(int* result) {
555 *result = 42;
556 Done();
557 }
558};
559
560class MultipleClient2 : public Worker {
561 public:
[email protected]3cdb7af812008-10-24 19:21:13562 MultipleClient2(
[email protected]aa96ae772009-01-20 22:08:15563 WaitableEvent* client1_msg_received, WaitableEvent* client1_can_reply,
[email protected]3cdb7af812008-10-24 19:21:13564 bool pump_during_send)
565 : Worker(L"test_channel2", Channel::MODE_CLIENT),
initial.commit09911bf2008-07-26 23:55:29566 client1_msg_received_(client1_msg_received),
[email protected]3cdb7af812008-10-24 19:21:13567 client1_can_reply_(client1_can_reply),
568 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29569
570 void Run() {
initial.commit09911bf2008-07-26 23:55:29571 client1_msg_received_->Wait();
[email protected]aa96ae772009-01-20 22:08:15572 SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
573 client1_can_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29574 Done();
575 }
576
577 private:
[email protected]aa96ae772009-01-20 22:08:15578 WaitableEvent *client1_msg_received_, *client1_can_reply_;
[email protected]3cdb7af812008-10-24 19:21:13579 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29580};
581
[email protected]3cdb7af812008-10-24 19:21:13582void Multiple(bool server_pump, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29583 std::vector<Worker*> workers;
584
585 // A shared worker thread so that server1 and server2 run on one thread.
[email protected]ab820df2008-08-26 05:55:10586 base::Thread worker_thread("Multiple");
initial.commit09911bf2008-07-26 23:55:29587 worker_thread.Start();
588
589 // Server1 sends a sync msg to client1, which blocks the reply until
590 // server2 (which runs on the same worker thread as server1) responds
591 // to a sync msg from client2.
[email protected]aa96ae772009-01-20 22:08:15592 WaitableEvent client1_msg_received(false, false);
593 WaitableEvent client1_can_reply(false, false);
initial.commit09911bf2008-07-26 23:55:29594
595 Worker* worker;
596
597 worker = new MultipleServer2();
598 worker->OverrideThread(&worker_thread);
599 workers.push_back(worker);
600
601 worker = new MultipleClient2(
[email protected]3cdb7af812008-10-24 19:21:13602 &client1_msg_received, &client1_can_reply, client_pump);
initial.commit09911bf2008-07-26 23:55:29603 workers.push_back(worker);
604
[email protected]3cdb7af812008-10-24 19:21:13605 worker = new MultipleServer1(server_pump);
initial.commit09911bf2008-07-26 23:55:29606 worker->OverrideThread(&worker_thread);
607 workers.push_back(worker);
608
609 worker = new MultipleClient1(
610 &client1_msg_received, &client1_can_reply);
611 workers.push_back(worker);
612
613 RunTest(workers);
614}
615
[email protected]3cdb7af812008-10-24 19:21:13616} // namespace
617
618// Tests that multiple SyncObjects on the same listener thread can unblock each
619// other.
620TEST_F(IPCSyncChannelTest, Multiple) {
621 Multiple(false, false);
622 Multiple(false, true);
623 Multiple(true, false);
624 Multiple(true, true);
625}
initial.commit09911bf2008-07-26 23:55:29626
627//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34628
629namespace {
630
initial.commit09911bf2008-07-26 23:55:29631class QueuedReplyServer1 : public Worker {
632 public:
[email protected]3cdb7af812008-10-24 19:21:13633 QueuedReplyServer1(bool pump_during_send)
634 : Worker(L"test_channel1", Channel::MODE_SERVER),
635 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29636 void Run() {
[email protected]4df10d612008-11-12 00:38:26637 SendDouble(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29638 Done();
639 }
[email protected]3cdb7af812008-10-24 19:21:13640
641 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29642};
643
644class QueuedReplyClient1 : public Worker {
645 public:
[email protected]aa96ae772009-01-20 22:08:15646 QueuedReplyClient1(WaitableEvent* client1_msg_received,
647 WaitableEvent* server2_can_reply) :
initial.commit09911bf2008-07-26 23:55:29648 Worker(L"test_channel1", Channel::MODE_CLIENT),
649 client1_msg_received_(client1_msg_received),
650 server2_can_reply_(server2_can_reply) { }
651
652 void OnDouble(int in, int* out) {
[email protected]aa96ae772009-01-20 22:08:15653 client1_msg_received_->Signal();
initial.commit09911bf2008-07-26 23:55:29654 *out = in * 2;
655 server2_can_reply_->Wait();
656 Done();
657 }
658
659 private:
[email protected]aa96ae772009-01-20 22:08:15660 WaitableEvent *client1_msg_received_, *server2_can_reply_;
initial.commit09911bf2008-07-26 23:55:29661};
662
663class QueuedReplyServer2 : public Worker {
664 public:
[email protected]aa96ae772009-01-20 22:08:15665 explicit QueuedReplyServer2(WaitableEvent* server2_can_reply) :
initial.commit09911bf2008-07-26 23:55:29666 Worker(L"test_channel2", Channel::MODE_SERVER),
667 server2_can_reply_(server2_can_reply) { }
668
669 void OnAnswer(int* result) {
[email protected]aa96ae772009-01-20 22:08:15670 server2_can_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29671
672 // give client1's reply time to reach the server listener thread
[email protected]aa96ae772009-01-20 22:08:15673 PlatformThread::Sleep(200);
initial.commit09911bf2008-07-26 23:55:29674
675 *result = 42;
676 Done();
677 }
678
[email protected]aa96ae772009-01-20 22:08:15679 WaitableEvent *server2_can_reply_;
initial.commit09911bf2008-07-26 23:55:29680};
681
682class QueuedReplyClient2 : public Worker {
683 public:
[email protected]3cdb7af812008-10-24 19:21:13684 explicit QueuedReplyClient2(
[email protected]aa96ae772009-01-20 22:08:15685 WaitableEvent* client1_msg_received, bool pump_during_send)
[email protected]3cdb7af812008-10-24 19:21:13686 : Worker(L"test_channel2", Channel::MODE_CLIENT),
687 client1_msg_received_(client1_msg_received),
688 pump_during_send_(pump_during_send){ }
initial.commit09911bf2008-07-26 23:55:29689
690 void Run() {
initial.commit09911bf2008-07-26 23:55:29691 client1_msg_received_->Wait();
[email protected]aa96ae772009-01-20 22:08:15692 SendAnswerToLife(pump_during_send_, base::kNoTimeout, true);
initial.commit09911bf2008-07-26 23:55:29693 Done();
694 }
695
[email protected]aa96ae772009-01-20 22:08:15696 WaitableEvent *client1_msg_received_;
[email protected]3cdb7af812008-10-24 19:21:13697 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29698};
699
[email protected]3cdb7af812008-10-24 19:21:13700void QueuedReply(bool server_pump, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29701 std::vector<Worker*> workers;
702
703 // A shared worker thread so that server1 and server2 run on one thread.
[email protected]ab820df2008-08-26 05:55:10704 base::Thread worker_thread("QueuedReply");
initial.commit09911bf2008-07-26 23:55:29705 worker_thread.Start();
706
[email protected]aa96ae772009-01-20 22:08:15707 WaitableEvent client1_msg_received(false, false);
708 WaitableEvent server2_can_reply(false, false);
initial.commit09911bf2008-07-26 23:55:29709
710 Worker* worker;
711
712 worker = new QueuedReplyServer2(&server2_can_reply);
713 worker->OverrideThread(&worker_thread);
714 workers.push_back(worker);
715
[email protected]3cdb7af812008-10-24 19:21:13716 worker = new QueuedReplyClient2(&client1_msg_received, client_pump);
initial.commit09911bf2008-07-26 23:55:29717 workers.push_back(worker);
718
[email protected]3cdb7af812008-10-24 19:21:13719 worker = new QueuedReplyServer1(server_pump);
initial.commit09911bf2008-07-26 23:55:29720 worker->OverrideThread(&worker_thread);
721 workers.push_back(worker);
722
723 worker = new QueuedReplyClient1(
724 &client1_msg_received, &server2_can_reply);
725 workers.push_back(worker);
726
727 RunTest(workers);
728}
729
[email protected]3cdb7af812008-10-24 19:21:13730} // namespace
731
732// While a blocking send is in progress, the listener thread might answer other
733// synchronous messages. This tests that if during the response to another
734// message the reply to the original messages comes, it is queued up correctly
735// and the original Send is unblocked later.
736TEST_F(IPCSyncChannelTest, QueuedReply) {
737 QueuedReply(false, false);
738 QueuedReply(false, true);
739 QueuedReply(true, false);
740 QueuedReply(true, true);
741}
initial.commit09911bf2008-07-26 23:55:29742
743//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34744
745namespace {
746
initial.commit09911bf2008-07-26 23:55:29747class BadServer : public Worker {
748 public:
[email protected]3cdb7af812008-10-24 19:21:13749 BadServer(bool pump_during_send)
750 : Worker(Channel::MODE_SERVER, "simpler_server"),
751 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29752 void Run() {
753 int answer = 0;
754
[email protected]4df10d612008-11-12 00:38:26755 SyncMessage* msg = new SyncMessage(
[email protected]3cdb7af812008-10-24 19:21:13756 MSG_ROUTING_CONTROL, SyncChannelTestMsg_Double::ID,
757 Message::PRIORITY_NORMAL, NULL);
758 if (pump_during_send_)
759 msg->EnableMessagePumping();
760
initial.commit09911bf2008-07-26 23:55:29761 // Temporarily set the minimum logging very high so that the assertion
762 // in ipc_message_utils doesn't fire.
763 int log_level = logging::GetMinLogLevel();
764 logging::SetMinLogLevel(kint32max);
765 bool result = Send(msg);
766 logging::SetMinLogLevel(log_level);
767 DCHECK(!result);
768
769 // Need to send another message to get the client to call Done().
770 result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
771 DCHECK(result);
772 DCHECK(answer == 42);
773
774 Done();
775 }
[email protected]3cdb7af812008-10-24 19:21:13776
777 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29778};
779
[email protected]3cdb7af812008-10-24 19:21:13780void BadMessage(bool pump_during_send) {
781 std::vector<Worker*> workers;
782 workers.push_back(new BadServer(pump_during_send));
783 workers.push_back(new SimpleClient());
784 RunTest(workers);
785}
786
[email protected]dd3eac22008-08-26 07:28:34787} // namespace
788
initial.commit09911bf2008-07-26 23:55:29789// Tests that if a message is not serialized correctly, the Send() will fail.
[email protected]dd3eac22008-08-26 07:28:34790TEST_F(IPCSyncChannelTest, BadMessage) {
[email protected]3cdb7af812008-10-24 19:21:13791 BadMessage(false);
792 BadMessage(true);
initial.commit09911bf2008-07-26 23:55:29793}
794
initial.commit09911bf2008-07-26 23:55:29795//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34796
797namespace {
798
[email protected]3cdb7af812008-10-24 19:21:13799class ChattyClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29800 public:
[email protected]3cdb7af812008-10-24 19:21:13801 ChattyClient() :
802 Worker(Channel::MODE_CLIENT, "chatty_client") { }
initial.commit09911bf2008-07-26 23:55:29803
804 void OnAnswer(int* answer) {
805 // The PostMessage limit is 10k. Send 20% more than that.
806 const int kMessageLimit = 10000;
807 const int kMessagesToSend = kMessageLimit * 120 / 100;
808 for (int i = 0; i < kMessagesToSend; ++i) {
[email protected]4df10d612008-11-12 00:38:26809 if (!SendDouble(false, true))
initial.commit09911bf2008-07-26 23:55:29810 break;
811 }
[email protected]4df10d612008-11-12 00:38:26812 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29813 Done();
814 }
815};
816
[email protected]3cdb7af812008-10-24 19:21:13817void ChattyServer(bool pump_during_send) {
818 std::vector<Worker*> workers;
819 workers.push_back(new UnblockServer(pump_during_send));
820 workers.push_back(new ChattyClient());
821 RunTest(workers);
822}
823
[email protected]dd3eac22008-08-26 07:28:34824} // namespace
825
[email protected]4df10d612008-11-12 00:38:26826// Tests http://b/1093251 - that sending lots of sync messages while
initial.commit09911bf2008-07-26 23:55:29827// the receiver is waiting for a sync reply does not overflow the PostMessage
828// queue.
[email protected]dd3eac22008-08-26 07:28:34829TEST_F(IPCSyncChannelTest, ChattyServer) {
[email protected]3cdb7af812008-10-24 19:21:13830 ChattyServer(false);
831 ChattyServer(true);
initial.commit09911bf2008-07-26 23:55:29832}
[email protected]d65cab7a2008-08-12 01:25:41833
[email protected]d65cab7a2008-08-12 01:25:41834//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34835
836namespace {
837
[email protected]d65cab7a2008-08-12 01:25:41838class TimeoutServer : public Worker {
839 public:
840 TimeoutServer(int timeout_ms,
[email protected]3cdb7af812008-10-24 19:21:13841 std::vector<bool> timeout_seq,
842 bool pump_during_send)
[email protected]d65cab7a2008-08-12 01:25:41843 : Worker(Channel::MODE_SERVER, "timeout_server"),
844 timeout_ms_(timeout_ms),
[email protected]3cdb7af812008-10-24 19:21:13845 timeout_seq_(timeout_seq),
846 pump_during_send_(pump_during_send) {
[email protected]d65cab7a2008-08-12 01:25:41847 }
848
849 void Run() {
850 for (std::vector<bool>::const_iterator iter = timeout_seq_.begin();
851 iter != timeout_seq_.end(); ++iter) {
[email protected]4df10d612008-11-12 00:38:26852 SendAnswerToLife(pump_during_send_, timeout_ms_, !*iter);
[email protected]d65cab7a2008-08-12 01:25:41853 }
854 Done();
855 }
856
857 private:
858 int timeout_ms_;
859 std::vector<bool> timeout_seq_;
[email protected]3cdb7af812008-10-24 19:21:13860 bool pump_during_send_;
[email protected]d65cab7a2008-08-12 01:25:41861};
862
863class UnresponsiveClient : public Worker {
864 public:
865 UnresponsiveClient(std::vector<bool> timeout_seq)
866 : Worker(Channel::MODE_CLIENT, "unresponsive_client"),
867 timeout_seq_(timeout_seq) {
868 }
869
870 void OnAnswerDelay(Message* reply_msg) {
871 DCHECK(!timeout_seq_.empty());
872 if (!timeout_seq_[0]) {
873 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
874 Send(reply_msg);
875 } else {
876 // Don't reply.
[email protected]463667372008-08-20 20:20:52877 delete reply_msg;
[email protected]d65cab7a2008-08-12 01:25:41878 }
879 timeout_seq_.erase(timeout_seq_.begin());
880 if (timeout_seq_.empty())
881 Done();
882 }
883
884 private:
885 // Whether we should time-out or respond to the various messages we receive.
886 std::vector<bool> timeout_seq_;
887};
888
[email protected]3cdb7af812008-10-24 19:21:13889void SendWithTimeoutOK(bool pump_during_send) {
890 std::vector<Worker*> workers;
891 std::vector<bool> timeout_seq;
892 timeout_seq.push_back(false);
893 timeout_seq.push_back(false);
894 timeout_seq.push_back(false);
895 workers.push_back(new TimeoutServer(5000, timeout_seq, pump_during_send));
896 workers.push_back(new SimpleClient());
897 RunTest(workers);
898}
899
900void SendWithTimeoutTimeout(bool pump_during_send) {
901 std::vector<Worker*> workers;
902 std::vector<bool> timeout_seq;
903 timeout_seq.push_back(true);
904 timeout_seq.push_back(false);
905 timeout_seq.push_back(false);
906 workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
907 workers.push_back(new UnresponsiveClient(timeout_seq));
908 RunTest(workers);
909}
910
911void SendWithTimeoutMixedOKAndTimeout(bool pump_during_send) {
912 std::vector<Worker*> workers;
913 std::vector<bool> timeout_seq;
914 timeout_seq.push_back(true);
915 timeout_seq.push_back(false);
916 timeout_seq.push_back(false);
917 timeout_seq.push_back(true);
918 timeout_seq.push_back(false);
919 workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
920 workers.push_back(new UnresponsiveClient(timeout_seq));
921 RunTest(workers);
922}
923
[email protected]dd3eac22008-08-26 07:28:34924} // namespace
925
[email protected]d65cab7a2008-08-12 01:25:41926// Tests that SendWithTimeout does not time-out if the response comes back fast
927// enough.
[email protected]dd3eac22008-08-26 07:28:34928TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) {
[email protected]3cdb7af812008-10-24 19:21:13929 SendWithTimeoutOK(false);
930 SendWithTimeoutOK(true);
[email protected]d65cab7a2008-08-12 01:25:41931}
932
933// Tests that SendWithTimeout does time-out.
[email protected]dd3eac22008-08-26 07:28:34934TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) {
[email protected]3cdb7af812008-10-24 19:21:13935 SendWithTimeoutTimeout(false);
936 SendWithTimeoutTimeout(true);
[email protected]d65cab7a2008-08-12 01:25:41937}
938
939// Sends some message that time-out and some that succeed.
[email protected]dd3eac22008-08-26 07:28:34940TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) {
[email protected]3cdb7af812008-10-24 19:21:13941 SendWithTimeoutMixedOKAndTimeout(false);
942 SendWithTimeoutMixedOKAndTimeout(true);
943}
[email protected]4df10d612008-11-12 00:38:26944
945//------------------------------------------------------------------------------
946
947namespace {
948
949class NestedTask : public Task {
950 public:
951 NestedTask(Worker* server) : server_(server) { }
952 void Run() {
953 // Sleep a bit so that we wake up after the reply has been received.
[email protected]aa96ae772009-01-20 22:08:15954 PlatformThread::Sleep(250);
955 server_->SendAnswerToLife(true, base::kNoTimeout, true);
[email protected]4df10d612008-11-12 00:38:26956 }
957
958 Worker* server_;
959};
960
961static bool timeout_occured = false;
962
963class TimeoutTask : public Task {
964 public:
965 void Run() {
966 timeout_occured = true;
967 }
968};
969
970class DoneEventRaceServer : public Worker {
971 public:
972 DoneEventRaceServer()
973 : Worker(Channel::MODE_SERVER, "done_event_race_server") { }
974
975 void Run() {
976 MessageLoop::current()->PostTask(FROM_HERE, new NestedTask(this));
977 MessageLoop::current()->PostDelayedTask(FROM_HERE, new TimeoutTask(), 9000);
978 // Even though we have a timeout on the Send, it will succeed since for this
979 // bug, the reply message comes back and is deserialized, however the done
980 // event wasn't set. So we indirectly use the timeout task to notice if a
981 // timeout occurred.
982 SendAnswerToLife(true, 10000, true);
983 DCHECK(!timeout_occured);
984 Done();
985 }
986};
987
988} // namespace
989
990// Tests http://b/1474092 - that if after the done_event is set but before
991// OnObjectSignaled is called another message is sent out, then after its
992// reply comes back OnObjectSignaled will be called for the first message.
993TEST_F(IPCSyncChannelTest, DoneEventRace) {
994 std::vector<Worker*> workers;
995 workers.push_back(new DoneEventRaceServer());
996 workers.push_back(new SimpleClient());
997 RunTest(workers);
998}