OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // Unit test for SyncChannel. | 5 // Unit test for SyncChannel. |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 Worker(const std::wstring& channel_name, Channel::Mode mode) | 76 Worker(const std::wstring& channel_name, Channel::Mode mode) |
77 : channel_name_(channel_name), | 77 : channel_name_(channel_name), |
78 mode_(mode), | 78 mode_(mode), |
79 ipc_thread_((WideToUTF8(channel_name) + "_ipc").c_str()), | 79 ipc_thread_((WideToUTF8(channel_name) + "_ipc").c_str()), |
80 listener_thread_((WideToUTF8(channel_name) + "_listener").c_str()), | 80 listener_thread_((WideToUTF8(channel_name) + "_listener").c_str()), |
81 overrided_thread_(NULL) { } | 81 overrided_thread_(NULL) { } |
82 | 82 |
83 // The IPC thread needs to outlive SyncChannel, so force the correct order of | 83 // The IPC thread needs to outlive SyncChannel, so force the correct order of |
84 // destruction. | 84 // destruction. |
85 virtual ~Worker() { | 85 virtual ~Worker() { |
86 CloseChannel(); | 86 Event listener_done, ipc_done; |
87 // We must stop the threads and release the channel here. The IPC thread | 87 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
88 // must die before the listener thread, otherwise if its in the process of | 88 this, &Worker::OnListenerThreadShutdown, listener_done.handle(), |
89 // sending a message, it will get an error, it will use channel_, which | 89 ipc_done.handle())); |
90 // references listener_. There are many ways of crashing, depending on | 90 HANDLE handles[] = { listener_done.handle(), ipc_done.handle() }; |
91 // timing. | 91 WaitForMultipleObjects(2, handles, TRUE, INFINITE); |
92 // This is a race condition so you may not see it all the time even if you | |
93 // reverse the Stop() calls. You may see this bug with AppVerifier only. | |
94 ipc_thread_.Stop(); | 92 ipc_thread_.Stop(); |
95 listener_thread_.Stop(); | 93 listener_thread_.Stop(); |
96 channel_.reset(); | |
97 } | 94 } |
98 void AddRef() { } | 95 void AddRef() { } |
99 void Release() { } | 96 void Release() { } |
100 bool Send(Message* msg) { return channel_->Send(msg); } | 97 bool Send(Message* msg) { return channel_->Send(msg); } |
101 bool SendWithTimeout(Message* msg, int timeout_ms) { | 98 bool SendWithTimeout(Message* msg, int timeout_ms) { |
102 return channel_->SendWithTimeout(msg, timeout_ms); | 99 return channel_->SendWithTimeout(msg, timeout_ms); |
103 } | 100 } |
104 void WaitForChannelCreation() { channel_created_.Wait(); } | 101 void WaitForChannelCreation() { channel_created_.Wait(); } |
105 void CloseChannel() { channel_.reset(); } | 102 void CloseChannel() { |
| 103 DCHECK(MessageLoop::current() == ListenerThread()->message_loop()); |
| 104 channel_->Close(); |
| 105 } |
106 void Start() { | 106 void Start() { |
107 StartThread(&listener_thread_); | 107 StartThread(&listener_thread_); |
108 base::Thread* thread = | 108 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
109 overrided_thread_ ? overrided_thread_ : &listener_thread_; | |
110 thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
111 this, &Worker::OnStart)); | 109 this, &Worker::OnStart)); |
112 } | 110 } |
113 void OverrideThread(base::Thread* overrided_thread) { | 111 void OverrideThread(base::Thread* overrided_thread) { |
114 DCHECK(overrided_thread_ == NULL); | 112 DCHECK(overrided_thread_ == NULL); |
115 overrided_thread_ = overrided_thread; | 113 overrided_thread_ = overrided_thread; |
116 } | 114 } |
117 Channel::Mode mode() { return mode_; } | 115 Channel::Mode mode() { return mode_; } |
118 HANDLE done_event() { return done_.handle(); } | 116 HANDLE done_event() { return done_.handle(); } |
119 | 117 |
120 protected: | 118 protected: |
121 // Derived classes need to call this when they've completed their part of | 119 // Derived classes need to call this when they've completed their part of |
122 // the test. | 120 // the test. |
123 void Done() { done_.Set(); } | 121 void Done() { done_.Set(); } |
124 | 122 |
125 // Functions for dervied classes to implement if they wish. | 123 // Functions for dervied classes to implement if they wish. |
126 virtual void Run() { } | 124 virtual void Run() { } |
127 virtual void OnDouble(int in, int* out) { NOTREACHED(); } | |
128 virtual void OnAnswer(int* answer) { NOTREACHED(); } | 125 virtual void OnAnswer(int* answer) { NOTREACHED(); } |
129 virtual void OnAnswerDelay(Message* reply_msg) { | 126 virtual void OnAnswerDelay(Message* reply_msg) { |
130 // The message handler map below can only take one entry for | 127 // The message handler map below can only take one entry for |
131 // SyncChannelTestMsg_AnswerToLife, so since some classes want | 128 // SyncChannelTestMsg_AnswerToLife, so since some classes want |
132 // the normal version while other want the delayed reply, we | 129 // the normal version while other want the delayed reply, we |
133 // call the normal version if the derived class didn't override | 130 // call the normal version if the derived class didn't override |
134 // this function. | 131 // this function. |
135 int answer; | 132 int answer; |
136 OnAnswer(&answer); | 133 OnAnswer(&answer); |
137 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer); | 134 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer); |
138 Send(reply_msg); | 135 Send(reply_msg); |
139 } | 136 } |
| 137 virtual void OnDouble(int in, int* out) { NOTREACHED(); } |
| 138 virtual void OnDoubleDelay(int in, Message* reply_msg) { |
| 139 int result; |
| 140 OnDouble(in, &result); |
| 141 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result); |
| 142 Send(reply_msg); |
| 143 } |
140 | 144 |
141 private: | 145 private: |
| 146 base::Thread* ListenerThread() { |
| 147 return overrided_thread_ ? overrided_thread_ : &listener_thread_; |
| 148 } |
142 // Called on the listener thread to create the sync channel. | 149 // Called on the listener thread to create the sync channel. |
143 void OnStart() { | 150 void OnStart() { |
144 // Link ipc_thread_, listener_thread_ and channel_ altogether. | 151 // Link ipc_thread_, listener_thread_ and channel_ altogether. |
145 StartThread(&ipc_thread_); | 152 StartThread(&ipc_thread_); |
146 channel_.reset(new SyncChannel( | 153 channel_.reset(new SyncChannel( |
147 channel_name_, mode_, this, NULL, ipc_thread_.message_loop(), true, | 154 channel_name_, mode_, this, NULL, ipc_thread_.message_loop(), true, |
148 TestProcess::GetShutDownEvent())); | 155 TestProcess::GetShutDownEvent())); |
149 channel_created_.Set(); | 156 channel_created_.Set(); |
150 Run(); | 157 Run(); |
151 } | 158 } |
152 | 159 |
| 160 void OnListenerThreadShutdown(HANDLE listener_event, HANDLE ipc_event) { |
| 161 // SyncChannel needs to be destructed on the thread that it was created on. |
| 162 channel_.reset(); |
| 163 SetEvent(listener_event); |
| 164 |
| 165 ipc_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 166 this, &Worker::OnIPCThreadShutdown, ipc_event)); |
| 167 } |
| 168 |
| 169 void OnIPCThreadShutdown(HANDLE ipc_event) { |
| 170 SetEvent(ipc_event); |
| 171 } |
| 172 |
153 void OnMessageReceived(const Message& message) { | 173 void OnMessageReceived(const Message& message) { |
154 IPC_BEGIN_MESSAGE_MAP(Worker, message) | 174 IPC_BEGIN_MESSAGE_MAP(Worker, message) |
155 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Double, OnDouble) | 175 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay) |
156 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife, | 176 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife, |
157 OnAnswerDelay) | 177 OnAnswerDelay) |
158 IPC_END_MESSAGE_MAP() | 178 IPC_END_MESSAGE_MAP() |
159 } | 179 } |
160 | 180 |
161 void StartThread(base::Thread* thread) { | 181 void StartThread(base::Thread* thread) { |
162 base::Thread::Options options; | 182 base::Thread::Options options; |
163 options.message_loop_type = MessageLoop::TYPE_IO; | 183 options.message_loop_type = MessageLoop::TYPE_IO; |
164 thread->StartWithOptions(options); | 184 thread->StartWithOptions(options); |
165 } | 185 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 | 224 |
205 int count = static_cast<int>(done_handles.size()); | 225 int count = static_cast<int>(done_handles.size()); |
206 WaitForMultipleObjects(count, &done_handles.front(), TRUE, INFINITE); | 226 WaitForMultipleObjects(count, &done_handles.front(), TRUE, INFINITE); |
207 STLDeleteContainerPointers(workers.begin(), workers.end()); | 227 STLDeleteContainerPointers(workers.begin(), workers.end()); |
208 | 228 |
209 TestProcess::GlobalCleanup(); | 229 TestProcess::GlobalCleanup(); |
210 } | 230 } |
211 | 231 |
212 } // namespace | 232 } // namespace |
213 | 233 |
214 | |
215 //----------------------------------------------------------------------------- | 234 //----------------------------------------------------------------------------- |
216 | 235 |
217 namespace { | 236 namespace { |
218 | 237 |
219 class SimpleServer : public Worker { | 238 class SimpleServer : public Worker { |
220 public: | 239 public: |
221 SimpleServer() : Worker(Channel::MODE_SERVER, "simpler_server") { } | 240 SimpleServer(bool pump_during_send) |
| 241 : Worker(Channel::MODE_SERVER, "simpler_server"), |
| 242 pump_during_send_(pump_during_send) { } |
222 void Run() { | 243 void Run() { |
223 int answer = 0; | 244 int answer = 0; |
224 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 245 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 246 if (pump_during_send_) |
| 247 msg->EnableMessagePumping(); |
| 248 bool result = Send(msg); |
225 DCHECK(result); | 249 DCHECK(result); |
226 DCHECK(answer == 42); | 250 DCHECK(answer == 42); |
227 Done(); | 251 Done(); |
228 } | 252 } |
| 253 |
| 254 bool pump_during_send_; |
229 }; | 255 }; |
230 | 256 |
231 class SimpleClient : public Worker { | 257 class SimpleClient : public Worker { |
232 public: | 258 public: |
233 SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { } | 259 SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { } |
234 | 260 |
235 void OnAnswer(int* answer) { | 261 void OnAnswer(int* answer) { |
236 *answer = 42; | 262 *answer = 42; |
237 Done(); | 263 Done(); |
238 } | 264 } |
239 }; | 265 }; |
240 | 266 |
| 267 void Simple(bool pump_during_send) { |
| 268 std::vector<Worker*> workers; |
| 269 workers.push_back(new SimpleServer(pump_during_send)); |
| 270 workers.push_back(new SimpleClient()); |
| 271 RunTest(workers); |
| 272 } |
| 273 |
241 } // namespace | 274 } // namespace |
242 | 275 |
243 // Tests basic synchronous call | 276 // Tests basic synchronous call |
244 TEST_F(IPCSyncChannelTest, Simple) { | 277 TEST_F(IPCSyncChannelTest, Simple) { |
245 std::vector<Worker*> workers; | 278 Simple(false); |
246 workers.push_back(new SimpleServer()); | 279 Simple(true); |
247 workers.push_back(new SimpleClient()); | |
248 RunTest(workers); | |
249 } | 280 } |
250 | 281 |
251 | |
252 //----------------------------------------------------------------------------- | 282 //----------------------------------------------------------------------------- |
253 | 283 |
254 namespace { | 284 namespace { |
255 | 285 |
256 class DelayClient : public Worker { | 286 class DelayClient : public Worker { |
257 public: | 287 public: |
258 DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { } | 288 DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { } |
259 | 289 |
260 void OnAnswerDelay(Message* reply_msg) { | 290 void OnAnswerDelay(Message* reply_msg) { |
261 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); | 291 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); |
262 Send(reply_msg); | 292 Send(reply_msg); |
263 Done(); | 293 Done(); |
264 } | 294 } |
265 }; | 295 }; |
266 | 296 |
| 297 void DelayReply(bool pump_during_send) { |
| 298 std::vector<Worker*> workers; |
| 299 workers.push_back(new SimpleServer(pump_during_send)); |
| 300 workers.push_back(new DelayClient()); |
| 301 RunTest(workers); |
| 302 } |
| 303 |
267 } // namespace | 304 } // namespace |
268 | 305 |
269 // Tests that asynchronous replies work | 306 // Tests that asynchronous replies work |
270 TEST_F(IPCSyncChannelTest, DelayReply) { | 307 TEST_F(IPCSyncChannelTest, DelayReply) { |
271 std::vector<Worker*> workers; | 308 DelayReply(false); |
272 workers.push_back(new SimpleServer()); | 309 DelayReply(true); |
273 workers.push_back(new DelayClient()); | |
274 RunTest(workers); | |
275 } | 310 } |
276 | 311 |
277 | |
278 //----------------------------------------------------------------------------- | 312 //----------------------------------------------------------------------------- |
279 | 313 |
280 namespace { | 314 namespace { |
281 | 315 |
282 class NoHangServer : public Worker { | 316 class NoHangServer : public Worker { |
283 public: | 317 public: |
284 explicit NoHangServer(Event* got_first_reply) | 318 explicit NoHangServer(Event* got_first_reply, bool pump_during_send) |
285 : Worker(Channel::MODE_SERVER, "no_hang_server"), | 319 : Worker(Channel::MODE_SERVER, "no_hang_server"), |
286 got_first_reply_(got_first_reply) { } | 320 got_first_reply_(got_first_reply), |
| 321 pump_during_send_(pump_during_send) { } |
287 void Run() { | 322 void Run() { |
288 int answer = 0; | 323 int answer = 0; |
289 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 324 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 325 if (pump_during_send_) |
| 326 msg->EnableMessagePumping(); |
| 327 bool result = Send(msg); |
290 DCHECK(result); | 328 DCHECK(result); |
291 DCHECK(answer == 42); | 329 DCHECK(answer == 42); |
292 got_first_reply_->Set(); | 330 got_first_reply_->Set(); |
293 | 331 |
294 result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 332 msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 333 if (pump_during_send_) |
| 334 msg->EnableMessagePumping(); |
| 335 result = Send(msg); |
295 DCHECK(!result); | 336 DCHECK(!result); |
296 Done(); | 337 Done(); |
297 } | 338 } |
298 | 339 |
299 Event* got_first_reply_; | 340 Event* got_first_reply_; |
| 341 bool pump_during_send_; |
300 }; | 342 }; |
301 | 343 |
302 class NoHangClient : public Worker { | 344 class NoHangClient : public Worker { |
303 public: | 345 public: |
304 explicit NoHangClient(Event* got_first_reply) | 346 explicit NoHangClient(Event* got_first_reply) |
305 : Worker(Channel::MODE_CLIENT, "no_hang_client"), | 347 : Worker(Channel::MODE_CLIENT, "no_hang_client"), |
306 got_first_reply_(got_first_reply) { } | 348 got_first_reply_(got_first_reply) { } |
307 | 349 |
308 virtual void OnAnswerDelay(Message* reply_msg) { | 350 virtual void OnAnswerDelay(Message* reply_msg) { |
309 // Use the DELAY_REPLY macro so that we can force the reply to be sent | 351 // Use the DELAY_REPLY macro so that we can force the reply to be sent |
310 // before this function returns (when the channel will be reset). | 352 // before this function returns (when the channel will be reset). |
311 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); | 353 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); |
312 Send(reply_msg); | 354 Send(reply_msg); |
313 got_first_reply_->Wait(); | 355 got_first_reply_->Wait(); |
314 CloseChannel(); | 356 CloseChannel(); |
315 Done(); | 357 Done(); |
316 } | 358 } |
317 | 359 |
318 Event* got_first_reply_; | 360 Event* got_first_reply_; |
319 }; | 361 }; |
320 | 362 |
| 363 void NoHang(bool pump_during_send) { |
| 364 Event got_first_reply; |
| 365 std::vector<Worker*> workers; |
| 366 workers.push_back(new NoHangServer(&got_first_reply, pump_during_send)); |
| 367 workers.push_back(new NoHangClient(&got_first_reply)); |
| 368 RunTest(workers); |
| 369 } |
| 370 |
321 } // namespace | 371 } // namespace |
322 | 372 |
323 // Tests that caller doesn't hang if receiver dies | 373 // Tests that caller doesn't hang if receiver dies |
324 TEST_F(IPCSyncChannelTest, NoHang) { | 374 TEST_F(IPCSyncChannelTest, NoHang) { |
325 Event got_first_reply; | 375 NoHang(false); |
326 | 376 NoHang(true); |
327 std::vector<Worker*> workers; | |
328 workers.push_back(new NoHangServer(&got_first_reply)); | |
329 workers.push_back(new NoHangClient(&got_first_reply)); | |
330 RunTest(workers); | |
331 } | 377 } |
332 | 378 |
333 | |
334 //----------------------------------------------------------------------------- | 379 //----------------------------------------------------------------------------- |
335 | 380 |
336 namespace { | 381 namespace { |
337 | 382 |
338 class RecursiveServer : public Worker { | 383 class UnblockServer : public Worker { |
339 public: | 384 public: |
340 RecursiveServer() : Worker(Channel::MODE_SERVER, "recursive_server") { } | 385 UnblockServer(bool pump_during_send) |
| 386 : Worker(Channel::MODE_SERVER, "unblock_server"), |
| 387 pump_during_send_(pump_during_send) { } |
341 void Run() { | 388 void Run() { |
342 int answer = 0; | 389 int answer = 0; |
343 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 390 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 391 if (pump_during_send_) |
| 392 msg->EnableMessagePumping(); |
| 393 bool result = Send(msg); |
344 DCHECK(result); | 394 DCHECK(result); |
345 DCHECK(answer == 42); | 395 DCHECK(answer == 42); |
346 Done(); | 396 Done(); |
347 } | 397 } |
348 | 398 |
349 void OnDouble(int in, int* out) { | 399 void OnDouble(int in, int* out) { |
350 *out = in * 2; | 400 *out = in * 2; |
351 } | 401 } |
| 402 |
| 403 bool pump_during_send_; |
| 404 }; |
| 405 |
| 406 class UnblockClient : public Worker { |
| 407 public: |
| 408 UnblockClient(bool pump_during_send) |
| 409 : Worker(Channel::MODE_CLIENT, "unblock_client"), |
| 410 pump_during_send_(pump_during_send) { } |
| 411 |
| 412 void OnAnswer(int* answer) { |
| 413 IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(21, answer); |
| 414 if (pump_during_send_) |
| 415 msg->EnableMessagePumping(); |
| 416 BOOL result = Send(msg); |
| 417 DCHECK(result); |
| 418 Done(); |
| 419 } |
| 420 |
| 421 bool pump_during_send_; |
| 422 }; |
| 423 |
| 424 void Unblock(bool server_pump, bool client_pump) { |
| 425 std::vector<Worker*> workers; |
| 426 workers.push_back(new UnblockServer(server_pump)); |
| 427 workers.push_back(new UnblockClient(client_pump)); |
| 428 RunTest(workers); |
| 429 } |
| 430 |
| 431 } // namespace |
| 432 |
| 433 // Tests that the caller unblocks to answer a sync message from the receiver. |
| 434 TEST_F(IPCSyncChannelTest, Unblock) { |
| 435 Unblock(false, false); |
| 436 Unblock(false, true); |
| 437 Unblock(true, false); |
| 438 Unblock(true, true); |
| 439 } |
| 440 |
| 441 //----------------------------------------------------------------------------- |
| 442 |
| 443 namespace { |
| 444 |
| 445 class RecursiveServer : public Worker { |
| 446 public: |
| 447 explicit RecursiveServer( |
| 448 bool expected_send_result, bool pump_first, bool pump_second) |
| 449 : Worker(Channel::MODE_SERVER, "recursive_server"), |
| 450 expected_send_result_(expected_send_result), |
| 451 pump_first_(pump_first), pump_second_(pump_second) { } |
| 452 void Run() { |
| 453 int answer; |
| 454 IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(21, &answer); |
| 455 if (pump_first_) |
| 456 msg->EnableMessagePumping(); |
| 457 bool result = Send(msg); |
| 458 DCHECK(result == expected_send_result_); |
| 459 Done(); |
| 460 } |
| 461 |
| 462 void OnDouble(int in, int* out) { |
| 463 int answer; |
| 464 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 465 if (pump_second_) |
| 466 msg->EnableMessagePumping(); |
| 467 bool result = Send(msg); |
| 468 DCHECK(result == expected_send_result_); |
| 469 } |
| 470 |
| 471 bool expected_send_result_, pump_first_, pump_second_; |
352 }; | 472 }; |
353 | 473 |
354 class RecursiveClient : public Worker { | 474 class RecursiveClient : public Worker { |
355 public: | 475 public: |
356 RecursiveClient() : Worker(Channel::MODE_CLIENT, "recursive_client") { } | 476 explicit RecursiveClient(bool pump_during_send, bool close_channel) |
| 477 : Worker(Channel::MODE_CLIENT, "recursive_client"), |
| 478 pump_during_send_(pump_during_send), close_channel_(close_channel) { } |
357 | 479 |
358 void OnAnswer(int* answer) { | 480 void OnDoubleDelay(int in, Message* reply_msg) { |
359 BOOL result = Send(new SyncChannelTestMsg_Double(21, answer)); | 481 int answer = 0; |
360 DCHECK(result); | 482 IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer); |
| 483 if (pump_during_send_) |
| 484 msg->EnableMessagePumping(); |
| 485 bool result = Send(msg); |
| 486 DCHECK(result != close_channel_); |
| 487 if (!close_channel_) { |
| 488 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2); |
| 489 Send(reply_msg); |
| 490 } |
361 Done(); | 491 Done(); |
362 } | 492 } |
| 493 |
| 494 void OnAnswerDelay(Message* reply_msg) { |
| 495 if (close_channel_) { |
| 496 CloseChannel(); |
| 497 } else { |
| 498 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); |
| 499 Send(reply_msg); |
| 500 } |
| 501 } |
| 502 |
| 503 bool pump_during_send_, close_channel_; |
363 }; | 504 }; |
364 | 505 |
| 506 void Recursive( |
| 507 bool server_pump_first, bool server_pump_second, bool client_pump) { |
| 508 std::vector<Worker*> workers; |
| 509 workers.push_back( |
| 510 new RecursiveServer(true, server_pump_first, server_pump_second)); |
| 511 workers.push_back(new RecursiveClient(client_pump, false)); |
| 512 RunTest(workers); |
| 513 } |
| 514 |
365 } // namespace | 515 } // namespace |
366 | 516 |
367 // Tests that the caller unblocks to answer a sync message from the receiver. | 517 // Tests a server calling Send while another Send is pending. |
368 TEST_F(IPCSyncChannelTest, Recursive) { | 518 TEST_F(IPCSyncChannelTest, Recursive) { |
| 519 Recursive(false, false, false); |
| 520 Recursive(false, false, true); |
| 521 Recursive(false, true, false); |
| 522 Recursive(false, true, true); |
| 523 Recursive(true, false, false); |
| 524 Recursive(true, false, true); |
| 525 Recursive(true, true, false); |
| 526 Recursive(true, true, true); |
| 527 } |
| 528 |
| 529 //----------------------------------------------------------------------------- |
| 530 |
| 531 namespace { |
| 532 |
| 533 void RecursiveNoHang( |
| 534 bool server_pump_first, bool server_pump_second, bool client_pump) { |
369 std::vector<Worker*> workers; | 535 std::vector<Worker*> workers; |
370 workers.push_back(new RecursiveServer()); | 536 workers.push_back( |
371 workers.push_back(new RecursiveClient()); | 537 new RecursiveServer(false, server_pump_first, server_pump_second)); |
| 538 workers.push_back(new RecursiveClient(client_pump, true)); |
372 RunTest(workers); | 539 RunTest(workers); |
373 } | 540 } |
374 | 541 |
| 542 } // namespace |
| 543 |
| 544 // Tests that if a caller makes a sync call during an existing sync call and |
| 545 // the receiver dies, neither of the Send() calls hang. |
| 546 TEST_F(IPCSyncChannelTest, RecursiveNoHang) { |
| 547 RecursiveNoHang(false, false, false); |
| 548 RecursiveNoHang(false, false, true); |
| 549 RecursiveNoHang(false, true, false); |
| 550 RecursiveNoHang(false, true, true); |
| 551 RecursiveNoHang(true, false, false); |
| 552 RecursiveNoHang(true, false, true); |
| 553 RecursiveNoHang(true, true, false); |
| 554 RecursiveNoHang(true, true, true); |
| 555 } |
375 | 556 |
376 //----------------------------------------------------------------------------- | 557 //----------------------------------------------------------------------------- |
377 | 558 |
378 namespace { | 559 namespace { |
379 | 560 |
380 class MultipleServer1 : public Worker { | 561 class MultipleServer1 : public Worker { |
381 public: | 562 public: |
382 MultipleServer1() : Worker(L"test_channel1", Channel::MODE_SERVER) { } | 563 MultipleServer1(bool pump_during_send) |
| 564 : Worker(L"test_channel1", Channel::MODE_SERVER), |
| 565 pump_during_send_(pump_during_send) { } |
| 566 |
383 void Run() { | 567 void Run() { |
384 int answer = 0; | 568 int answer = 0; |
385 bool result = Send(new SyncChannelTestMsg_Double(5, &answer)); | 569 IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer); |
| 570 if (pump_during_send_) |
| 571 msg->EnableMessagePumping(); |
| 572 bool result = Send(msg); |
386 DCHECK(result); | 573 DCHECK(result); |
387 DCHECK(answer == 10); | 574 DCHECK(answer == 10); |
388 Done(); | 575 Done(); |
389 } | 576 } |
| 577 |
| 578 bool pump_during_send_; |
390 }; | 579 }; |
391 | 580 |
392 class MultipleClient1 : public Worker { | 581 class MultipleClient1 : public Worker { |
393 public: | 582 public: |
394 MultipleClient1(Event* client1_msg_received, Event* client1_can_reply) : | 583 MultipleClient1(Event* client1_msg_received, Event* client1_can_reply) : |
395 Worker(L"test_channel1", Channel::MODE_CLIENT), | 584 Worker(L"test_channel1", Channel::MODE_CLIENT), |
396 client1_msg_received_(client1_msg_received), | 585 client1_msg_received_(client1_msg_received), |
397 client1_can_reply_(client1_can_reply) { } | 586 client1_can_reply_(client1_can_reply) { } |
398 | 587 |
399 void OnDouble(int in, int* out) { | 588 void OnDouble(int in, int* out) { |
(...skipping 12 matching lines...) Expand all Loading... |
412 MultipleServer2() : Worker(L"test_channel2", Channel::MODE_SERVER) { } | 601 MultipleServer2() : Worker(L"test_channel2", Channel::MODE_SERVER) { } |
413 | 602 |
414 void OnAnswer(int* result) { | 603 void OnAnswer(int* result) { |
415 *result = 42; | 604 *result = 42; |
416 Done(); | 605 Done(); |
417 } | 606 } |
418 }; | 607 }; |
419 | 608 |
420 class MultipleClient2 : public Worker { | 609 class MultipleClient2 : public Worker { |
421 public: | 610 public: |
422 MultipleClient2(Event* client1_msg_received, Event* client1_can_reply) : | 611 MultipleClient2( |
423 Worker(L"test_channel2", Channel::MODE_CLIENT), | 612 Event* client1_msg_received, Event* client1_can_reply, |
| 613 bool pump_during_send) |
| 614 : Worker(L"test_channel2", Channel::MODE_CLIENT), |
424 client1_msg_received_(client1_msg_received), | 615 client1_msg_received_(client1_msg_received), |
425 client1_can_reply_(client1_can_reply) { } | 616 client1_can_reply_(client1_can_reply), |
| 617 pump_during_send_(pump_during_send) { } |
426 | 618 |
427 void Run() { | 619 void Run() { |
428 int answer = 0; | 620 int answer = 0; |
429 client1_msg_received_->Wait(); | 621 client1_msg_received_->Wait(); |
430 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 622 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 623 if (pump_during_send_) |
| 624 msg->EnableMessagePumping(); |
| 625 bool result = Send(msg); |
431 DCHECK(result); | 626 DCHECK(result); |
432 DCHECK(answer == 42); | 627 DCHECK(answer == 42); |
433 client1_can_reply_->Set(); | 628 client1_can_reply_->Set(); |
434 Done(); | 629 Done(); |
435 } | 630 } |
436 | 631 |
437 private: | 632 private: |
438 Event *client1_msg_received_, *client1_can_reply_; | 633 Event *client1_msg_received_, *client1_can_reply_; |
| 634 bool pump_during_send_; |
439 }; | 635 }; |
440 | 636 |
441 } // namespace | 637 void Multiple(bool server_pump, bool client_pump) { |
442 | |
443 // Tests that multiple SyncObjects on the same listener thread can unblock each | |
444 // other. | |
445 TEST_F(IPCSyncChannelTest, Multiple) { | |
446 std::vector<Worker*> workers; | 638 std::vector<Worker*> workers; |
447 | 639 |
448 // A shared worker thread so that server1 and server2 run on one thread. | 640 // A shared worker thread so that server1 and server2 run on one thread. |
449 base::Thread worker_thread("Multiple"); | 641 base::Thread worker_thread("Multiple"); |
450 worker_thread.Start(); | 642 worker_thread.Start(); |
451 | 643 |
452 // Server1 sends a sync msg to client1, which blocks the reply until | 644 // Server1 sends a sync msg to client1, which blocks the reply until |
453 // server2 (which runs on the same worker thread as server1) responds | 645 // server2 (which runs on the same worker thread as server1) responds |
454 // to a sync msg from client2. | 646 // to a sync msg from client2. |
455 Event client1_msg_received, client1_can_reply; | 647 Event client1_msg_received, client1_can_reply; |
456 | 648 |
457 Worker* worker; | 649 Worker* worker; |
458 | 650 |
459 worker = new MultipleServer2(); | 651 worker = new MultipleServer2(); |
460 worker->OverrideThread(&worker_thread); | 652 worker->OverrideThread(&worker_thread); |
461 workers.push_back(worker); | 653 workers.push_back(worker); |
462 | 654 |
463 worker = new MultipleClient2( | 655 worker = new MultipleClient2( |
464 &client1_msg_received, &client1_can_reply); | 656 &client1_msg_received, &client1_can_reply, client_pump); |
465 workers.push_back(worker); | 657 workers.push_back(worker); |
466 | 658 |
467 worker = new MultipleServer1(); | 659 worker = new MultipleServer1(server_pump); |
468 worker->OverrideThread(&worker_thread); | 660 worker->OverrideThread(&worker_thread); |
469 workers.push_back(worker); | 661 workers.push_back(worker); |
470 | 662 |
471 worker = new MultipleClient1( | 663 worker = new MultipleClient1( |
472 &client1_msg_received, &client1_can_reply); | 664 &client1_msg_received, &client1_can_reply); |
473 workers.push_back(worker); | 665 workers.push_back(worker); |
474 | 666 |
475 RunTest(workers); | 667 RunTest(workers); |
476 } | 668 } |
477 | 669 |
| 670 } // namespace |
| 671 |
| 672 // Tests that multiple SyncObjects on the same listener thread can unblock each |
| 673 // other. |
| 674 TEST_F(IPCSyncChannelTest, Multiple) { |
| 675 Multiple(false, false); |
| 676 Multiple(false, true); |
| 677 Multiple(true, false); |
| 678 Multiple(true, true); |
| 679 } |
478 | 680 |
479 //----------------------------------------------------------------------------- | 681 //----------------------------------------------------------------------------- |
480 | 682 |
481 namespace { | 683 namespace { |
482 | 684 |
483 class QueuedReplyServer1 : public Worker { | 685 class QueuedReplyServer1 : public Worker { |
484 public: | 686 public: |
485 QueuedReplyServer1() : Worker(L"test_channel1", Channel::MODE_SERVER) { } | 687 QueuedReplyServer1(bool pump_during_send) |
| 688 : Worker(L"test_channel1", Channel::MODE_SERVER), |
| 689 pump_during_send_(pump_during_send) { } |
486 void Run() { | 690 void Run() { |
487 int answer = 0; | 691 int answer = 0; |
488 bool result = Send(new SyncChannelTestMsg_Double(5, &answer)); | 692 IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer); |
| 693 if (pump_during_send_) |
| 694 msg->EnableMessagePumping(); |
| 695 bool result = Send(msg); |
489 DCHECK(result); | 696 DCHECK(result); |
490 DCHECK(answer == 10); | 697 DCHECK(answer == 10); |
491 Done(); | 698 Done(); |
492 } | 699 } |
| 700 |
| 701 bool pump_during_send_; |
493 }; | 702 }; |
494 | 703 |
495 class QueuedReplyClient1 : public Worker { | 704 class QueuedReplyClient1 : public Worker { |
496 public: | 705 public: |
497 QueuedReplyClient1(Event* client1_msg_received, Event* server2_can_reply) : | 706 QueuedReplyClient1(Event* client1_msg_received, Event* server2_can_reply) : |
498 Worker(L"test_channel1", Channel::MODE_CLIENT), | 707 Worker(L"test_channel1", Channel::MODE_CLIENT), |
499 client1_msg_received_(client1_msg_received), | 708 client1_msg_received_(client1_msg_received), |
500 server2_can_reply_(server2_can_reply) { } | 709 server2_can_reply_(server2_can_reply) { } |
501 | 710 |
502 void OnDouble(int in, int* out) { | 711 void OnDouble(int in, int* out) { |
(...skipping 21 matching lines...) Expand all Loading... |
524 | 733 |
525 *result = 42; | 734 *result = 42; |
526 Done(); | 735 Done(); |
527 } | 736 } |
528 | 737 |
529 Event *server2_can_reply_; | 738 Event *server2_can_reply_; |
530 }; | 739 }; |
531 | 740 |
532 class QueuedReplyClient2 : public Worker { | 741 class QueuedReplyClient2 : public Worker { |
533 public: | 742 public: |
534 explicit QueuedReplyClient2(Event* client1_msg_received) : | 743 explicit QueuedReplyClient2( |
535 Worker(L"test_channel2", Channel::MODE_CLIENT), | 744 Event* client1_msg_received, bool pump_during_send) |
536 client1_msg_received_(client1_msg_received) { } | 745 : Worker(L"test_channel2", Channel::MODE_CLIENT), |
| 746 client1_msg_received_(client1_msg_received), |
| 747 pump_during_send_(pump_during_send){ } |
537 | 748 |
538 void Run() { | 749 void Run() { |
539 int answer = 0; | 750 int answer = 0; |
540 client1_msg_received_->Wait(); | 751 client1_msg_received_->Wait(); |
541 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 752 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 753 if (pump_during_send_) |
| 754 msg->EnableMessagePumping(); |
| 755 bool result = Send(msg); |
542 DCHECK(result); | 756 DCHECK(result); |
543 DCHECK(answer == 42); | 757 DCHECK(answer == 42); |
544 Done(); | 758 Done(); |
545 } | 759 } |
546 | 760 |
547 private: | |
548 Event *client1_msg_received_; | 761 Event *client1_msg_received_; |
| 762 bool pump_during_send_; |
549 }; | 763 }; |
550 | 764 |
551 } // namespace | 765 void QueuedReply(bool server_pump, bool client_pump) { |
552 | |
553 // While a blocking send is in progress, the listener thread might answer other | |
554 // synchronous messages. This tests that if during the response to another | |
555 // message the reply to the original messages comes, it is queued up correctly | |
556 // and the original Send is unblocked later. | |
557 TEST_F(IPCSyncChannelTest, QueuedReply) { | |
558 std::vector<Worker*> workers; | 766 std::vector<Worker*> workers; |
559 | 767 |
560 // A shared worker thread so that server1 and server2 run on one thread. | 768 // A shared worker thread so that server1 and server2 run on one thread. |
561 base::Thread worker_thread("QueuedReply"); | 769 base::Thread worker_thread("QueuedReply"); |
562 worker_thread.Start(); | 770 worker_thread.Start(); |
563 | 771 |
564 Event client1_msg_received, server2_can_reply; | 772 Event client1_msg_received, server2_can_reply; |
565 | 773 |
566 Worker* worker; | 774 Worker* worker; |
567 | 775 |
568 worker = new QueuedReplyServer2(&server2_can_reply); | 776 worker = new QueuedReplyServer2(&server2_can_reply); |
569 worker->OverrideThread(&worker_thread); | 777 worker->OverrideThread(&worker_thread); |
570 workers.push_back(worker); | 778 workers.push_back(worker); |
571 | 779 |
572 worker = new QueuedReplyClient2(&client1_msg_received); | 780 worker = new QueuedReplyClient2(&client1_msg_received, client_pump); |
573 workers.push_back(worker); | 781 workers.push_back(worker); |
574 | 782 |
575 worker = new QueuedReplyServer1(); | 783 worker = new QueuedReplyServer1(server_pump); |
576 worker->OverrideThread(&worker_thread); | 784 worker->OverrideThread(&worker_thread); |
577 workers.push_back(worker); | 785 workers.push_back(worker); |
578 | 786 |
579 worker = new QueuedReplyClient1( | 787 worker = new QueuedReplyClient1( |
580 &client1_msg_received, &server2_can_reply); | 788 &client1_msg_received, &server2_can_reply); |
581 workers.push_back(worker); | 789 workers.push_back(worker); |
582 | 790 |
583 RunTest(workers); | 791 RunTest(workers); |
584 } | 792 } |
585 | 793 |
| 794 } // namespace |
| 795 |
| 796 // While a blocking send is in progress, the listener thread might answer other |
| 797 // synchronous messages. This tests that if during the response to another |
| 798 // message the reply to the original messages comes, it is queued up correctly |
| 799 // and the original Send is unblocked later. |
| 800 TEST_F(IPCSyncChannelTest, QueuedReply) { |
| 801 QueuedReply(false, false); |
| 802 QueuedReply(false, true); |
| 803 QueuedReply(true, false); |
| 804 QueuedReply(true, true); |
| 805 } |
586 | 806 |
587 //----------------------------------------------------------------------------- | 807 //----------------------------------------------------------------------------- |
588 | 808 |
589 namespace { | 809 namespace { |
590 | 810 |
591 class BadServer : public Worker { | 811 class BadServer : public Worker { |
592 public: | 812 public: |
593 BadServer() : Worker(Channel::MODE_SERVER, "simpler_server") { } | 813 BadServer(bool pump_during_send) |
| 814 : Worker(Channel::MODE_SERVER, "simpler_server"), |
| 815 pump_during_send_(pump_during_send) { } |
594 void Run() { | 816 void Run() { |
595 int answer = 0; | 817 int answer = 0; |
596 | 818 |
597 Message* msg = new SyncMessage(MSG_ROUTING_CONTROL, | 819 IPC::SyncMessage* msg = new SyncMessage( |
598 SyncChannelTestMsg_Double::ID, | 820 MSG_ROUTING_CONTROL, SyncChannelTestMsg_Double::ID, |
599 Message::PRIORITY_NORMAL, | 821 Message::PRIORITY_NORMAL, NULL); |
600 NULL); | 822 if (pump_during_send_) |
| 823 msg->EnableMessagePumping(); |
| 824 |
601 // Temporarily set the minimum logging very high so that the assertion | 825 // Temporarily set the minimum logging very high so that the assertion |
602 // in ipc_message_utils doesn't fire. | 826 // in ipc_message_utils doesn't fire. |
603 int log_level = logging::GetMinLogLevel(); | 827 int log_level = logging::GetMinLogLevel(); |
604 logging::SetMinLogLevel(kint32max); | 828 logging::SetMinLogLevel(kint32max); |
605 bool result = Send(msg); | 829 bool result = Send(msg); |
606 logging::SetMinLogLevel(log_level); | 830 logging::SetMinLogLevel(log_level); |
607 DCHECK(!result); | 831 DCHECK(!result); |
608 | 832 |
609 // Need to send another message to get the client to call Done(). | 833 // Need to send another message to get the client to call Done(). |
610 result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 834 result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); |
611 DCHECK(result); | 835 DCHECK(result); |
612 DCHECK(answer == 42); | 836 DCHECK(answer == 42); |
613 | 837 |
614 Done(); | 838 Done(); |
615 } | 839 } |
| 840 |
| 841 bool pump_during_send_; |
616 }; | 842 }; |
617 | 843 |
| 844 void BadMessage(bool pump_during_send) { |
| 845 std::vector<Worker*> workers; |
| 846 workers.push_back(new BadServer(pump_during_send)); |
| 847 workers.push_back(new SimpleClient()); |
| 848 RunTest(workers); |
| 849 } |
| 850 |
618 } // namespace | 851 } // namespace |
619 | 852 |
620 // Tests that if a message is not serialized correctly, the Send() will fail. | 853 // Tests that if a message is not serialized correctly, the Send() will fail. |
621 TEST_F(IPCSyncChannelTest, BadMessage) { | 854 TEST_F(IPCSyncChannelTest, BadMessage) { |
622 std::vector<Worker*> workers; | 855 BadMessage(false); |
623 workers.push_back(new BadServer()); | 856 BadMessage(true); |
624 workers.push_back(new SimpleClient()); | |
625 RunTest(workers); | |
626 } | 857 } |
627 | 858 |
628 | |
629 //----------------------------------------------------------------------------- | 859 //----------------------------------------------------------------------------- |
630 | 860 |
631 namespace { | 861 namespace { |
632 | 862 |
633 class ChattyRecursiveClient : public Worker { | 863 class ChattyClient : public Worker { |
634 public: | 864 public: |
635 ChattyRecursiveClient() : | 865 ChattyClient() : |
636 Worker(Channel::MODE_CLIENT, "chatty_recursive_client") { } | 866 Worker(Channel::MODE_CLIENT, "chatty_client") { } |
637 | 867 |
638 void OnAnswer(int* answer) { | 868 void OnAnswer(int* answer) { |
639 // The PostMessage limit is 10k. Send 20% more than that. | 869 // The PostMessage limit is 10k. Send 20% more than that. |
640 const int kMessageLimit = 10000; | 870 const int kMessageLimit = 10000; |
641 const int kMessagesToSend = kMessageLimit * 120 / 100; | 871 const int kMessagesToSend = kMessageLimit * 120 / 100; |
642 for (int i = 0; i < kMessagesToSend; ++i) { | 872 for (int i = 0; i < kMessagesToSend; ++i) { |
643 bool result = Send(new SyncChannelTestMsg_Double(21, answer)); | 873 bool result = Send(new SyncChannelTestMsg_Double(21, answer)); |
644 DCHECK(result); | 874 DCHECK(result); |
645 if (!result) | 875 if (!result) |
646 break; | 876 break; |
647 } | 877 } |
648 Done(); | 878 Done(); |
649 } | 879 } |
650 }; | 880 }; |
651 | 881 |
| 882 void ChattyServer(bool pump_during_send) { |
| 883 std::vector<Worker*> workers; |
| 884 workers.push_back(new UnblockServer(pump_during_send)); |
| 885 workers.push_back(new ChattyClient()); |
| 886 RunTest(workers); |
| 887 } |
| 888 |
652 } // namespace | 889 } // namespace |
653 | 890 |
654 // Tests http://b/issue?id=1093251 - that sending lots of sync messages while | 891 // Tests http://b/issue?id=1093251 - that sending lots of sync messages while |
655 // the receiver is waiting for a sync reply does not overflow the PostMessage | 892 // the receiver is waiting for a sync reply does not overflow the PostMessage |
656 // queue. | 893 // queue. |
657 TEST_F(IPCSyncChannelTest, ChattyServer) { | 894 TEST_F(IPCSyncChannelTest, ChattyServer) { |
658 std::vector<Worker*> workers; | 895 ChattyServer(false); |
659 workers.push_back(new RecursiveServer()); | 896 ChattyServer(true); |
660 workers.push_back(new ChattyRecursiveClient()); | |
661 RunTest(workers); | |
662 } | 897 } |
663 | 898 |
664 | |
665 //------------------------------------------------------------------------------ | 899 //------------------------------------------------------------------------------ |
666 | 900 |
667 namespace { | 901 namespace { |
668 | 902 |
669 class TimeoutServer : public Worker { | 903 class TimeoutServer : public Worker { |
670 public: | 904 public: |
671 TimeoutServer(int timeout_ms, | 905 TimeoutServer(int timeout_ms, |
672 std::vector<bool> timeout_seq) | 906 std::vector<bool> timeout_seq, |
| 907 bool pump_during_send) |
673 : Worker(Channel::MODE_SERVER, "timeout_server"), | 908 : Worker(Channel::MODE_SERVER, "timeout_server"), |
674 timeout_ms_(timeout_ms), | 909 timeout_ms_(timeout_ms), |
675 timeout_seq_(timeout_seq) { | 910 timeout_seq_(timeout_seq), |
| 911 pump_during_send_(pump_during_send) { |
676 } | 912 } |
677 | 913 |
678 void Run() { | 914 void Run() { |
679 for (std::vector<bool>::const_iterator iter = timeout_seq_.begin(); | 915 for (std::vector<bool>::const_iterator iter = timeout_seq_.begin(); |
680 iter != timeout_seq_.end(); ++iter) { | 916 iter != timeout_seq_.end(); ++iter) { |
681 int answer = 0; | 917 int answer = 0; |
682 bool result = | 918 IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
683 SendWithTimeout(new SyncChannelTestMsg_AnswerToLife(&answer), | 919 if (pump_during_send_) |
684 timeout_ms_); | 920 msg->EnableMessagePumping(); |
| 921 bool result = SendWithTimeout(msg, timeout_ms_); |
685 if (*iter) { | 922 if (*iter) { |
686 // Time-out expected. | 923 // Time-out expected. |
687 DCHECK(!result); | 924 DCHECK(!result); |
688 DCHECK(answer == 0); | 925 DCHECK(answer == 0); |
689 } else { | 926 } else { |
690 DCHECK(result); | 927 DCHECK(result); |
691 DCHECK(answer == 42); | 928 DCHECK(answer == 42); |
692 } | 929 } |
693 } | 930 } |
694 Done(); | 931 Done(); |
695 } | 932 } |
696 | 933 |
697 private: | 934 private: |
698 int timeout_ms_; | 935 int timeout_ms_; |
699 std::vector<bool> timeout_seq_; | 936 std::vector<bool> timeout_seq_; |
| 937 bool pump_during_send_; |
700 }; | 938 }; |
701 | 939 |
702 class UnresponsiveClient : public Worker { | 940 class UnresponsiveClient : public Worker { |
703 public: | 941 public: |
704 UnresponsiveClient(std::vector<bool> timeout_seq) | 942 UnresponsiveClient(std::vector<bool> timeout_seq) |
705 : Worker(Channel::MODE_CLIENT, "unresponsive_client"), | 943 : Worker(Channel::MODE_CLIENT, "unresponsive_client"), |
706 timeout_seq_(timeout_seq) { | 944 timeout_seq_(timeout_seq) { |
707 } | 945 } |
708 | 946 |
709 void OnAnswerDelay(Message* reply_msg) { | 947 void OnAnswerDelay(Message* reply_msg) { |
710 DCHECK(!timeout_seq_.empty()); | 948 DCHECK(!timeout_seq_.empty()); |
711 if (!timeout_seq_[0]) { | 949 if (!timeout_seq_[0]) { |
712 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); | 950 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42); |
713 Send(reply_msg); | 951 Send(reply_msg); |
714 } else { | 952 } else { |
715 // Don't reply. | 953 // Don't reply. |
716 delete reply_msg; | 954 delete reply_msg; |
717 } | 955 } |
718 timeout_seq_.erase(timeout_seq_.begin()); | 956 timeout_seq_.erase(timeout_seq_.begin()); |
719 if (timeout_seq_.empty()) | 957 if (timeout_seq_.empty()) |
720 Done(); | 958 Done(); |
721 } | 959 } |
722 | 960 |
723 private: | 961 private: |
724 // Whether we should time-out or respond to the various messages we receive. | 962 // Whether we should time-out or respond to the various messages we receive. |
725 std::vector<bool> timeout_seq_; | 963 std::vector<bool> timeout_seq_; |
726 }; | 964 }; |
727 | 965 |
728 } // namespace | 966 void SendWithTimeoutOK(bool pump_during_send) { |
729 | |
730 // Tests that SendWithTimeout does not time-out if the response comes back fast | |
731 // enough. | |
732 TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) { | |
733 std::vector<Worker*> workers; | 967 std::vector<Worker*> workers; |
734 std::vector<bool> timeout_seq; | 968 std::vector<bool> timeout_seq; |
735 timeout_seq.push_back(false); | 969 timeout_seq.push_back(false); |
736 timeout_seq.push_back(false); | 970 timeout_seq.push_back(false); |
737 timeout_seq.push_back(false); | 971 timeout_seq.push_back(false); |
738 workers.push_back(new TimeoutServer(5000, timeout_seq)); | 972 workers.push_back(new TimeoutServer(5000, timeout_seq, pump_during_send)); |
739 workers.push_back(new SimpleClient()); | 973 workers.push_back(new SimpleClient()); |
740 RunTest(workers); | 974 RunTest(workers); |
741 } | 975 } |
742 | 976 |
743 // Tests that SendWithTimeout does time-out. | 977 void SendWithTimeoutTimeout(bool pump_during_send) { |
744 TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) { | |
745 std::vector<Worker*> workers; | 978 std::vector<Worker*> workers; |
746 std::vector<bool> timeout_seq; | 979 std::vector<bool> timeout_seq; |
747 timeout_seq.push_back(true); | 980 timeout_seq.push_back(true); |
748 timeout_seq.push_back(false); | 981 timeout_seq.push_back(false); |
749 timeout_seq.push_back(false); | 982 timeout_seq.push_back(false); |
750 workers.push_back(new TimeoutServer(100, timeout_seq)); | 983 workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send)); |
751 workers.push_back(new UnresponsiveClient(timeout_seq)); | 984 workers.push_back(new UnresponsiveClient(timeout_seq)); |
752 RunTest(workers); | 985 RunTest(workers); |
753 } | 986 } |
754 | 987 |
755 // Sends some message that time-out and some that succeed. | 988 void SendWithTimeoutMixedOKAndTimeout(bool pump_during_send) { |
756 TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) { | |
757 std::vector<Worker*> workers; | 989 std::vector<Worker*> workers; |
758 std::vector<bool> timeout_seq; | 990 std::vector<bool> timeout_seq; |
759 timeout_seq.push_back(true); | 991 timeout_seq.push_back(true); |
760 timeout_seq.push_back(false); | 992 timeout_seq.push_back(false); |
761 timeout_seq.push_back(false); | 993 timeout_seq.push_back(false); |
762 timeout_seq.push_back(true); | 994 timeout_seq.push_back(true); |
763 timeout_seq.push_back(false); | 995 timeout_seq.push_back(false); |
764 workers.push_back(new TimeoutServer(100, timeout_seq)); | 996 workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send)); |
765 workers.push_back(new UnresponsiveClient(timeout_seq)); | 997 workers.push_back(new UnresponsiveClient(timeout_seq)); |
766 RunTest(workers); | 998 RunTest(workers); |
767 } | 999 } |
| 1000 |
| 1001 } // namespace |
| 1002 |
| 1003 // Tests that SendWithTimeout does not time-out if the response comes back fast |
| 1004 // enough. |
| 1005 TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) { |
| 1006 SendWithTimeoutOK(false); |
| 1007 SendWithTimeoutOK(true); |
| 1008 } |
| 1009 |
| 1010 // Tests that SendWithTimeout does time-out. |
| 1011 TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) { |
| 1012 SendWithTimeoutTimeout(false); |
| 1013 SendWithTimeoutTimeout(true); |
| 1014 } |
| 1015 |
| 1016 // Sends some message that time-out and some that succeed. |
| 1017 TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) { |
| 1018 SendWithTimeoutMixedOKAndTimeout(false); |
| 1019 SendWithTimeoutMixedOKAndTimeout(true); |
| 1020 } |
OLD | NEW |