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