| 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 |