blob: c6261b47c9e7d09fb0952dc569ebbb5fd7f77a2b [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
7#include <windows.h>
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/logging.h"
13#include "base/message_loop.h"
14#include "base/string_util.h"
15#include "base/thread.h"
16#include "chrome/common/child_process.h"
17#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
22#define IPC_MESSAGE_MACROS_ENUMS
23#include "chrome/common/ipc_sync_channel_unittest.h"
24
25// define the classes
26#define IPC_MESSAGE_MACROS_CLASSES
27#include "chrome/common/ipc_sync_channel_unittest.h"
28
29using namespace IPC;
30
[email protected]dd3eac22008-08-26 07:28:3431namespace {
32
33class IPCSyncChannelTest : public testing::Test {
34 private:
35 MessageLoop message_loop_;
36};
37
initial.commit09911bf2008-07-26 23:55:2938// SyncChannel should only be used in child processes as we don't want to hang
39// the browser. So in the unit test we need to have a ChildProcess object.
40class TestProcess : public ChildProcess {
41 public:
42 explicit TestProcess(const std::wstring& channel_name) {}
43 static void GlobalInit() {
44 ChildProcessFactory<TestProcess> factory;
45 ChildProcess::GlobalInit(L"blah", &factory);
46 }
47};
48
49// Wrapper around an event handle.
50class Event {
51 public:
52 Event() : handle_(CreateEvent(NULL, FALSE, FALSE, NULL)) { }
53 ~Event() { CloseHandle(handle_); }
54 void Set() { SetEvent(handle_); }
55 void Wait() { WaitForSingleObject(handle_, INFINITE); }
56 HANDLE handle() { return handle_; }
57
58 private:
59 HANDLE handle_;
60
61 DISALLOW_EVIL_CONSTRUCTORS(Event);
62};
63
64// Base class for a "process" with listener and IPC threads.
65class Worker : public Channel::Listener, public Message::Sender {
66 public:
67 // Will create a channel without a name.
68 Worker(Channel::Mode mode, const std::string& thread_name)
69 : channel_name_(),
70 mode_(mode),
71 ipc_thread_((thread_name + "_ipc").c_str()),
72 listener_thread_((thread_name + "_listener").c_str()),
73 overrided_thread_(NULL) { }
74
75 // Will create a named channel and use this name for the threads' name.
76 Worker(const std::wstring& channel_name, Channel::Mode mode)
77 : channel_name_(channel_name),
78 mode_(mode),
79 ipc_thread_((WideToUTF8(channel_name) + "_ipc").c_str()),
80 listener_thread_((WideToUTF8(channel_name) + "_listener").c_str()),
81 overrided_thread_(NULL) { }
82
83 // The IPC thread needs to outlive SyncChannel, so force the correct order of
84 // destruction.
85 virtual ~Worker() {
[email protected]3cdb7af812008-10-24 19:21:1386 Event listener_done, ipc_done;
87 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
88 this, &Worker::OnListenerThreadShutdown, listener_done.handle(),
89 ipc_done.handle()));
90 HANDLE handles[] = { listener_done.handle(), ipc_done.handle() };
91 WaitForMultipleObjects(2, handles, TRUE, INFINITE);
initial.commit09911bf2008-07-26 23:55:2992 ipc_thread_.Stop();
93 listener_thread_.Stop();
initial.commit09911bf2008-07-26 23:55:2994 }
95 void AddRef() { }
96 void Release() { }
97 bool Send(Message* msg) { return channel_->Send(msg); }
[email protected]d65cab7a2008-08-12 01:25:4198 bool SendWithTimeout(Message* msg, int timeout_ms) {
99 return channel_->SendWithTimeout(msg, timeout_ms);
100 }
initial.commit09911bf2008-07-26 23:55:29101 void WaitForChannelCreation() { channel_created_.Wait(); }
[email protected]3cdb7af812008-10-24 19:21:13102 void CloseChannel() {
103 DCHECK(MessageLoop::current() == ListenerThread()->message_loop());
104 channel_->Close();
105 }
initial.commit09911bf2008-07-26 23:55:29106 void Start() {
[email protected]17b89142008-11-07 21:52:15107 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT);
[email protected]3cdb7af812008-10-24 19:21:13108 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
initial.commit09911bf2008-07-26 23:55:29109 this, &Worker::OnStart));
110 }
[email protected]ab820df2008-08-26 05:55:10111 void OverrideThread(base::Thread* overrided_thread) {
initial.commit09911bf2008-07-26 23:55:29112 DCHECK(overrided_thread_ == NULL);
113 overrided_thread_ = overrided_thread;
114 }
[email protected]4df10d612008-11-12 00:38:26115 bool SendAnswerToLife(bool pump, int timeout, bool succeed) {
116 int answer = 0;
117 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
118 if (pump)
119 msg->EnableMessagePumping();
120 bool result = SendWithTimeout(msg, timeout);
121 DCHECK(result == succeed);
122 DCHECK(answer == (succeed ? 42 : 0));
123 return result;
124 }
125 bool SendDouble(bool pump, bool succeed) {
126 int answer = 0;
127 SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
128 if (pump)
129 msg->EnableMessagePumping();
130 bool result = Send(msg);
131 DCHECK(result == succeed);
132 DCHECK(answer == (succeed ? 10 : 0));
133 return result;
134 }
initial.commit09911bf2008-07-26 23:55:29135 Channel::Mode mode() { return mode_; }
136 HANDLE done_event() { return done_.handle(); }
137
138 protected:
139 // Derived classes need to call this when they've completed their part of
140 // the test.
141 void Done() { done_.Set(); }
initial.commit09911bf2008-07-26 23:55:29142 // Functions for dervied classes to implement if they wish.
143 virtual void Run() { }
initial.commit09911bf2008-07-26 23:55:29144 virtual void OnAnswer(int* answer) { NOTREACHED(); }
145 virtual void OnAnswerDelay(Message* reply_msg) {
146 // The message handler map below can only take one entry for
147 // SyncChannelTestMsg_AnswerToLife, so since some classes want
148 // the normal version while other want the delayed reply, we
149 // call the normal version if the derived class didn't override
150 // this function.
151 int answer;
152 OnAnswer(&answer);
153 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
154 Send(reply_msg);
155 }
[email protected]3cdb7af812008-10-24 19:21:13156 virtual void OnDouble(int in, int* out) { NOTREACHED(); }
157 virtual void OnDoubleDelay(int in, Message* reply_msg) {
158 int result;
159 OnDouble(in, &result);
160 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
161 Send(reply_msg);
162 }
initial.commit09911bf2008-07-26 23:55:29163
164 private:
[email protected]3cdb7af812008-10-24 19:21:13165 base::Thread* ListenerThread() {
166 return overrided_thread_ ? overrided_thread_ : &listener_thread_;
167 }
initial.commit09911bf2008-07-26 23:55:29168 // Called on the listener thread to create the sync channel.
169 void OnStart() {
initial.commit09911bf2008-07-26 23:55:29170 // Link ipc_thread_, listener_thread_ and channel_ altogether.
[email protected]17b89142008-11-07 21:52:15171 StartThread(&ipc_thread_, MessageLoop::TYPE_IO);
initial.commit09911bf2008-07-26 23:55:29172 channel_.reset(new SyncChannel(
[email protected]d65cab7a2008-08-12 01:25:41173 channel_name_, mode_, this, NULL, ipc_thread_.message_loop(), true,
174 TestProcess::GetShutDownEvent()));
initial.commit09911bf2008-07-26 23:55:29175 channel_created_.Set();
176 Run();
177 }
178
[email protected]3cdb7af812008-10-24 19:21:13179 void OnListenerThreadShutdown(HANDLE listener_event, HANDLE ipc_event) {
180 // SyncChannel needs to be destructed on the thread that it was created on.
181 channel_.reset();
182 SetEvent(listener_event);
183
184 ipc_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
185 this, &Worker::OnIPCThreadShutdown, ipc_event));
186 }
187
188 void OnIPCThreadShutdown(HANDLE ipc_event) {
189 SetEvent(ipc_event);
190 }
191
initial.commit09911bf2008-07-26 23:55:29192 void OnMessageReceived(const Message& message) {
193 IPC_BEGIN_MESSAGE_MAP(Worker, message)
[email protected]3cdb7af812008-10-24 19:21:13194 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
initial.commit09911bf2008-07-26 23:55:29195 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
196 OnAnswerDelay)
197 IPC_END_MESSAGE_MAP()
198 }
199
[email protected]17b89142008-11-07 21:52:15200 void StartThread(base::Thread* thread, MessageLoop::Type type) {
[email protected]ab820df2008-08-26 05:55:10201 base::Thread::Options options;
[email protected]17b89142008-11-07 21:52:15202 options.message_loop_type = type;
[email protected]ab820df2008-08-26 05:55:10203 thread->StartWithOptions(options);
204 }
205
initial.commit09911bf2008-07-26 23:55:29206 Event done_;
207 Event channel_created_;
208 std::wstring channel_name_;
209 Channel::Mode mode_;
210 scoped_ptr<SyncChannel> channel_;
[email protected]ab820df2008-08-26 05:55:10211 base::Thread ipc_thread_;
212 base::Thread listener_thread_;
213 base::Thread* overrided_thread_;
initial.commit09911bf2008-07-26 23:55:29214
215 DISALLOW_EVIL_CONSTRUCTORS(Worker);
216};
217
218
219// Starts the test with the given workers. This function deletes the workers
220// when it's done.
221void RunTest(std::vector<Worker*> workers) {
222 TestProcess::GlobalInit();
223
224 // First we create the workers that are channel servers, or else the other
225 // workers' channel initialization might fail because the pipe isn't created..
226 for (size_t i = 0; i < workers.size(); ++i) {
227 if (workers[i]->mode() == Channel::MODE_SERVER) {
228 workers[i]->Start();
229 workers[i]->WaitForChannelCreation();
230 }
231 }
232
233 // now create the clients
234 for (size_t i = 0; i < workers.size(); ++i) {
235 if (workers[i]->mode() == Channel::MODE_CLIENT)
236 workers[i]->Start();
237 }
238
239 // wait for all the workers to finish
240 std::vector<HANDLE> done_handles;
241 for (size_t i = 0; i < workers.size(); ++i)
242 done_handles.push_back(workers[i]->done_event());
243
244 int count = static_cast<int>(done_handles.size());
245 WaitForMultipleObjects(count, &done_handles.front(), TRUE, INFINITE);
246 STLDeleteContainerPointers(workers.begin(), workers.end());
[email protected]ab820df2008-08-26 05:55:10247
248 TestProcess::GlobalCleanup();
initial.commit09911bf2008-07-26 23:55:29249}
250
[email protected]dd3eac22008-08-26 07:28:34251} // namespace
252
initial.commit09911bf2008-07-26 23:55:29253//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34254
255namespace {
256
initial.commit09911bf2008-07-26 23:55:29257class SimpleServer : public Worker {
258 public:
[email protected]3cdb7af812008-10-24 19:21:13259 SimpleServer(bool pump_during_send)
260 : Worker(Channel::MODE_SERVER, "simpler_server"),
261 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29262 void Run() {
[email protected]4df10d612008-11-12 00:38:26263 SendAnswerToLife(pump_during_send_, INFINITE, true);
initial.commit09911bf2008-07-26 23:55:29264 Done();
265 }
[email protected]3cdb7af812008-10-24 19:21:13266
267 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29268};
269
270class SimpleClient : public Worker {
271 public:
272 SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { }
273
274 void OnAnswer(int* answer) {
275 *answer = 42;
276 Done();
277 }
278};
279
[email protected]3cdb7af812008-10-24 19:21:13280void Simple(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29281 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13282 workers.push_back(new SimpleServer(pump_during_send));
initial.commit09911bf2008-07-26 23:55:29283 workers.push_back(new SimpleClient());
284 RunTest(workers);
285}
286
[email protected]3cdb7af812008-10-24 19:21:13287} // namespace
288
289// Tests basic synchronous call
290TEST_F(IPCSyncChannelTest, Simple) {
291 Simple(false);
292 Simple(true);
293}
initial.commit09911bf2008-07-26 23:55:29294
295//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34296
297namespace {
298
initial.commit09911bf2008-07-26 23:55:29299class DelayClient : public Worker {
300 public:
301 DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { }
302
303 void OnAnswerDelay(Message* reply_msg) {
304 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
305 Send(reply_msg);
306 Done();
307 }
308};
309
[email protected]3cdb7af812008-10-24 19:21:13310void DelayReply(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29311 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13312 workers.push_back(new SimpleServer(pump_during_send));
initial.commit09911bf2008-07-26 23:55:29313 workers.push_back(new DelayClient());
314 RunTest(workers);
315}
316
[email protected]3cdb7af812008-10-24 19:21:13317} // namespace
318
319// Tests that asynchronous replies work
320TEST_F(IPCSyncChannelTest, DelayReply) {
321 DelayReply(false);
322 DelayReply(true);
323}
initial.commit09911bf2008-07-26 23:55:29324
325//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34326
327namespace {
328
initial.commit09911bf2008-07-26 23:55:29329class NoHangServer : public Worker {
330 public:
[email protected]3cdb7af812008-10-24 19:21:13331 explicit NoHangServer(Event* got_first_reply, bool pump_during_send)
332 : Worker(Channel::MODE_SERVER, "no_hang_server"),
333 got_first_reply_(got_first_reply),
334 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29335 void Run() {
[email protected]4df10d612008-11-12 00:38:26336 SendAnswerToLife(pump_during_send_, INFINITE, true);
initial.commit09911bf2008-07-26 23:55:29337 got_first_reply_->Set();
338
[email protected]4df10d612008-11-12 00:38:26339 SendAnswerToLife(pump_during_send_, INFINITE, false);
initial.commit09911bf2008-07-26 23:55:29340 Done();
341 }
342
343 Event* got_first_reply_;
[email protected]3cdb7af812008-10-24 19:21:13344 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29345};
346
347class NoHangClient : public Worker {
348 public:
349 explicit NoHangClient(Event* got_first_reply)
350 : Worker(Channel::MODE_CLIENT, "no_hang_client"),
351 got_first_reply_(got_first_reply) { }
352
353 virtual void OnAnswerDelay(Message* reply_msg) {
354 // Use the DELAY_REPLY macro so that we can force the reply to be sent
355 // before this function returns (when the channel will be reset).
356 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
357 Send(reply_msg);
358 got_first_reply_->Wait();
359 CloseChannel();
360 Done();
361 }
362
363 Event* got_first_reply_;
364};
365
[email protected]3cdb7af812008-10-24 19:21:13366void NoHang(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29367 Event got_first_reply;
initial.commit09911bf2008-07-26 23:55:29368 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13369 workers.push_back(new NoHangServer(&got_first_reply, pump_during_send));
initial.commit09911bf2008-07-26 23:55:29370 workers.push_back(new NoHangClient(&got_first_reply));
371 RunTest(workers);
372}
373
[email protected]3cdb7af812008-10-24 19:21:13374} // namespace
375
376// Tests that caller doesn't hang if receiver dies
377TEST_F(IPCSyncChannelTest, NoHang) {
378 NoHang(false);
379 NoHang(true);
380}
initial.commit09911bf2008-07-26 23:55:29381
382//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34383
384namespace {
385
[email protected]3cdb7af812008-10-24 19:21:13386class UnblockServer : public Worker {
initial.commit09911bf2008-07-26 23:55:29387 public:
[email protected]3cdb7af812008-10-24 19:21:13388 UnblockServer(bool pump_during_send)
389 : Worker(Channel::MODE_SERVER, "unblock_server"),
390 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29391 void Run() {
[email protected]4df10d612008-11-12 00:38:26392 SendAnswerToLife(pump_during_send_, INFINITE, true);
initial.commit09911bf2008-07-26 23:55:29393 Done();
394 }
395
396 void OnDouble(int in, int* out) {
397 *out = in * 2;
398 }
[email protected]3cdb7af812008-10-24 19:21:13399
400 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29401};
402
[email protected]3cdb7af812008-10-24 19:21:13403class UnblockClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29404 public:
[email protected]3cdb7af812008-10-24 19:21:13405 UnblockClient(bool pump_during_send)
406 : Worker(Channel::MODE_CLIENT, "unblock_client"),
407 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29408
409 void OnAnswer(int* answer) {
[email protected]4df10d612008-11-12 00:38:26410 SendDouble(pump_during_send_, true);
411 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29412 Done();
413 }
[email protected]3cdb7af812008-10-24 19:21:13414
415 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29416};
417
[email protected]3cdb7af812008-10-24 19:21:13418void Unblock(bool server_pump, bool client_pump) {
419 std::vector<Worker*> workers;
420 workers.push_back(new UnblockServer(server_pump));
421 workers.push_back(new UnblockClient(client_pump));
422 RunTest(workers);
423}
424
[email protected]dd3eac22008-08-26 07:28:34425} // namespace
426
initial.commit09911bf2008-07-26 23:55:29427// Tests that the caller unblocks to answer a sync message from the receiver.
[email protected]3cdb7af812008-10-24 19:21:13428TEST_F(IPCSyncChannelTest, Unblock) {
429 Unblock(false, false);
430 Unblock(false, true);
431 Unblock(true, false);
432 Unblock(true, true);
433}
434
435//-----------------------------------------------------------------------------
436
437namespace {
438
439class RecursiveServer : public Worker {
440 public:
441 explicit RecursiveServer(
442 bool expected_send_result, bool pump_first, bool pump_second)
443 : Worker(Channel::MODE_SERVER, "recursive_server"),
444 expected_send_result_(expected_send_result),
445 pump_first_(pump_first), pump_second_(pump_second) { }
446 void Run() {
[email protected]4df10d612008-11-12 00:38:26447 SendDouble(pump_first_, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13448 Done();
449 }
450
451 void OnDouble(int in, int* out) {
[email protected]4df10d612008-11-12 00:38:26452 *out = in * 2;
453 SendAnswerToLife(pump_second_, INFINITE, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13454 }
455
456 bool expected_send_result_, pump_first_, pump_second_;
457};
458
459class RecursiveClient : public Worker {
460 public:
461 explicit RecursiveClient(bool pump_during_send, bool close_channel)
462 : Worker(Channel::MODE_CLIENT, "recursive_client"),
463 pump_during_send_(pump_during_send), close_channel_(close_channel) { }
464
465 void OnDoubleDelay(int in, Message* reply_msg) {
[email protected]4df10d612008-11-12 00:38:26466 SendDouble(pump_during_send_, !close_channel_);
[email protected]c690a182008-10-24 23:10:32467 if (close_channel_) {
468 delete reply_msg;
469 } else {
[email protected]3cdb7af812008-10-24 19:21:13470 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
471 Send(reply_msg);
472 }
473 Done();
474 }
475
476 void OnAnswerDelay(Message* reply_msg) {
477 if (close_channel_) {
[email protected]c690a182008-10-24 23:10:32478 delete reply_msg;
[email protected]3cdb7af812008-10-24 19:21:13479 CloseChannel();
480 } else {
481 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
482 Send(reply_msg);
483 }
484 }
485
486 bool pump_during_send_, close_channel_;
487};
488
489void Recursive(
490 bool server_pump_first, bool server_pump_second, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29491 std::vector<Worker*> workers;
[email protected]3cdb7af812008-10-24 19:21:13492 workers.push_back(
493 new RecursiveServer(true, server_pump_first, server_pump_second));
494 workers.push_back(new RecursiveClient(client_pump, false));
initial.commit09911bf2008-07-26 23:55:29495 RunTest(workers);
496}
497
[email protected]3cdb7af812008-10-24 19:21:13498} // namespace
499
500// Tests a server calling Send while another Send is pending.
501TEST_F(IPCSyncChannelTest, Recursive) {
502 Recursive(false, false, false);
503 Recursive(false, false, true);
504 Recursive(false, true, false);
505 Recursive(false, true, true);
506 Recursive(true, false, false);
507 Recursive(true, false, true);
508 Recursive(true, true, false);
509 Recursive(true, true, true);
510}
511
512//-----------------------------------------------------------------------------
513
514namespace {
515
516void RecursiveNoHang(
517 bool server_pump_first, bool server_pump_second, bool client_pump) {
518 std::vector<Worker*> workers;
519 workers.push_back(
520 new RecursiveServer(false, server_pump_first, server_pump_second));
521 workers.push_back(new RecursiveClient(client_pump, true));
522 RunTest(workers);
523}
524
525} // namespace
526
527// Tests that if a caller makes a sync call during an existing sync call and
528// the receiver dies, neither of the Send() calls hang.
529TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
530 RecursiveNoHang(false, false, false);
531 RecursiveNoHang(false, false, true);
532 RecursiveNoHang(false, true, false);
533 RecursiveNoHang(false, true, true);
534 RecursiveNoHang(true, false, false);
535 RecursiveNoHang(true, false, true);
536 RecursiveNoHang(true, true, false);
537 RecursiveNoHang(true, true, true);
538}
initial.commit09911bf2008-07-26 23:55:29539
540//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34541
542namespace {
543
initial.commit09911bf2008-07-26 23:55:29544class MultipleServer1 : public Worker {
545 public:
[email protected]3cdb7af812008-10-24 19:21:13546 MultipleServer1(bool pump_during_send)
547 : Worker(L"test_channel1", Channel::MODE_SERVER),
548 pump_during_send_(pump_during_send) { }
549
initial.commit09911bf2008-07-26 23:55:29550 void Run() {
[email protected]4df10d612008-11-12 00:38:26551 SendDouble(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29552 Done();
553 }
[email protected]3cdb7af812008-10-24 19:21:13554
555 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29556};
557
558class MultipleClient1 : public Worker {
559 public:
560 MultipleClient1(Event* client1_msg_received, Event* client1_can_reply) :
561 Worker(L"test_channel1", Channel::MODE_CLIENT),
562 client1_msg_received_(client1_msg_received),
563 client1_can_reply_(client1_can_reply) { }
564
565 void OnDouble(int in, int* out) {
566 client1_msg_received_->Set();
567 *out = in * 2;
568 client1_can_reply_->Wait();
569 Done();
570 }
571
572 private:
573 Event *client1_msg_received_, *client1_can_reply_;
574};
575
576class MultipleServer2 : public Worker {
577 public:
578 MultipleServer2() : Worker(L"test_channel2", Channel::MODE_SERVER) { }
579
580 void OnAnswer(int* result) {
581 *result = 42;
582 Done();
583 }
584};
585
586class MultipleClient2 : public Worker {
587 public:
[email protected]3cdb7af812008-10-24 19:21:13588 MultipleClient2(
589 Event* client1_msg_received, Event* client1_can_reply,
590 bool pump_during_send)
591 : Worker(L"test_channel2", Channel::MODE_CLIENT),
initial.commit09911bf2008-07-26 23:55:29592 client1_msg_received_(client1_msg_received),
[email protected]3cdb7af812008-10-24 19:21:13593 client1_can_reply_(client1_can_reply),
594 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29595
596 void Run() {
initial.commit09911bf2008-07-26 23:55:29597 client1_msg_received_->Wait();
[email protected]4df10d612008-11-12 00:38:26598 SendAnswerToLife(pump_during_send_, INFINITE, true);
initial.commit09911bf2008-07-26 23:55:29599 client1_can_reply_->Set();
600 Done();
601 }
602
603 private:
604 Event *client1_msg_received_, *client1_can_reply_;
[email protected]3cdb7af812008-10-24 19:21:13605 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29606};
607
[email protected]3cdb7af812008-10-24 19:21:13608void Multiple(bool server_pump, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29609 std::vector<Worker*> workers;
610
611 // A shared worker thread so that server1 and server2 run on one thread.
[email protected]ab820df2008-08-26 05:55:10612 base::Thread worker_thread("Multiple");
initial.commit09911bf2008-07-26 23:55:29613 worker_thread.Start();
614
615 // Server1 sends a sync msg to client1, which blocks the reply until
616 // server2 (which runs on the same worker thread as server1) responds
617 // to a sync msg from client2.
618 Event client1_msg_received, client1_can_reply;
619
620 Worker* worker;
621
622 worker = new MultipleServer2();
623 worker->OverrideThread(&worker_thread);
624 workers.push_back(worker);
625
626 worker = new MultipleClient2(
[email protected]3cdb7af812008-10-24 19:21:13627 &client1_msg_received, &client1_can_reply, client_pump);
initial.commit09911bf2008-07-26 23:55:29628 workers.push_back(worker);
629
[email protected]3cdb7af812008-10-24 19:21:13630 worker = new MultipleServer1(server_pump);
initial.commit09911bf2008-07-26 23:55:29631 worker->OverrideThread(&worker_thread);
632 workers.push_back(worker);
633
634 worker = new MultipleClient1(
635 &client1_msg_received, &client1_can_reply);
636 workers.push_back(worker);
637
638 RunTest(workers);
639}
640
[email protected]3cdb7af812008-10-24 19:21:13641} // namespace
642
643// Tests that multiple SyncObjects on the same listener thread can unblock each
644// other.
645TEST_F(IPCSyncChannelTest, Multiple) {
646 Multiple(false, false);
647 Multiple(false, true);
648 Multiple(true, false);
649 Multiple(true, true);
650}
initial.commit09911bf2008-07-26 23:55:29651
652//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34653
654namespace {
655
initial.commit09911bf2008-07-26 23:55:29656class QueuedReplyServer1 : public Worker {
657 public:
[email protected]3cdb7af812008-10-24 19:21:13658 QueuedReplyServer1(bool pump_during_send)
659 : Worker(L"test_channel1", Channel::MODE_SERVER),
660 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29661 void Run() {
[email protected]4df10d612008-11-12 00:38:26662 SendDouble(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29663 Done();
664 }
[email protected]3cdb7af812008-10-24 19:21:13665
666 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29667};
668
669class QueuedReplyClient1 : public Worker {
670 public:
671 QueuedReplyClient1(Event* client1_msg_received, Event* server2_can_reply) :
672 Worker(L"test_channel1", Channel::MODE_CLIENT),
673 client1_msg_received_(client1_msg_received),
674 server2_can_reply_(server2_can_reply) { }
675
676 void OnDouble(int in, int* out) {
677 client1_msg_received_->Set();
678 *out = in * 2;
679 server2_can_reply_->Wait();
680 Done();
681 }
682
683 private:
684 Event *client1_msg_received_, *server2_can_reply_;
685};
686
687class QueuedReplyServer2 : public Worker {
688 public:
689 explicit QueuedReplyServer2(Event* server2_can_reply) :
690 Worker(L"test_channel2", Channel::MODE_SERVER),
691 server2_can_reply_(server2_can_reply) { }
692
693 void OnAnswer(int* result) {
694 server2_can_reply_->Set();
695
696 // give client1's reply time to reach the server listener thread
697 Sleep(200);
698
699 *result = 42;
700 Done();
701 }
702
703 Event *server2_can_reply_;
704};
705
706class QueuedReplyClient2 : public Worker {
707 public:
[email protected]3cdb7af812008-10-24 19:21:13708 explicit QueuedReplyClient2(
709 Event* client1_msg_received, bool pump_during_send)
710 : Worker(L"test_channel2", Channel::MODE_CLIENT),
711 client1_msg_received_(client1_msg_received),
712 pump_during_send_(pump_during_send){ }
initial.commit09911bf2008-07-26 23:55:29713
714 void Run() {
initial.commit09911bf2008-07-26 23:55:29715 client1_msg_received_->Wait();
[email protected]4df10d612008-11-12 00:38:26716 SendAnswerToLife(pump_during_send_, INFINITE, true);
initial.commit09911bf2008-07-26 23:55:29717 Done();
718 }
719
initial.commit09911bf2008-07-26 23:55:29720 Event *client1_msg_received_;
[email protected]3cdb7af812008-10-24 19:21:13721 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29722};
723
[email protected]3cdb7af812008-10-24 19:21:13724void QueuedReply(bool server_pump, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29725 std::vector<Worker*> workers;
726
727 // A shared worker thread so that server1 and server2 run on one thread.
[email protected]ab820df2008-08-26 05:55:10728 base::Thread worker_thread("QueuedReply");
initial.commit09911bf2008-07-26 23:55:29729 worker_thread.Start();
730
731 Event client1_msg_received, server2_can_reply;
732
733 Worker* worker;
734
735 worker = new QueuedReplyServer2(&server2_can_reply);
736 worker->OverrideThread(&worker_thread);
737 workers.push_back(worker);
738
[email protected]3cdb7af812008-10-24 19:21:13739 worker = new QueuedReplyClient2(&client1_msg_received, client_pump);
initial.commit09911bf2008-07-26 23:55:29740 workers.push_back(worker);
741
[email protected]3cdb7af812008-10-24 19:21:13742 worker = new QueuedReplyServer1(server_pump);
initial.commit09911bf2008-07-26 23:55:29743 worker->OverrideThread(&worker_thread);
744 workers.push_back(worker);
745
746 worker = new QueuedReplyClient1(
747 &client1_msg_received, &server2_can_reply);
748 workers.push_back(worker);
749
750 RunTest(workers);
751}
752
[email protected]3cdb7af812008-10-24 19:21:13753} // namespace
754
755// While a blocking send is in progress, the listener thread might answer other
756// synchronous messages. This tests that if during the response to another
757// message the reply to the original messages comes, it is queued up correctly
758// and the original Send is unblocked later.
759TEST_F(IPCSyncChannelTest, QueuedReply) {
760 QueuedReply(false, false);
761 QueuedReply(false, true);
762 QueuedReply(true, false);
763 QueuedReply(true, true);
764}
initial.commit09911bf2008-07-26 23:55:29765
766//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34767
768namespace {
769
initial.commit09911bf2008-07-26 23:55:29770class BadServer : public Worker {
771 public:
[email protected]3cdb7af812008-10-24 19:21:13772 BadServer(bool pump_during_send)
773 : Worker(Channel::MODE_SERVER, "simpler_server"),
774 pump_during_send_(pump_during_send) { }
initial.commit09911bf2008-07-26 23:55:29775 void Run() {
776 int answer = 0;
777
[email protected]4df10d612008-11-12 00:38:26778 SyncMessage* msg = new SyncMessage(
[email protected]3cdb7af812008-10-24 19:21:13779 MSG_ROUTING_CONTROL, SyncChannelTestMsg_Double::ID,
780 Message::PRIORITY_NORMAL, NULL);
781 if (pump_during_send_)
782 msg->EnableMessagePumping();
783
initial.commit09911bf2008-07-26 23:55:29784 // Temporarily set the minimum logging very high so that the assertion
785 // in ipc_message_utils doesn't fire.
786 int log_level = logging::GetMinLogLevel();
787 logging::SetMinLogLevel(kint32max);
788 bool result = Send(msg);
789 logging::SetMinLogLevel(log_level);
790 DCHECK(!result);
791
792 // Need to send another message to get the client to call Done().
793 result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
794 DCHECK(result);
795 DCHECK(answer == 42);
796
797 Done();
798 }
[email protected]3cdb7af812008-10-24 19:21:13799
800 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29801};
802
[email protected]3cdb7af812008-10-24 19:21:13803void BadMessage(bool pump_during_send) {
804 std::vector<Worker*> workers;
805 workers.push_back(new BadServer(pump_during_send));
806 workers.push_back(new SimpleClient());
807 RunTest(workers);
808}
809
[email protected]dd3eac22008-08-26 07:28:34810} // namespace
811
initial.commit09911bf2008-07-26 23:55:29812// Tests that if a message is not serialized correctly, the Send() will fail.
[email protected]dd3eac22008-08-26 07:28:34813TEST_F(IPCSyncChannelTest, BadMessage) {
[email protected]3cdb7af812008-10-24 19:21:13814 BadMessage(false);
815 BadMessage(true);
initial.commit09911bf2008-07-26 23:55:29816}
817
initial.commit09911bf2008-07-26 23:55:29818//-----------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34819
820namespace {
821
[email protected]3cdb7af812008-10-24 19:21:13822class ChattyClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29823 public:
[email protected]3cdb7af812008-10-24 19:21:13824 ChattyClient() :
825 Worker(Channel::MODE_CLIENT, "chatty_client") { }
initial.commit09911bf2008-07-26 23:55:29826
827 void OnAnswer(int* answer) {
828 // The PostMessage limit is 10k. Send 20% more than that.
829 const int kMessageLimit = 10000;
830 const int kMessagesToSend = kMessageLimit * 120 / 100;
831 for (int i = 0; i < kMessagesToSend; ++i) {
[email protected]4df10d612008-11-12 00:38:26832 if (!SendDouble(false, true))
initial.commit09911bf2008-07-26 23:55:29833 break;
834 }
[email protected]4df10d612008-11-12 00:38:26835 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29836 Done();
837 }
838};
839
[email protected]3cdb7af812008-10-24 19:21:13840void ChattyServer(bool pump_during_send) {
841 std::vector<Worker*> workers;
842 workers.push_back(new UnblockServer(pump_during_send));
843 workers.push_back(new ChattyClient());
844 RunTest(workers);
845}
846
[email protected]dd3eac22008-08-26 07:28:34847} // namespace
848
[email protected]4df10d612008-11-12 00:38:26849// Tests http://b/1093251 - that sending lots of sync messages while
initial.commit09911bf2008-07-26 23:55:29850// the receiver is waiting for a sync reply does not overflow the PostMessage
851// queue.
[email protected]dd3eac22008-08-26 07:28:34852TEST_F(IPCSyncChannelTest, ChattyServer) {
[email protected]3cdb7af812008-10-24 19:21:13853 ChattyServer(false);
854 ChattyServer(true);
initial.commit09911bf2008-07-26 23:55:29855}
[email protected]d65cab7a2008-08-12 01:25:41856
[email protected]d65cab7a2008-08-12 01:25:41857//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34858
859namespace {
860
[email protected]d65cab7a2008-08-12 01:25:41861class TimeoutServer : public Worker {
862 public:
863 TimeoutServer(int timeout_ms,
[email protected]3cdb7af812008-10-24 19:21:13864 std::vector<bool> timeout_seq,
865 bool pump_during_send)
[email protected]d65cab7a2008-08-12 01:25:41866 : Worker(Channel::MODE_SERVER, "timeout_server"),
867 timeout_ms_(timeout_ms),
[email protected]3cdb7af812008-10-24 19:21:13868 timeout_seq_(timeout_seq),
869 pump_during_send_(pump_during_send) {
[email protected]d65cab7a2008-08-12 01:25:41870 }
871
872 void Run() {
873 for (std::vector<bool>::const_iterator iter = timeout_seq_.begin();
874 iter != timeout_seq_.end(); ++iter) {
[email protected]4df10d612008-11-12 00:38:26875 SendAnswerToLife(pump_during_send_, timeout_ms_, !*iter);
[email protected]d65cab7a2008-08-12 01:25:41876 }
877 Done();
878 }
879
880 private:
881 int timeout_ms_;
882 std::vector<bool> timeout_seq_;
[email protected]3cdb7af812008-10-24 19:21:13883 bool pump_during_send_;
[email protected]d65cab7a2008-08-12 01:25:41884};
885
886class UnresponsiveClient : public Worker {
887 public:
888 UnresponsiveClient(std::vector<bool> timeout_seq)
889 : Worker(Channel::MODE_CLIENT, "unresponsive_client"),
890 timeout_seq_(timeout_seq) {
891 }
892
893 void OnAnswerDelay(Message* reply_msg) {
894 DCHECK(!timeout_seq_.empty());
895 if (!timeout_seq_[0]) {
896 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
897 Send(reply_msg);
898 } else {
899 // Don't reply.
[email protected]463667372008-08-20 20:20:52900 delete reply_msg;
[email protected]d65cab7a2008-08-12 01:25:41901 }
902 timeout_seq_.erase(timeout_seq_.begin());
903 if (timeout_seq_.empty())
904 Done();
905 }
906
907 private:
908 // Whether we should time-out or respond to the various messages we receive.
909 std::vector<bool> timeout_seq_;
910};
911
[email protected]3cdb7af812008-10-24 19:21:13912void SendWithTimeoutOK(bool pump_during_send) {
913 std::vector<Worker*> workers;
914 std::vector<bool> timeout_seq;
915 timeout_seq.push_back(false);
916 timeout_seq.push_back(false);
917 timeout_seq.push_back(false);
918 workers.push_back(new TimeoutServer(5000, timeout_seq, pump_during_send));
919 workers.push_back(new SimpleClient());
920 RunTest(workers);
921}
922
923void SendWithTimeoutTimeout(bool pump_during_send) {
924 std::vector<Worker*> workers;
925 std::vector<bool> timeout_seq;
926 timeout_seq.push_back(true);
927 timeout_seq.push_back(false);
928 timeout_seq.push_back(false);
929 workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
930 workers.push_back(new UnresponsiveClient(timeout_seq));
931 RunTest(workers);
932}
933
934void SendWithTimeoutMixedOKAndTimeout(bool pump_during_send) {
935 std::vector<Worker*> workers;
936 std::vector<bool> timeout_seq;
937 timeout_seq.push_back(true);
938 timeout_seq.push_back(false);
939 timeout_seq.push_back(false);
940 timeout_seq.push_back(true);
941 timeout_seq.push_back(false);
942 workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
943 workers.push_back(new UnresponsiveClient(timeout_seq));
944 RunTest(workers);
945}
946
[email protected]dd3eac22008-08-26 07:28:34947} // namespace
948
[email protected]d65cab7a2008-08-12 01:25:41949// Tests that SendWithTimeout does not time-out if the response comes back fast
950// enough.
[email protected]dd3eac22008-08-26 07:28:34951TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) {
[email protected]3cdb7af812008-10-24 19:21:13952 SendWithTimeoutOK(false);
953 SendWithTimeoutOK(true);
[email protected]d65cab7a2008-08-12 01:25:41954}
955
956// Tests that SendWithTimeout does time-out.
[email protected]dd3eac22008-08-26 07:28:34957TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) {
[email protected]3cdb7af812008-10-24 19:21:13958 SendWithTimeoutTimeout(false);
959 SendWithTimeoutTimeout(true);
[email protected]d65cab7a2008-08-12 01:25:41960}
961
962// Sends some message that time-out and some that succeed.
[email protected]dd3eac22008-08-26 07:28:34963TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) {
[email protected]3cdb7af812008-10-24 19:21:13964 SendWithTimeoutMixedOKAndTimeout(false);
965 SendWithTimeoutMixedOKAndTimeout(true);
966}
[email protected]4df10d612008-11-12 00:38:26967
968//------------------------------------------------------------------------------
969
970namespace {
971
972class NestedTask : public Task {
973 public:
974 NestedTask(Worker* server) : server_(server) { }
975 void Run() {
976 // Sleep a bit so that we wake up after the reply has been received.
977 Sleep(250);
978 server_->SendAnswerToLife(true, INFINITE, true);
979 }
980
981 Worker* server_;
982};
983
984static bool timeout_occured = false;
985
986class TimeoutTask : public Task {
987 public:
988 void Run() {
989 timeout_occured = true;
990 }
991};
992
993class DoneEventRaceServer : public Worker {
994 public:
995 DoneEventRaceServer()
996 : Worker(Channel::MODE_SERVER, "done_event_race_server") { }
997
998 void Run() {
999 MessageLoop::current()->PostTask(FROM_HERE, new NestedTask(this));
1000 MessageLoop::current()->PostDelayedTask(FROM_HERE, new TimeoutTask(), 9000);
1001 // Even though we have a timeout on the Send, it will succeed since for this
1002 // bug, the reply message comes back and is deserialized, however the done
1003 // event wasn't set. So we indirectly use the timeout task to notice if a
1004 // timeout occurred.
1005 SendAnswerToLife(true, 10000, true);
1006 DCHECK(!timeout_occured);
1007 Done();
1008 }
1009};
1010
1011} // namespace
1012
1013// Tests http://b/1474092 - that if after the done_event is set but before
1014// OnObjectSignaled is called another message is sent out, then after its
1015// reply comes back OnObjectSignaled will be called for the first message.
1016TEST_F(IPCSyncChannelTest, DoneEventRace) {
1017 std::vector<Worker*> workers;
1018 workers.push_back(new DoneEventRaceServer());
1019 workers.push_back(new SimpleClient());
1020 RunTest(workers);
1021}