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 3 // found in the LICENSE file. 4 5 #include "base/logging.h" 6 #include "base/message_loop.h" 7 #include "base/platform_thread.h" 8 #include "base/ref_counted.h" 9 #include "base/thread.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 #if defined(OS_WIN) 13 #include "base/message_pump_win.h" 14 #include "base/scoped_handle.h" 15 #endif 16 #if defined(OS_POSIX) 17 #include "base/message_pump_libevent.h" 18 #endif 19 20 using base::Thread; 21 using base::Time; 22 using base::TimeDelta; 23 24 // TODO(darin): Platform-specific MessageLoop tests should be grouped together 25 // to avoid chopping this file up with so many #ifdefs. 26 27 namespace { 28 29 class MessageLoopTest : public testing::Test {}; 30 31 class Foo : public base::RefCounted<Foo> { 32 public: 33 Foo() : test_count_(0) { 34 } 35 36 void Test0() { 37 ++test_count_; 38 } 39 40 void Test1ConstRef(const std::string& a) { 41 ++test_count_; 42 result_.append(a); 43 } 44 45 void Test1Ptr(std::string* a) { 46 ++test_count_; 47 result_.append(*a); 48 } 49 50 void Test1Int(int a) { 51 test_count_ += a; 52 } 53 54 void Test2Ptr(std::string* a, std::string* b) { 55 ++test_count_; 56 result_.append(*a); 57 result_.append(*b); 58 } 59 60 void Test2Mixed(const std::string& a, std::string* b) { 61 ++test_count_; 62 result_.append(a); 63 result_.append(*b); 64 } 65 66 int test_count() const { return test_count_; } 67 const std::string& result() const { return result_; } 68 69 private: 70 friend class base::RefCounted<Foo>; 71 72 ~Foo() {} 73 74 int test_count_; 75 std::string result_; 76 }; 77 78 class QuitMsgLoop : public base::RefCounted<QuitMsgLoop> { 79 public: 80 void QuitNow() { 81 MessageLoop::current()->Quit(); 82 } 83 84 private: 85 friend class base::RefCounted<QuitMsgLoop>; 86 87 ~QuitMsgLoop() {} 88 }; 89 90 void RunTest_PostTask(MessageLoop::Type message_loop_type) { 91 MessageLoop loop(message_loop_type); 92 93 // Add tests to message loop 94 scoped_refptr<Foo> foo = new Foo(); 95 std::string a("a"), b("b"), c("c"), d("d"); 96 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 97 foo.get(), &Foo::Test0)); 98 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 99 foo.get(), &Foo::Test1ConstRef, a)); 100 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 101 foo.get(), &Foo::Test1Ptr, &b)); 102 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 103 foo.get(), &Foo::Test1Int, 100)); 104 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 105 foo.get(), &Foo::Test2Ptr, &a, &c)); 106 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 107 foo.get(), &Foo::Test2Mixed, a, &d)); 108 109 // After all tests, post a message that will shut down the message loop 110 scoped_refptr<QuitMsgLoop> quit = new QuitMsgLoop(); 111 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 112 quit.get(), &QuitMsgLoop::QuitNow)); 113 114 // Now kick things off 115 MessageLoop::current()->Run(); 116 117 EXPECT_EQ(foo->test_count(), 105); 118 EXPECT_EQ(foo->result(), "abacad"); 119 } 120 121 void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type) { 122 MessageLoop loop(message_loop_type); 123 124 // Add tests to message loop 125 scoped_refptr<Foo> foo = new Foo(); 126 std::string a("a"), b("b"), c("c"), d("d"); 127 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 128 foo.get(), &Foo::Test0)); 129 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 130 foo.get(), &Foo::Test1ConstRef, a)); 131 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 132 foo.get(), &Foo::Test1Ptr, &b)); 133 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 134 foo.get(), &Foo::Test1Int, 100)); 135 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 136 foo.get(), &Foo::Test2Ptr, &a, &c)); 137 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 138 foo.get(), &Foo::Test2Mixed, a, &d)); 139 140 // After all tests, post a message that will shut down the message loop 141 scoped_refptr<QuitMsgLoop> quit = new QuitMsgLoop(); 142 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 143 quit.get(), &QuitMsgLoop::QuitNow)); 144 145 // Now kick things off with the SEH block active. 146 MessageLoop::current()->set_exception_restoration(true); 147 MessageLoop::current()->Run(); 148 MessageLoop::current()->set_exception_restoration(false); 149 150 EXPECT_EQ(foo->test_count(), 105); 151 EXPECT_EQ(foo->result(), "abacad"); 152 } 153 154 // This class runs slowly to simulate a large amount of work being done. 155 class SlowTask : public Task { 156 public: 157 SlowTask(int pause_ms, int* quit_counter) 158 : pause_ms_(pause_ms), quit_counter_(quit_counter) { 159 } 160 virtual void Run() { 161 PlatformThread::Sleep(pause_ms_); 162 if (--(*quit_counter_) == 0) 163 MessageLoop::current()->Quit(); 164 } 165 private: 166 int pause_ms_; 167 int* quit_counter_; 168 }; 169 170 // This class records the time when Run was called in a Time object, which is 171 // useful for building a variety of MessageLoop tests. 172 class RecordRunTimeTask : public SlowTask { 173 public: 174 RecordRunTimeTask(Time* run_time, int* quit_counter) 175 : SlowTask(10, quit_counter), run_time_(run_time) { 176 } 177 virtual void Run() { 178 *run_time_ = Time::Now(); 179 // Cause our Run function to take some time to execute. As a result we can 180 // count on subsequent RecordRunTimeTask objects running at a future time, 181 // without worry about the resolution of our system clock being an issue. 182 SlowTask::Run(); 183 } 184 private: 185 Time* run_time_; 186 }; 187 188 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) { 189 MessageLoop loop(message_loop_type); 190 191 // Test that PostDelayedTask results in a delayed task. 192 193 const int kDelayMS = 100; 194 195 int num_tasks = 1; 196 Time run_time; 197 198 loop.PostDelayedTask( 199 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), kDelayMS); 200 201 Time time_before_run = Time::Now(); 202 loop.Run(); 203 Time time_after_run = Time::Now(); 204 205 EXPECT_EQ(0, num_tasks); 206 EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds()); 207 } 208 209 void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type) { 210 MessageLoop loop(message_loop_type); 211 212 // Test that two tasks with different delays run in the right order. 213 214 int num_tasks = 2; 215 Time run_time1, run_time2; 216 217 loop.PostDelayedTask( 218 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 200); 219 // If we get a large pause in execution (due to a context switch) here, this 220 // test could fail. 221 loop.PostDelayedTask( 222 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10); 223 224 loop.Run(); 225 EXPECT_EQ(0, num_tasks); 226 227 EXPECT_TRUE(run_time2 < run_time1); 228 } 229 230 void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type) { 231 MessageLoop loop(message_loop_type); 232 233 // Test that two tasks with the same delay run in the order in which they 234 // were posted. 235 // 236 // NOTE: This is actually an approximate test since the API only takes a 237 // "delay" parameter, so we are not exactly simulating two tasks that get 238 // posted at the exact same time. It would be nice if the API allowed us to 239 // specify the desired run time. 240 241 const int kDelayMS = 100; 242 243 int num_tasks = 2; 244 Time run_time1, run_time2; 245 246 loop.PostDelayedTask( 247 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), kDelayMS); 248 loop.PostDelayedTask( 249 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), kDelayMS); 250 251 loop.Run(); 252 EXPECT_EQ(0, num_tasks); 253 254 EXPECT_TRUE(run_time1 < run_time2); 255 } 256 257 void RunTest_PostDelayedTask_InPostOrder_2( 258 MessageLoop::Type message_loop_type) { 259 MessageLoop loop(message_loop_type); 260 261 // Test that a delayed task still runs after a normal tasks even if the 262 // normal tasks take a long time to run. 263 264 const int kPauseMS = 50; 265 266 int num_tasks = 2; 267 Time run_time; 268 269 loop.PostTask( 270 FROM_HERE, new SlowTask(kPauseMS, &num_tasks)); 271 loop.PostDelayedTask( 272 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 10); 273 274 Time time_before_run = Time::Now(); 275 loop.Run(); 276 Time time_after_run = Time::Now(); 277 278 EXPECT_EQ(0, num_tasks); 279 280 EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds()); 281 } 282 283 void RunTest_PostDelayedTask_InPostOrder_3( 284 MessageLoop::Type message_loop_type) { 285 MessageLoop loop(message_loop_type); 286 287 // Test that a delayed task still runs after a pile of normal tasks. The key 288 // difference between this test and the previous one is that here we return 289 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities 290 // to maybe run the delayed task. It should know not to do so until the 291 // delayed task's delay has passed. 292 293 int num_tasks = 11; 294 Time run_time1, run_time2; 295 296 // Clutter the ML with tasks. 297 for (int i = 1; i < num_tasks; ++i) 298 loop.PostTask(FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks)); 299 300 loop.PostDelayedTask( 301 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 1); 302 303 loop.Run(); 304 EXPECT_EQ(0, num_tasks); 305 306 EXPECT_TRUE(run_time2 > run_time1); 307 } 308 309 void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type) { 310 MessageLoop loop(message_loop_type); 311 312 // Test that the interval of the timer, used to run the next delayed task, is 313 // set to a value corresponding to when the next delayed task should run. 314 315 // By setting num_tasks to 1, we ensure that the first task to run causes the 316 // run loop to exit. 317 int num_tasks = 1; 318 Time run_time1, run_time2; 319 320 loop.PostDelayedTask( 321 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 1000000); 322 loop.PostDelayedTask( 323 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10); 324 325 Time start_time = Time::Now(); 326 327 loop.Run(); 328 EXPECT_EQ(0, num_tasks); 329 330 // Ensure that we ran in far less time than the slower timer. 331 TimeDelta total_time = Time::Now() - start_time; 332 EXPECT_GT(5000, total_time.InMilliseconds()); 333 334 // In case both timers somehow run at nearly the same time, sleep a little 335 // and then run all pending to force them both to have run. This is just 336 // encouraging flakiness if there is any. 337 PlatformThread::Sleep(100); 338 loop.RunAllPending(); 339 340 EXPECT_TRUE(run_time1.is_null()); 341 EXPECT_FALSE(run_time2.is_null()); 342 } 343 344 #if defined(OS_WIN) 345 346 class SubPumpTask : public Task { 347 public: 348 virtual void Run() { 349 MessageLoop::current()->SetNestableTasksAllowed(true); 350 MSG msg; 351 while (GetMessage(&msg, NULL, 0, 0)) { 352 TranslateMessage(&msg); 353 DispatchMessage(&msg); 354 } 355 MessageLoop::current()->Quit(); 356 } 357 }; 358 359 class SubPumpQuitTask : public Task { 360 public: 361 SubPumpQuitTask() { 362 } 363 virtual void Run() { 364 PostQuitMessage(0); 365 } 366 }; 367 368 void RunTest_PostDelayedTask_SharedTimer_SubPump() { 369 MessageLoop loop(MessageLoop::TYPE_UI); 370 371 // Test that the interval of the timer, used to run the next delayed task, is 372 // set to a value corresponding to when the next delayed task should run. 373 374 // By setting num_tasks to 1, we ensure that the first task to run causes the 375 // run loop to exit. 376 int num_tasks = 1; 377 Time run_time; 378 379 loop.PostTask(FROM_HERE, new SubPumpTask()); 380 381 // This very delayed task should never run. 382 loop.PostDelayedTask( 383 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 1000000); 384 385 // This slightly delayed task should run from within SubPumpTask::Run(). 386 loop.PostDelayedTask( 387 FROM_HERE, new SubPumpQuitTask(), 10); 388 389 Time start_time = Time::Now(); 390 391 loop.Run(); 392 EXPECT_EQ(1, num_tasks); 393 394 // Ensure that we ran in far less time than the slower timer. 395 TimeDelta total_time = Time::Now() - start_time; 396 EXPECT_GT(5000, total_time.InMilliseconds()); 397 398 // In case both timers somehow run at nearly the same time, sleep a little 399 // and then run all pending to force them both to have run. This is just 400 // encouraging flakiness if there is any. 401 PlatformThread::Sleep(100); 402 loop.RunAllPending(); 403 404 EXPECT_TRUE(run_time.is_null()); 405 } 406 407 #endif // defined(OS_WIN) 408 409 class RecordDeletionTask : public Task { 410 public: 411 RecordDeletionTask(Task* post_on_delete, bool* was_deleted) 412 : post_on_delete_(post_on_delete), was_deleted_(was_deleted) { 413 } 414 ~RecordDeletionTask() { 415 *was_deleted_ = true; 416 if (post_on_delete_) 417 MessageLoop::current()->PostTask(FROM_HERE, post_on_delete_); 418 } 419 virtual void Run() {} 420 private: 421 Task* post_on_delete_; 422 bool* was_deleted_; 423 }; 424 425 void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type) { 426 bool a_was_deleted = false; 427 bool b_was_deleted = false; 428 { 429 MessageLoop loop(message_loop_type); 430 loop.PostTask( 431 FROM_HERE, new RecordDeletionTask(NULL, &a_was_deleted)); 432 loop.PostDelayedTask( 433 FROM_HERE, new RecordDeletionTask(NULL, &b_was_deleted), 1000); 434 } 435 EXPECT_TRUE(a_was_deleted); 436 EXPECT_TRUE(b_was_deleted); 437 } 438 439 void RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type) { 440 bool a_was_deleted = false; 441 bool b_was_deleted = false; 442 bool c_was_deleted = false; 443 { 444 MessageLoop loop(message_loop_type); 445 RecordDeletionTask* a = new RecordDeletionTask(NULL, &a_was_deleted); 446 RecordDeletionTask* b = new RecordDeletionTask(a, &b_was_deleted); 447 RecordDeletionTask* c = new RecordDeletionTask(b, &c_was_deleted); 448 loop.PostTask(FROM_HERE, c); 449 } 450 EXPECT_TRUE(a_was_deleted); 451 EXPECT_TRUE(b_was_deleted); 452 EXPECT_TRUE(c_was_deleted); 453 } 454 455 class NestingTest : public Task { 456 public: 457 explicit NestingTest(int* depth) : depth_(depth) { 458 } 459 void Run() { 460 if (*depth_ > 0) { 461 *depth_ -= 1; 462 MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(depth_)); 463 464 MessageLoop::current()->SetNestableTasksAllowed(true); 465 MessageLoop::current()->Run(); 466 } 467 MessageLoop::current()->Quit(); 468 } 469 private: 470 int* depth_; 471 }; 472 473 #if defined(OS_WIN) 474 475 LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) { 476 ADD_FAILURE() << "bad exception handler"; 477 ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode); 478 return EXCEPTION_EXECUTE_HANDLER; 479 } 480 481 // This task throws an SEH exception: initially write to an invalid address. 482 // If the right SEH filter is installed, it will fix the error. 483 class CrasherTask : public Task { 484 public: 485 // Ctor. If trash_SEH_handler is true, the task will override the unhandled 486 // exception handler with one sure to crash this test. 487 explicit CrasherTask(bool trash_SEH_handler) 488 : trash_SEH_handler_(trash_SEH_handler) { 489 } 490 void Run() { 491 PlatformThread::Sleep(1); 492 if (trash_SEH_handler_) 493 ::SetUnhandledExceptionFilter(&BadExceptionHandler); 494 // Generate a SEH fault. We do it in asm to make sure we know how to undo 495 // the damage. 496 497 #if defined(_M_IX86) 498 499 __asm { 500 mov eax, dword ptr [CrasherTask::bad_array_] 501 mov byte ptr [eax], 66 502 } 503 504 #elif defined(_M_X64) 505 506 bad_array_[0] = 66; 507 508 #else 509 #error "needs architecture support" 510 #endif 511 512 MessageLoop::current()->Quit(); 513 } 514 // Points the bad array to a valid memory location. 515 static void FixError() { 516 bad_array_ = &valid_store_; 517 } 518 519 private: 520 bool trash_SEH_handler_; 521 static volatile char* bad_array_; 522 static char valid_store_; 523 }; 524 525 volatile char* CrasherTask::bad_array_ = 0; 526 char CrasherTask::valid_store_ = 0; 527 528 // This SEH filter fixes the problem and retries execution. Fixing requires 529 // that the last instruction: mov eax, [CrasherTask::bad_array_] to be retried 530 // so we move the instruction pointer 5 bytes back. 531 LONG WINAPI HandleCrasherTaskException(EXCEPTION_POINTERS *ex_info) { 532 if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) 533 return EXCEPTION_EXECUTE_HANDLER; 534 535 CrasherTask::FixError(); 536 537 #if defined(_M_IX86) 538 539 ex_info->ContextRecord->Eip -= 5; 540 541 #elif defined(_M_X64) 542 543 ex_info->ContextRecord->Rip -= 5; 544 545 #endif 546 547 return EXCEPTION_CONTINUE_EXECUTION; 548 } 549 550 void RunTest_Crasher(MessageLoop::Type message_loop_type) { 551 MessageLoop loop(message_loop_type); 552 553 if (::IsDebuggerPresent()) 554 return; 555 556 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = 557 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException); 558 559 MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(false)); 560 MessageLoop::current()->set_exception_restoration(true); 561 MessageLoop::current()->Run(); 562 MessageLoop::current()->set_exception_restoration(false); 563 564 ::SetUnhandledExceptionFilter(old_SEH_filter); 565 } 566 567 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) { 568 MessageLoop loop(message_loop_type); 569 570 if (::IsDebuggerPresent()) 571 return; 572 573 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = 574 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException); 575 576 MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(true)); 577 MessageLoop::current()->set_exception_restoration(true); 578 MessageLoop::current()->Run(); 579 MessageLoop::current()->set_exception_restoration(false); 580 581 ::SetUnhandledExceptionFilter(old_SEH_filter); 582 } 583 584 #endif // defined(OS_WIN) 585 586 void RunTest_Nesting(MessageLoop::Type message_loop_type) { 587 MessageLoop loop(message_loop_type); 588 589 int depth = 100; 590 MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(&depth)); 591 MessageLoop::current()->Run(); 592 EXPECT_EQ(depth, 0); 593 } 594 595 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; 596 597 enum TaskType { 598 MESSAGEBOX, 599 ENDDIALOG, 600 RECURSIVE, 601 TIMEDMESSAGELOOP, 602 QUITMESSAGELOOP, 603 ORDERERD, 604 PUMPS, 605 SLEEP, 606 }; 607 608 // Saves the order in which the tasks executed. 609 struct TaskItem { 610 TaskItem(TaskType t, int c, bool s) 611 : type(t), 612 cookie(c), 613 start(s) { 614 } 615 616 TaskType type; 617 int cookie; 618 bool start; 619 620 bool operator == (const TaskItem& other) const { 621 return type == other.type && cookie == other.cookie && start == other.start; 622 } 623 }; 624 625 typedef std::vector<TaskItem> TaskList; 626 627 std::ostream& operator <<(std::ostream& os, TaskType type) { 628 switch (type) { 629 case MESSAGEBOX: os << "MESSAGEBOX"; break; 630 case ENDDIALOG: os << "ENDDIALOG"; break; 631 case RECURSIVE: os << "RECURSIVE"; break; 632 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; 633 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; 634 case ORDERERD: os << "ORDERERD"; break; 635 case PUMPS: os << "PUMPS"; break; 636 case SLEEP: os << "SLEEP"; break; 637 default: 638 NOTREACHED(); 639 os << "Unknown TaskType"; 640 break; 641 } 642 return os; 643 } 644 645 std::ostream& operator <<(std::ostream& os, const TaskItem& item) { 646 if (item.start) 647 return os << item.type << " " << item.cookie << " starts"; 648 else 649 return os << item.type << " " << item.cookie << " ends"; 650 } 651 652 // Saves the order the tasks ran. 653 class OrderedTasks : public Task { 654 public: 655 OrderedTasks(TaskList* order, int cookie) 656 : order_(order), 657 type_(ORDERERD), 658 cookie_(cookie) { 659 } 660 OrderedTasks(TaskList* order, TaskType type, int cookie) 661 : order_(order), 662 type_(type), 663 cookie_(cookie) { 664 } 665 666 void RunStart() { 667 TaskItem item(type_, cookie_, true); 668 DLOG(INFO) << item; 669 order_->push_back(item); 670 } 671 void RunEnd() { 672 TaskItem item(type_, cookie_, false); 673 DLOG(INFO) << item; 674 order_->push_back(item); 675 } 676 677 virtual void Run() { 678 RunStart(); 679 RunEnd(); 680 } 681 682 protected: 683 TaskList* order() const { 684 return order_; 685 } 686 687 int cookie() const { 688 return cookie_; 689 } 690 691 private: 692 TaskList* order_; 693 TaskType type_; 694 int cookie_; 695 }; 696 697 #if defined(OS_WIN) 698 699 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes, 700 // common controls (like OpenFile) and StartDoc printing function can cause 701 // implicit message loops. 702 class MessageBoxTask : public OrderedTasks { 703 public: 704 MessageBoxTask(TaskList* order, int cookie, bool is_reentrant) 705 : OrderedTasks(order, MESSAGEBOX, cookie), 706 is_reentrant_(is_reentrant) { 707 } 708 709 virtual void Run() { 710 RunStart(); 711 if (is_reentrant_) 712 MessageLoop::current()->SetNestableTasksAllowed(true); 713 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK); 714 RunEnd(); 715 } 716 717 private: 718 bool is_reentrant_; 719 }; 720 721 // Will end the MessageBox. 722 class EndDialogTask : public OrderedTasks { 723 public: 724 EndDialogTask(TaskList* order, int cookie) 725 : OrderedTasks(order, ENDDIALOG, cookie) { 726 } 727 728 virtual void Run() { 729 RunStart(); 730 HWND window = GetActiveWindow(); 731 if (window != NULL) { 732 EXPECT_NE(EndDialog(window, IDCONTINUE), 0); 733 // Cheap way to signal that the window wasn't found if RunEnd() isn't 734 // called. 735 RunEnd(); 736 } 737 } 738 }; 739 740 #endif // defined(OS_WIN) 741 742 class RecursiveTask : public OrderedTasks { 743 public: 744 RecursiveTask(int depth, TaskList* order, int cookie, bool is_reentrant) 745 : OrderedTasks(order, RECURSIVE, cookie), 746 depth_(depth), 747 is_reentrant_(is_reentrant) { 748 } 749 750 virtual void Run() { 751 RunStart(); 752 if (depth_ > 0) { 753 if (is_reentrant_) 754 MessageLoop::current()->SetNestableTasksAllowed(true); 755 MessageLoop::current()->PostTask(FROM_HERE, 756 new RecursiveTask(depth_ - 1, order(), cookie(), is_reentrant_)); 757 } 758 RunEnd(); 759 } 760 761 private: 762 int depth_; 763 bool is_reentrant_; 764 }; 765 766 class QuitTask : public OrderedTasks { 767 public: 768 QuitTask(TaskList* order, int cookie) 769 : OrderedTasks(order, QUITMESSAGELOOP, cookie) { 770 } 771 772 virtual void Run() { 773 RunStart(); 774 MessageLoop::current()->Quit(); 775 RunEnd(); 776 } 777 }; 778 779 class SleepTask : public OrderedTasks { 780 public: 781 SleepTask(TaskList* order, int cookie, int ms) 782 : OrderedTasks(order, SLEEP, cookie), ms_(ms) { 783 } 784 785 virtual void Run() { 786 RunStart(); 787 PlatformThread::Sleep(ms_); 788 RunEnd(); 789 } 790 791 private: 792 int ms_; 793 }; 794 795 #if defined(OS_WIN) 796 797 class Recursive2Tasks : public Task { 798 public: 799 Recursive2Tasks(MessageLoop* target, 800 HANDLE event, 801 bool expect_window, 802 TaskList* order, 803 bool is_reentrant) 804 : target_(target), 805 event_(event), 806 expect_window_(expect_window), 807 order_(order), 808 is_reentrant_(is_reentrant) { 809 } 810 811 virtual void Run() { 812 target_->PostTask(FROM_HERE, 813 new RecursiveTask(2, order_, 1, is_reentrant_)); 814 target_->PostTask(FROM_HERE, 815 new MessageBoxTask(order_, 2, is_reentrant_)); 816 target_->PostTask(FROM_HERE, 817 new RecursiveTask(2, order_, 3, is_reentrant_)); 818 // The trick here is that for recursive task processing, this task will be 819 // ran _inside_ the MessageBox message loop, dismissing the MessageBox 820 // without a chance. 821 // For non-recursive task processing, this will be executed _after_ the 822 // MessageBox will have been dismissed by the code below, where 823 // expect_window_ is true. 824 target_->PostTask(FROM_HERE, new EndDialogTask(order_, 4)); 825 target_->PostTask(FROM_HERE, new QuitTask(order_, 5)); 826 827 // Enforce that every tasks are sent before starting to run the main thread 828 // message loop. 829 ASSERT_TRUE(SetEvent(event_)); 830 831 // Poll for the MessageBox. Don't do this at home! At the speed we do it, 832 // you will never realize one MessageBox was shown. 833 for (; expect_window_;) { 834 HWND window = FindWindow(L"#32770", kMessageBoxTitle); 835 if (window) { 836 // Dismiss it. 837 for (;;) { 838 HWND button = FindWindowEx(window, NULL, L"Button", NULL); 839 if (button != NULL) { 840 EXPECT_TRUE(0 == SendMessage(button, WM_LBUTTONDOWN, 0, 0)); 841 EXPECT_TRUE(0 == SendMessage(button, WM_LBUTTONUP, 0, 0)); 842 break; 843 } 844 } 845 break; 846 } 847 } 848 } 849 850 private: 851 MessageLoop* target_; 852 HANDLE event_; 853 TaskList* order_; 854 bool expect_window_; 855 bool is_reentrant_; 856 }; 857 858 #endif // defined(OS_WIN) 859 860 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) { 861 MessageLoop loop(message_loop_type); 862 863 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); 864 TaskList order; 865 MessageLoop::current()->PostTask(FROM_HERE, 866 new RecursiveTask(2, &order, 1, false)); 867 MessageLoop::current()->PostTask(FROM_HERE, 868 new RecursiveTask(2, &order, 2, false)); 869 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); 870 871 MessageLoop::current()->Run(); 872 873 // FIFO order. 874 ASSERT_EQ(14U, order.size()); 875 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 876 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 877 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 878 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 879 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 880 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 881 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); 882 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); 883 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 884 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 885 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 886 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 887 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); 888 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); 889 } 890 891 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) { 892 MessageLoop loop(message_loop_type); 893 894 TaskList order; 895 MessageLoop::current()->PostTask(FROM_HERE, 896 new RecursiveTask(2, &order, 1, true)); 897 MessageLoop::current()->PostTask(FROM_HERE, 898 new RecursiveTask(2, &order, 2, true)); 899 MessageLoop::current()->PostTask(FROM_HERE, 900 new QuitTask(&order, 3)); 901 902 MessageLoop::current()->Run(); 903 904 // FIFO order. 905 ASSERT_EQ(14U, order.size()); 906 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 907 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 908 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 909 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 910 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 911 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 912 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); 913 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); 914 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 915 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 916 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 917 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 918 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); 919 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); 920 } 921 922 #if defined(OS_WIN) 923 // TODO(darin): These tests need to be ported since they test critical 924 // message loop functionality. 925 926 // A side effect of this test is the generation a beep. Sorry. 927 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { 928 MessageLoop loop(message_loop_type); 929 930 Thread worker("RecursiveDenial2_worker"); 931 Thread::Options options; 932 options.message_loop_type = message_loop_type; 933 ASSERT_EQ(true, worker.StartWithOptions(options)); 934 TaskList order; 935 ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 936 worker.message_loop()->PostTask(FROM_HERE, 937 new Recursive2Tasks(MessageLoop::current(), 938 event, 939 true, 940 &order, 941 false)); 942 // Let the other thread execute. 943 WaitForSingleObject(event, INFINITE); 944 MessageLoop::current()->Run(); 945 946 ASSERT_EQ(order.size(), 17); 947 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 948 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 949 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); 950 EXPECT_EQ(order[ 3], TaskItem(MESSAGEBOX, 2, false)); 951 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, true)); 952 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 3, false)); 953 // When EndDialogTask is processed, the window is already dismissed, hence no 954 // "end" entry. 955 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, true)); 956 EXPECT_EQ(order[ 7], TaskItem(QUITMESSAGELOOP, 5, true)); 957 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, false)); 958 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 1, true)); 959 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, false)); 960 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 3, true)); 961 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, false)); 962 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, true)); 963 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, false)); 964 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 3, true)); 965 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, false)); 966 } 967 968 // A side effect of this test is the generation a beep. Sorry. This test also 969 // needs to process windows messages on the current thread. 970 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { 971 MessageLoop loop(message_loop_type); 972 973 Thread worker("RecursiveSupport2_worker"); 974 Thread::Options options; 975 options.message_loop_type = message_loop_type; 976 ASSERT_EQ(true, worker.StartWithOptions(options)); 977 TaskList order; 978 ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 979 worker.message_loop()->PostTask(FROM_HERE, 980 new Recursive2Tasks(MessageLoop::current(), 981 event, 982 false, 983 &order, 984 true)); 985 // Let the other thread execute. 986 WaitForSingleObject(event, INFINITE); 987 MessageLoop::current()->Run(); 988 989 ASSERT_EQ(order.size(), 18); 990 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 991 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 992 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); 993 // Note that this executes in the MessageBox modal loop. 994 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 3, true)); 995 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, false)); 996 EXPECT_EQ(order[ 5], TaskItem(ENDDIALOG, 4, true)); 997 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, false)); 998 EXPECT_EQ(order[ 7], TaskItem(MESSAGEBOX, 2, false)); 999 /* The order can subtly change here. The reason is that when RecursiveTask(1) 1000 is called in the main thread, if it is faster than getting to the 1001 PostTask(FROM_HERE, QuitTask) execution, the order of task execution can 1002 change. We don't care anyway that the order isn't correct. 1003 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true)); 1004 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false)); 1005 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 1006 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 1007 */ 1008 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, true)); 1009 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 3, false)); 1010 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, true)); 1011 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 1, false)); 1012 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, true)); 1013 EXPECT_EQ(order[17], TaskItem(RECURSIVE, 3, false)); 1014 } 1015 1016 #endif // defined(OS_WIN) 1017 1018 class TaskThatPumps : public OrderedTasks { 1019 public: 1020 TaskThatPumps(TaskList* order, int cookie) 1021 : OrderedTasks(order, PUMPS, cookie) { 1022 } 1023 1024 virtual void Run() { 1025 RunStart(); 1026 bool old_state = MessageLoop::current()->NestableTasksAllowed(); 1027 MessageLoop::current()->SetNestableTasksAllowed(true); 1028 MessageLoop::current()->RunAllPending(); 1029 MessageLoop::current()->SetNestableTasksAllowed(old_state); 1030 RunEnd(); 1031 } 1032 }; 1033 1034 // Tests that non nestable tasks run in FIFO if there are no nested loops. 1035 void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) { 1036 MessageLoop loop(message_loop_type); 1037 1038 TaskList order; 1039 1040 Task* task = new OrderedTasks(&order, 1); 1041 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); 1042 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 2)); 1043 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); 1044 MessageLoop::current()->Run(); 1045 1046 // FIFO order. 1047 ASSERT_EQ(6U, order.size()); 1048 EXPECT_EQ(order[ 0], TaskItem(ORDERERD, 1, true)); 1049 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 1, false)); 1050 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 2, true)); 1051 EXPECT_EQ(order[ 3], TaskItem(ORDERERD, 2, false)); 1052 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 1053 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 1054 } 1055 1056 // Tests that non nestable tasks don't run when there's code in the call stack. 1057 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, 1058 bool use_delayed) { 1059 MessageLoop loop(message_loop_type); 1060 1061 TaskList order; 1062 1063 MessageLoop::current()->PostTask(FROM_HERE, 1064 new TaskThatPumps(&order, 1)); 1065 Task* task = new OrderedTasks(&order, 2); 1066 if (use_delayed) { 1067 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1); 1068 } else { 1069 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); 1070 } 1071 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 3)); 1072 MessageLoop::current()->PostTask(FROM_HERE, new SleepTask(&order, 4, 50)); 1073 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 5)); 1074 Task* non_nestable_quit = new QuitTask(&order, 6); 1075 if (use_delayed) { 1076 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, 1077 non_nestable_quit, 1078 2); 1079 } else { 1080 MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit); 1081 } 1082 1083 MessageLoop::current()->Run(); 1084 1085 // FIFO order. 1086 ASSERT_EQ(12U, order.size()); 1087 EXPECT_EQ(order[ 0], TaskItem(PUMPS, 1, true)); 1088 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 3, true)); 1089 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 3, false)); 1090 EXPECT_EQ(order[ 3], TaskItem(SLEEP, 4, true)); 1091 EXPECT_EQ(order[ 4], TaskItem(SLEEP, 4, false)); 1092 EXPECT_EQ(order[ 5], TaskItem(ORDERERD, 5, true)); 1093 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 5, false)); 1094 EXPECT_EQ(order[ 7], TaskItem(PUMPS, 1, false)); 1095 EXPECT_EQ(order[ 8], TaskItem(ORDERERD, 2, true)); 1096 EXPECT_EQ(order[ 9], TaskItem(ORDERERD, 2, false)); 1097 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 6, true)); 1098 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 6, false)); 1099 } 1100 1101 #if defined(OS_WIN) 1102 1103 class DispatcherImpl : public MessageLoopForUI::Dispatcher { 1104 public: 1105 DispatcherImpl() : dispatch_count_(0) {} 1106 1107 virtual bool Dispatch(const MSG& msg) { 1108 ::TranslateMessage(&msg); 1109 ::DispatchMessage(&msg); 1110 // Do not count WM_TIMER since it is not what we post and it will cause 1111 // flakiness. 1112 if (msg.message != WM_TIMER) 1113 ++dispatch_count_; 1114 // We treat WM_LBUTTONUP as the last message. 1115 return msg.message != WM_LBUTTONUP; 1116 } 1117 1118 int dispatch_count_; 1119 }; 1120 1121 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { 1122 MessageLoop loop(message_loop_type); 1123 1124 class MyTask : public Task { 1125 public: 1126 virtual void Run() { 1127 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); 1128 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); 1129 } 1130 }; 1131 Task* task = new MyTask(); 1132 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); 1133 DispatcherImpl dispatcher; 1134 MessageLoopForUI::current()->Run(&dispatcher); 1135 ASSERT_EQ(2, dispatcher.dispatch_count_); 1136 } 1137 1138 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { 1139 if (code == base::MessagePumpForUI::kMessageFilterCode) { 1140 MSG* msg = reinterpret_cast<MSG*>(lparam); 1141 if (msg->message == WM_LBUTTONDOWN) 1142 return TRUE; 1143 } 1144 return FALSE; 1145 } 1146 1147 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { 1148 MessageLoop loop(message_loop_type); 1149 1150 class MyTask : public Task { 1151 public: 1152 virtual void Run() { 1153 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); 1154 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); 1155 } 1156 }; 1157 Task* task = new MyTask(); 1158 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); 1159 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, 1160 MsgFilterProc, 1161 NULL, 1162 GetCurrentThreadId()); 1163 DispatcherImpl dispatcher; 1164 MessageLoopForUI::current()->Run(&dispatcher); 1165 ASSERT_EQ(1, dispatcher.dispatch_count_); 1166 UnhookWindowsHookEx(msg_hook); 1167 } 1168 1169 class TestIOHandler : public MessageLoopForIO::IOHandler { 1170 public: 1171 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait); 1172 1173 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 1174 DWORD bytes_transfered, DWORD error); 1175 1176 void Init(); 1177 void WaitForIO(); 1178 OVERLAPPED* context() { return &context_.overlapped; } 1179 DWORD size() { return sizeof(buffer_); } 1180 1181 private: 1182 char buffer_[48]; 1183 MessageLoopForIO::IOContext context_; 1184 HANDLE signal_; 1185 ScopedHandle file_; 1186 bool wait_; 1187 }; 1188 1189 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait) 1190 : signal_(signal), wait_(wait) { 1191 memset(buffer_, 0, sizeof(buffer_)); 1192 memset(&context_, 0, sizeof(context_)); 1193 context_.handler = this; 1194 1195 file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 1196 FILE_FLAG_OVERLAPPED, NULL)); 1197 EXPECT_TRUE(file_.IsValid()); 1198 } 1199 1200 void TestIOHandler::Init() { 1201 MessageLoopForIO::current()->RegisterIOHandler(file_, this); 1202 1203 DWORD read; 1204 EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context())); 1205 EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); 1206 if (wait_) 1207 WaitForIO(); 1208 } 1209 1210 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context, 1211 DWORD bytes_transfered, DWORD error) { 1212 ASSERT_TRUE(context == &context_); 1213 ASSERT_TRUE(SetEvent(signal_)); 1214 } 1215 1216 void TestIOHandler::WaitForIO() { 1217 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this)); 1218 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this)); 1219 } 1220 1221 class IOHandlerTask : public Task { 1222 public: 1223 explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {} 1224 virtual void Run() { 1225 handler_->Init(); 1226 } 1227 1228 private: 1229 TestIOHandler* handler_; 1230 }; 1231 1232 void RunTest_IOHandler() { 1233 ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 1234 ASSERT_TRUE(callback_called.IsValid()); 1235 1236 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; 1237 ScopedHandle server(CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 1238 0, 0, 0, NULL)); 1239 ASSERT_TRUE(server.IsValid()); 1240 1241 Thread thread("IOHandler test"); 1242 Thread::Options options; 1243 options.message_loop_type = MessageLoop::TYPE_IO; 1244 ASSERT_TRUE(thread.StartWithOptions(options)); 1245 1246 MessageLoop* thread_loop = thread.message_loop(); 1247 ASSERT_TRUE(NULL != thread_loop); 1248 1249 TestIOHandler handler(kPipeName, callback_called, false); 1250 IOHandlerTask* task = new IOHandlerTask(&handler); 1251 thread_loop->PostTask(FROM_HERE, task); 1252 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1253 1254 const char buffer[] = "Hello there!"; 1255 DWORD written; 1256 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); 1257 1258 DWORD result = WaitForSingleObject(callback_called, 1000); 1259 EXPECT_EQ(WAIT_OBJECT_0, result); 1260 1261 thread.Stop(); 1262 } 1263 1264 void RunTest_WaitForIO() { 1265 ScopedHandle callback1_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 1266 ScopedHandle callback2_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 1267 ASSERT_TRUE(callback1_called.IsValid()); 1268 ASSERT_TRUE(callback2_called.IsValid()); 1269 1270 const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1"; 1271 const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2"; 1272 ScopedHandle server1(CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 1273 0, 0, 0, NULL)); 1274 ScopedHandle server2(CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 1275 0, 0, 0, NULL)); 1276 ASSERT_TRUE(server1.IsValid()); 1277 ASSERT_TRUE(server2.IsValid()); 1278 1279 Thread thread("IOHandler test"); 1280 Thread::Options options; 1281 options.message_loop_type = MessageLoop::TYPE_IO; 1282 ASSERT_TRUE(thread.StartWithOptions(options)); 1283 1284 MessageLoop* thread_loop = thread.message_loop(); 1285 ASSERT_TRUE(NULL != thread_loop); 1286 1287 TestIOHandler handler1(kPipeName1, callback1_called, false); 1288 TestIOHandler handler2(kPipeName2, callback2_called, true); 1289 IOHandlerTask* task1 = new IOHandlerTask(&handler1); 1290 IOHandlerTask* task2 = new IOHandlerTask(&handler2); 1291 thread_loop->PostTask(FROM_HERE, task1); 1292 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1293 thread_loop->PostTask(FROM_HERE, task2); 1294 Sleep(100); 1295 1296 // At this time handler1 is waiting to be called, and the thread is waiting 1297 // on the Init method of handler2, filtering only handler2 callbacks. 1298 1299 const char buffer[] = "Hello there!"; 1300 DWORD written; 1301 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); 1302 Sleep(200); 1303 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << 1304 "handler1 has not been called"; 1305 1306 EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL)); 1307 1308 HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() }; 1309 DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000); 1310 EXPECT_EQ(WAIT_OBJECT_0, result); 1311 1312 thread.Stop(); 1313 } 1314 1315 #endif // defined(OS_WIN) 1316 1317 } // namespace 1318 1319 //----------------------------------------------------------------------------- 1320 // Each test is run against each type of MessageLoop. That way we are sure 1321 // that message loops work properly in all configurations. Of course, in some 1322 // cases, a unit test may only be for a particular type of loop. 1323 1324 TEST(MessageLoopTest, PostTask) { 1325 RunTest_PostTask(MessageLoop::TYPE_DEFAULT); 1326 RunTest_PostTask(MessageLoop::TYPE_UI); 1327 RunTest_PostTask(MessageLoop::TYPE_IO); 1328 } 1329 1330 TEST(MessageLoopTest, PostTask_SEH) { 1331 RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT); 1332 RunTest_PostTask_SEH(MessageLoop::TYPE_UI); 1333 RunTest_PostTask_SEH(MessageLoop::TYPE_IO); 1334 } 1335 1336 TEST(MessageLoopTest, PostDelayedTask_Basic) { 1337 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_DEFAULT); 1338 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_UI); 1339 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_IO); 1340 } 1341 1342 TEST(MessageLoopTest, PostDelayedTask_InDelayOrder) { 1343 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_DEFAULT); 1344 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_UI); 1345 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_IO); 1346 } 1347 1348 TEST(MessageLoopTest, PostDelayedTask_InPostOrder) { 1349 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_DEFAULT); 1350 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_UI); 1351 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_IO); 1352 } 1353 1354 TEST(MessageLoopTest, PostDelayedTask_InPostOrder_2) { 1355 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_DEFAULT); 1356 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_UI); 1357 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_IO); 1358 } 1359 1360 TEST(MessageLoopTest, PostDelayedTask_InPostOrder_3) { 1361 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_DEFAULT); 1362 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_UI); 1363 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_IO); 1364 } 1365 1366 TEST(MessageLoopTest, PostDelayedTask_SharedTimer) { 1367 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_DEFAULT); 1368 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_UI); 1369 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_IO); 1370 } 1371 1372 #if defined(OS_WIN) 1373 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) { 1374 RunTest_PostDelayedTask_SharedTimer_SubPump(); 1375 } 1376 #endif 1377 1378 // TODO(darin): re-enable these tests once MessageLoop supports them again. 1379 #if 0 1380 TEST(MessageLoopTest, EnsureTaskDeletion) { 1381 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT); 1382 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI); 1383 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO); 1384 } 1385 1386 TEST(MessageLoopTest, EnsureTaskDeletion_Chain) { 1387 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT); 1388 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI); 1389 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO); 1390 } 1391 #endif 1392 1393 #if defined(OS_WIN) 1394 TEST(MessageLoopTest, Crasher) { 1395 RunTest_Crasher(MessageLoop::TYPE_DEFAULT); 1396 RunTest_Crasher(MessageLoop::TYPE_UI); 1397 RunTest_Crasher(MessageLoop::TYPE_IO); 1398 } 1399 1400 TEST(MessageLoopTest, CrasherNasty) { 1401 RunTest_CrasherNasty(MessageLoop::TYPE_DEFAULT); 1402 RunTest_CrasherNasty(MessageLoop::TYPE_UI); 1403 RunTest_CrasherNasty(MessageLoop::TYPE_IO); 1404 } 1405 #endif // defined(OS_WIN) 1406 1407 TEST(MessageLoopTest, Nesting) { 1408 RunTest_Nesting(MessageLoop::TYPE_DEFAULT); 1409 RunTest_Nesting(MessageLoop::TYPE_UI); 1410 RunTest_Nesting(MessageLoop::TYPE_IO); 1411 } 1412 1413 TEST(MessageLoopTest, RecursiveDenial1) { 1414 RunTest_RecursiveDenial1(MessageLoop::TYPE_DEFAULT); 1415 RunTest_RecursiveDenial1(MessageLoop::TYPE_UI); 1416 RunTest_RecursiveDenial1(MessageLoop::TYPE_IO); 1417 } 1418 1419 TEST(MessageLoopTest, RecursiveSupport1) { 1420 RunTest_RecursiveSupport1(MessageLoop::TYPE_DEFAULT); 1421 RunTest_RecursiveSupport1(MessageLoop::TYPE_UI); 1422 RunTest_RecursiveSupport1(MessageLoop::TYPE_IO); 1423 } 1424 1425 #if defined(OS_WIN) 1426 TEST(MessageLoopTest, RecursiveDenial2) { 1427 RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT); 1428 RunTest_RecursiveDenial2(MessageLoop::TYPE_UI); 1429 RunTest_RecursiveDenial2(MessageLoop::TYPE_IO); 1430 } 1431 1432 TEST(MessageLoopTest, RecursiveSupport2) { 1433 // This test requires a UI loop 1434 RunTest_RecursiveSupport2(MessageLoop::TYPE_UI); 1435 } 1436 #endif // defined(OS_WIN) 1437 1438 TEST(MessageLoopTest, NonNestableWithNoNesting) { 1439 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_DEFAULT); 1440 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_UI); 1441 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO); 1442 } 1443 1444 TEST(MessageLoopTest, NonNestableInNestedLoop) { 1445 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, false); 1446 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); 1447 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); 1448 } 1449 1450 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { 1451 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); 1452 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); 1453 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); 1454 } 1455 1456 #if defined(OS_WIN) 1457 TEST(MessageLoopTest, Dispatcher) { 1458 // This test requires a UI loop 1459 RunTest_Dispatcher(MessageLoop::TYPE_UI); 1460 } 1461 1462 TEST(MessageLoopTest, DispatcherWithMessageHook) { 1463 // This test requires a UI loop 1464 RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI); 1465 } 1466 1467 TEST(MessageLoopTest, IOHandler) { 1468 RunTest_IOHandler(); 1469 } 1470 1471 TEST(MessageLoopTest, WaitForIO) { 1472 RunTest_WaitForIO(); 1473 } 1474 #endif // defined(OS_WIN) 1475 1476 #if defined(OS_POSIX) 1477 1478 namespace { 1479 1480 class QuitDelegate : public 1481 base::MessagePumpLibevent::Watcher { 1482 public: 1483 virtual void OnFileCanWriteWithoutBlocking(int fd) { 1484 MessageLoop::current()->Quit(); 1485 } 1486 virtual void OnFileCanReadWithoutBlocking(int fd) { 1487 MessageLoop::current()->Quit(); 1488 } 1489 }; 1490 1491 } // namespace 1492 1493 TEST(MessageLoopTest, DISABLED_FileDescriptorWatcherOutlivesMessageLoop) { 1494 // Simulate a MessageLoop that dies before an FileDescriptorWatcher. 1495 // This could happen when people use the Singleton pattern or atexit. 1496 // This is disabled for now because it fails (valgrind shows 1497 // invalid reads), and it's not clear any code relies on this... 1498 // TODO(dkegel): enable if it turns out we rely on this 1499 1500 // Create a file descriptor. Doesn't need to be readable or writable, 1501 // as we don't need to actually get any notifications. 1502 // pipe() is just the easiest way to do it. 1503 int pipefds[2]; 1504 int err = pipe(pipefds); 1505 ASSERT_TRUE(err == 0); 1506 int fd = pipefds[1]; 1507 { 1508 // Arrange for controller to live longer than message loop. 1509 base::MessagePumpLibevent::FileDescriptorWatcher controller; 1510 { 1511 MessageLoopForIO message_loop; 1512 1513 QuitDelegate delegate; 1514 message_loop.WatchFileDescriptor(fd, 1515 true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate); 1516 // and don't run the message loop, just destroy it. 1517 } 1518 } 1519 close(pipefds[0]); 1520 close(pipefds[1]); 1521 } 1522 1523 TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) { 1524 // Verify that it's ok to call StopWatchingFileDescriptor(). 1525 // (Errors only showed up in valgrind.) 1526 int pipefds[2]; 1527 int err = pipe(pipefds); 1528 ASSERT_TRUE(err == 0); 1529 int fd = pipefds[1]; 1530 { 1531 // Arrange for message loop to live longer than controller. 1532 MessageLoopForIO message_loop; 1533 { 1534 base::MessagePumpLibevent::FileDescriptorWatcher controller; 1535 1536 QuitDelegate delegate; 1537 message_loop.WatchFileDescriptor(fd, 1538 true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate); 1539 controller.StopWatchingFileDescriptor(); 1540 } 1541 } 1542 close(pipefds[0]); 1543 close(pipefds[1]); 1544 } 1545 1546 #endif // defined(OS_POSIX) 1547