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/memory/ref_counted.h" 10 #include "base/message_loop.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 24 using base::PlatformThread; 25 using base::Thread; 26 using base::Time; 27 using 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 32 namespace { 33 34 class MessageLoopTest : public testing::Test {}; 35 36 class 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 83 class 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 95 void 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 126 void 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. 160 class 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. 177 class 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 193 void 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 214 void 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 235 void 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 262 void 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 288 void 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 314 void 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 351 class 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 364 class SubPumpQuitTask : public Task { 365 public: 366 SubPumpQuitTask() { 367 } 368 virtual void Run() { 369 PostQuitMessage(0); 370 } 371 }; 372 373 void 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 414 class 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 430 void 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 444 void 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 460 class 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 480 LONG 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. 488 class 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 530 volatile char* CrasherTask::bad_array_ = 0; 531 char 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. 536 LONG 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 555 void 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 572 void 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 591 void 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 600 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; 601 602 enum 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. 614 struct 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 630 typedef std::vector<TaskItem> TaskList; 631 632 std::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 650 std::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. 658 class 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. 707 class 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. 727 class 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 747 class 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 771 class RecursiveSlowTask : public RecursiveTask { 772 public: 773 RecursiveSlowTask(int depth, TaskList* order, int cookie, bool is_reentrant) 774 : RecursiveTask(depth, order, cookie, is_reentrant) { 775 } 776 777 virtual void Run() { 778 RecursiveTask::Run(); 779 PlatformThread::Sleep(10); // milliseconds 780 } 781 }; 782 783 class QuitTask : public OrderedTasks { 784 public: 785 QuitTask(TaskList* order, int cookie) 786 : OrderedTasks(order, QUITMESSAGELOOP, cookie) { 787 } 788 789 virtual void Run() { 790 RunStart(); 791 MessageLoop::current()->Quit(); 792 RunEnd(); 793 } 794 }; 795 796 class SleepTask : public OrderedTasks { 797 public: 798 SleepTask(TaskList* order, int cookie, int ms) 799 : OrderedTasks(order, SLEEP, cookie), ms_(ms) { 800 } 801 802 virtual void Run() { 803 RunStart(); 804 PlatformThread::Sleep(ms_); 805 RunEnd(); 806 } 807 808 private: 809 int ms_; 810 }; 811 812 #if defined(OS_WIN) 813 814 class Recursive2Tasks : public Task { 815 public: 816 Recursive2Tasks(MessageLoop* target, 817 HANDLE event, 818 bool expect_window, 819 TaskList* order, 820 bool is_reentrant) 821 : target_(target), 822 event_(event), 823 expect_window_(expect_window), 824 order_(order), 825 is_reentrant_(is_reentrant) { 826 } 827 828 virtual void Run() { 829 target_->PostTask(FROM_HERE, 830 new RecursiveTask(2, order_, 1, is_reentrant_)); 831 target_->PostTask(FROM_HERE, 832 new MessageBoxTask(order_, 2, is_reentrant_)); 833 target_->PostTask(FROM_HERE, 834 new RecursiveTask(2, order_, 3, is_reentrant_)); 835 // The trick here is that for recursive task processing, this task will be 836 // ran _inside_ the MessageBox message loop, dismissing the MessageBox 837 // without a chance. 838 // For non-recursive task processing, this will be executed _after_ the 839 // MessageBox will have been dismissed by the code below, where 840 // expect_window_ is true. 841 target_->PostTask(FROM_HERE, new EndDialogTask(order_, 4)); 842 target_->PostTask(FROM_HERE, new QuitTask(order_, 5)); 843 844 // Enforce that every tasks are sent before starting to run the main thread 845 // message loop. 846 ASSERT_TRUE(SetEvent(event_)); 847 848 // Poll for the MessageBox. Don't do this at home! At the speed we do it, 849 // you will never realize one MessageBox was shown. 850 for (; expect_window_;) { 851 HWND window = FindWindow(L"#32770", kMessageBoxTitle); 852 if (window) { 853 // Dismiss it. 854 for (;;) { 855 HWND button = FindWindowEx(window, NULL, L"Button", NULL); 856 if (button != NULL) { 857 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0)); 858 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0)); 859 break; 860 } 861 } 862 break; 863 } 864 } 865 } 866 867 private: 868 MessageLoop* target_; 869 HANDLE event_; 870 TaskList* order_; 871 bool expect_window_; 872 bool is_reentrant_; 873 }; 874 875 #endif // defined(OS_WIN) 876 877 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) { 878 MessageLoop loop(message_loop_type); 879 880 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); 881 TaskList order; 882 MessageLoop::current()->PostTask(FROM_HERE, 883 new RecursiveTask(2, &order, 1, false)); 884 MessageLoop::current()->PostTask(FROM_HERE, 885 new RecursiveTask(2, &order, 2, false)); 886 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); 887 888 MessageLoop::current()->Run(); 889 890 // FIFO order. 891 ASSERT_EQ(14U, order.size()); 892 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 893 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 894 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 895 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 896 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 897 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 898 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); 899 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); 900 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 901 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 902 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 903 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 904 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); 905 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); 906 } 907 908 void RunTest_RecursiveDenial3(MessageLoop::Type message_loop_type) { 909 MessageLoop loop(message_loop_type); 910 911 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); 912 TaskList order; 913 MessageLoop::current()->PostTask(FROM_HERE, 914 new RecursiveSlowTask(2, &order, 1, false)); 915 MessageLoop::current()->PostTask(FROM_HERE, 916 new RecursiveSlowTask(2, &order, 2, false)); 917 MessageLoop::current()->PostDelayedTask(FROM_HERE, 918 new OrderedTasks(&order, 3), 5); 919 MessageLoop::current()->PostDelayedTask(FROM_HERE, 920 new QuitTask(&order, 4), 5); 921 922 MessageLoop::current()->Run(); 923 924 // FIFO order. 925 ASSERT_EQ(16U, order.size()); 926 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 927 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 928 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 929 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 930 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 1, true)); 931 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 1, false)); 932 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 3, true)); 933 EXPECT_EQ(order[ 7], TaskItem(ORDERERD, 3, false)); 934 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 935 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 936 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 4, true)); 937 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 4, false)); 938 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 1, true)); 939 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, false)); 940 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 2, true)); 941 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 2, false)); 942 } 943 944 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) { 945 MessageLoop loop(message_loop_type); 946 947 TaskList order; 948 MessageLoop::current()->PostTask(FROM_HERE, 949 new RecursiveTask(2, &order, 1, true)); 950 MessageLoop::current()->PostTask(FROM_HERE, 951 new RecursiveTask(2, &order, 2, true)); 952 MessageLoop::current()->PostTask(FROM_HERE, 953 new QuitTask(&order, 3)); 954 955 MessageLoop::current()->Run(); 956 957 // FIFO order. 958 ASSERT_EQ(14U, order.size()); 959 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 960 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 961 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 962 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 963 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 964 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 965 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); 966 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); 967 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 968 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 969 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 970 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 971 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); 972 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); 973 } 974 975 #if defined(OS_WIN) 976 // TODO(darin): These tests need to be ported since they test critical 977 // message loop functionality. 978 979 // A side effect of this test is the generation a beep. Sorry. 980 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { 981 MessageLoop loop(message_loop_type); 982 983 Thread worker("RecursiveDenial2_worker"); 984 Thread::Options options; 985 options.message_loop_type = message_loop_type; 986 ASSERT_EQ(true, worker.StartWithOptions(options)); 987 TaskList order; 988 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 989 worker.message_loop()->PostTask(FROM_HERE, 990 new Recursive2Tasks(MessageLoop::current(), 991 event, 992 true, 993 &order, 994 false)); 995 // Let the other thread execute. 996 WaitForSingleObject(event, INFINITE); 997 MessageLoop::current()->Run(); 998 999 ASSERT_EQ(order.size(), 17); 1000 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 1001 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 1002 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); 1003 EXPECT_EQ(order[ 3], TaskItem(MESSAGEBOX, 2, false)); 1004 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, true)); 1005 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 3, false)); 1006 // When EndDialogTask is processed, the window is already dismissed, hence no 1007 // "end" entry. 1008 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, true)); 1009 EXPECT_EQ(order[ 7], TaskItem(QUITMESSAGELOOP, 5, true)); 1010 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, false)); 1011 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 1, true)); 1012 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, false)); 1013 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 3, true)); 1014 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, false)); 1015 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, true)); 1016 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, false)); 1017 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 3, true)); 1018 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, false)); 1019 } 1020 1021 // A side effect of this test is the generation a beep. Sorry. This test also 1022 // needs to process windows messages on the current thread. 1023 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { 1024 MessageLoop loop(message_loop_type); 1025 1026 Thread worker("RecursiveSupport2_worker"); 1027 Thread::Options options; 1028 options.message_loop_type = message_loop_type; 1029 ASSERT_EQ(true, worker.StartWithOptions(options)); 1030 TaskList order; 1031 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 1032 worker.message_loop()->PostTask(FROM_HERE, 1033 new Recursive2Tasks(MessageLoop::current(), 1034 event, 1035 false, 1036 &order, 1037 true)); 1038 // Let the other thread execute. 1039 WaitForSingleObject(event, INFINITE); 1040 MessageLoop::current()->Run(); 1041 1042 ASSERT_EQ(order.size(), 18); 1043 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 1044 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 1045 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); 1046 // Note that this executes in the MessageBox modal loop. 1047 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 3, true)); 1048 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, false)); 1049 EXPECT_EQ(order[ 5], TaskItem(ENDDIALOG, 4, true)); 1050 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, false)); 1051 EXPECT_EQ(order[ 7], TaskItem(MESSAGEBOX, 2, false)); 1052 /* The order can subtly change here. The reason is that when RecursiveTask(1) 1053 is called in the main thread, if it is faster than getting to the 1054 PostTask(FROM_HERE, QuitTask) execution, the order of task execution can 1055 change. We don't care anyway that the order isn't correct. 1056 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true)); 1057 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false)); 1058 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 1059 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 1060 */ 1061 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, true)); 1062 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 3, false)); 1063 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, true)); 1064 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 1, false)); 1065 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, true)); 1066 EXPECT_EQ(order[17], TaskItem(RECURSIVE, 3, false)); 1067 } 1068 1069 #endif // defined(OS_WIN) 1070 1071 class TaskThatPumps : public OrderedTasks { 1072 public: 1073 TaskThatPumps(TaskList* order, int cookie) 1074 : OrderedTasks(order, PUMPS, cookie) { 1075 } 1076 1077 virtual void Run() { 1078 RunStart(); 1079 bool old_state = MessageLoop::current()->NestableTasksAllowed(); 1080 MessageLoop::current()->SetNestableTasksAllowed(true); 1081 MessageLoop::current()->RunAllPending(); 1082 MessageLoop::current()->SetNestableTasksAllowed(old_state); 1083 RunEnd(); 1084 } 1085 }; 1086 1087 // Tests that non nestable tasks run in FIFO if there are no nested loops. 1088 void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) { 1089 MessageLoop loop(message_loop_type); 1090 1091 TaskList order; 1092 1093 Task* task = new OrderedTasks(&order, 1); 1094 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); 1095 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 2)); 1096 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); 1097 MessageLoop::current()->Run(); 1098 1099 // FIFO order. 1100 ASSERT_EQ(6U, order.size()); 1101 EXPECT_EQ(order[ 0], TaskItem(ORDERERD, 1, true)); 1102 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 1, false)); 1103 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 2, true)); 1104 EXPECT_EQ(order[ 3], TaskItem(ORDERERD, 2, false)); 1105 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 1106 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 1107 } 1108 1109 // Tests that non nestable tasks don't run when there's code in the call stack. 1110 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, 1111 bool use_delayed) { 1112 MessageLoop loop(message_loop_type); 1113 1114 TaskList order; 1115 1116 MessageLoop::current()->PostTask(FROM_HERE, 1117 new TaskThatPumps(&order, 1)); 1118 Task* task = new OrderedTasks(&order, 2); 1119 if (use_delayed) { 1120 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1); 1121 } else { 1122 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); 1123 } 1124 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 3)); 1125 MessageLoop::current()->PostTask(FROM_HERE, new SleepTask(&order, 4, 50)); 1126 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 5)); 1127 Task* non_nestable_quit = new QuitTask(&order, 6); 1128 if (use_delayed) { 1129 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, 1130 non_nestable_quit, 1131 2); 1132 } else { 1133 MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit); 1134 } 1135 1136 MessageLoop::current()->Run(); 1137 1138 // FIFO order. 1139 ASSERT_EQ(12U, order.size()); 1140 EXPECT_EQ(order[ 0], TaskItem(PUMPS, 1, true)); 1141 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 3, true)); 1142 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 3, false)); 1143 EXPECT_EQ(order[ 3], TaskItem(SLEEP, 4, true)); 1144 EXPECT_EQ(order[ 4], TaskItem(SLEEP, 4, false)); 1145 EXPECT_EQ(order[ 5], TaskItem(ORDERERD, 5, true)); 1146 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 5, false)); 1147 EXPECT_EQ(order[ 7], TaskItem(PUMPS, 1, false)); 1148 EXPECT_EQ(order[ 8], TaskItem(ORDERERD, 2, true)); 1149 EXPECT_EQ(order[ 9], TaskItem(ORDERERD, 2, false)); 1150 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 6, true)); 1151 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 6, false)); 1152 } 1153 1154 #if defined(OS_WIN) 1155 1156 class DispatcherImpl : public MessageLoopForUI::Dispatcher { 1157 public: 1158 DispatcherImpl() : dispatch_count_(0) {} 1159 1160 virtual bool Dispatch(const MSG& msg) { 1161 ::TranslateMessage(&msg); 1162 ::DispatchMessage(&msg); 1163 // Do not count WM_TIMER since it is not what we post and it will cause 1164 // flakiness. 1165 if (msg.message != WM_TIMER) 1166 ++dispatch_count_; 1167 // We treat WM_LBUTTONUP as the last message. 1168 return msg.message != WM_LBUTTONUP; 1169 } 1170 1171 int dispatch_count_; 1172 }; 1173 1174 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { 1175 MessageLoop loop(message_loop_type); 1176 1177 class MyTask : public Task { 1178 public: 1179 virtual void Run() { 1180 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); 1181 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); 1182 } 1183 }; 1184 Task* task = new MyTask(); 1185 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); 1186 DispatcherImpl dispatcher; 1187 MessageLoopForUI::current()->Run(&dispatcher); 1188 ASSERT_EQ(2, dispatcher.dispatch_count_); 1189 } 1190 1191 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { 1192 if (code == base::MessagePumpForUI::kMessageFilterCode) { 1193 MSG* msg = reinterpret_cast<MSG*>(lparam); 1194 if (msg->message == WM_LBUTTONDOWN) 1195 return TRUE; 1196 } 1197 return FALSE; 1198 } 1199 1200 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { 1201 MessageLoop loop(message_loop_type); 1202 1203 class MyTask : public Task { 1204 public: 1205 virtual void Run() { 1206 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); 1207 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); 1208 } 1209 }; 1210 Task* task = new MyTask(); 1211 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); 1212 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, 1213 MsgFilterProc, 1214 NULL, 1215 GetCurrentThreadId()); 1216 DispatcherImpl dispatcher; 1217 MessageLoopForUI::current()->Run(&dispatcher); 1218 ASSERT_EQ(1, dispatcher.dispatch_count_); 1219 UnhookWindowsHookEx(msg_hook); 1220 } 1221 1222 class TestIOHandler : public MessageLoopForIO::IOHandler { 1223 public: 1224 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait); 1225 1226 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 1227 DWORD bytes_transfered, DWORD error); 1228 1229 void Init(); 1230 void WaitForIO(); 1231 OVERLAPPED* context() { return &context_.overlapped; } 1232 DWORD size() { return sizeof(buffer_); } 1233 1234 private: 1235 char buffer_[48]; 1236 MessageLoopForIO::IOContext context_; 1237 HANDLE signal_; 1238 base::win::ScopedHandle file_; 1239 bool wait_; 1240 }; 1241 1242 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait) 1243 : signal_(signal), wait_(wait) { 1244 memset(buffer_, 0, sizeof(buffer_)); 1245 memset(&context_, 0, sizeof(context_)); 1246 context_.handler = this; 1247 1248 file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 1249 FILE_FLAG_OVERLAPPED, NULL)); 1250 EXPECT_TRUE(file_.IsValid()); 1251 } 1252 1253 void TestIOHandler::Init() { 1254 MessageLoopForIO::current()->RegisterIOHandler(file_, this); 1255 1256 DWORD read; 1257 EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context())); 1258 EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); 1259 if (wait_) 1260 WaitForIO(); 1261 } 1262 1263 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context, 1264 DWORD bytes_transfered, DWORD error) { 1265 ASSERT_TRUE(context == &context_); 1266 ASSERT_TRUE(SetEvent(signal_)); 1267 } 1268 1269 void TestIOHandler::WaitForIO() { 1270 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this)); 1271 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this)); 1272 } 1273 1274 class IOHandlerTask : public Task { 1275 public: 1276 explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {} 1277 virtual void Run() { 1278 handler_->Init(); 1279 } 1280 1281 private: 1282 TestIOHandler* handler_; 1283 }; 1284 1285 void RunTest_IOHandler() { 1286 base::win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 1287 ASSERT_TRUE(callback_called.IsValid()); 1288 1289 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; 1290 base::win::ScopedHandle server( 1291 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 1292 ASSERT_TRUE(server.IsValid()); 1293 1294 Thread thread("IOHandler test"); 1295 Thread::Options options; 1296 options.message_loop_type = MessageLoop::TYPE_IO; 1297 ASSERT_TRUE(thread.StartWithOptions(options)); 1298 1299 MessageLoop* thread_loop = thread.message_loop(); 1300 ASSERT_TRUE(NULL != thread_loop); 1301 1302 TestIOHandler handler(kPipeName, callback_called, false); 1303 IOHandlerTask* task = new IOHandlerTask(&handler); 1304 thread_loop->PostTask(FROM_HERE, task); 1305 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1306 1307 const char buffer[] = "Hello there!"; 1308 DWORD written; 1309 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); 1310 1311 DWORD result = WaitForSingleObject(callback_called, 1000); 1312 EXPECT_EQ(WAIT_OBJECT_0, result); 1313 1314 thread.Stop(); 1315 } 1316 1317 void RunTest_WaitForIO() { 1318 base::win::ScopedHandle callback1_called( 1319 CreateEvent(NULL, TRUE, FALSE, NULL)); 1320 base::win::ScopedHandle callback2_called( 1321 CreateEvent(NULL, TRUE, FALSE, NULL)); 1322 ASSERT_TRUE(callback1_called.IsValid()); 1323 ASSERT_TRUE(callback2_called.IsValid()); 1324 1325 const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1"; 1326 const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2"; 1327 base::win::ScopedHandle server1( 1328 CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 1329 base::win::ScopedHandle server2( 1330 CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 1331 ASSERT_TRUE(server1.IsValid()); 1332 ASSERT_TRUE(server2.IsValid()); 1333 1334 Thread thread("IOHandler test"); 1335 Thread::Options options; 1336 options.message_loop_type = MessageLoop::TYPE_IO; 1337 ASSERT_TRUE(thread.StartWithOptions(options)); 1338 1339 MessageLoop* thread_loop = thread.message_loop(); 1340 ASSERT_TRUE(NULL != thread_loop); 1341 1342 TestIOHandler handler1(kPipeName1, callback1_called, false); 1343 TestIOHandler handler2(kPipeName2, callback2_called, true); 1344 IOHandlerTask* task1 = new IOHandlerTask(&handler1); 1345 IOHandlerTask* task2 = new IOHandlerTask(&handler2); 1346 thread_loop->PostTask(FROM_HERE, task1); 1347 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1348 thread_loop->PostTask(FROM_HERE, task2); 1349 Sleep(100); 1350 1351 // At this time handler1 is waiting to be called, and the thread is waiting 1352 // on the Init method of handler2, filtering only handler2 callbacks. 1353 1354 const char buffer[] = "Hello there!"; 1355 DWORD written; 1356 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); 1357 Sleep(200); 1358 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << 1359 "handler1 has not been called"; 1360 1361 EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL)); 1362 1363 HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() }; 1364 DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000); 1365 EXPECT_EQ(WAIT_OBJECT_0, result); 1366 1367 thread.Stop(); 1368 } 1369 1370 #endif // defined(OS_WIN) 1371 1372 } // namespace 1373 1374 //----------------------------------------------------------------------------- 1375 // Each test is run against each type of MessageLoop. That way we are sure 1376 // that message loops work properly in all configurations. Of course, in some 1377 // cases, a unit test may only be for a particular type of loop. 1378 1379 TEST(MessageLoopTest, PostTask) { 1380 RunTest_PostTask(MessageLoop::TYPE_DEFAULT); 1381 RunTest_PostTask(MessageLoop::TYPE_UI); 1382 RunTest_PostTask(MessageLoop::TYPE_IO); 1383 } 1384 1385 TEST(MessageLoopTest, PostTask_SEH) { 1386 RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT); 1387 RunTest_PostTask_SEH(MessageLoop::TYPE_UI); 1388 RunTest_PostTask_SEH(MessageLoop::TYPE_IO); 1389 } 1390 1391 TEST(MessageLoopTest, PostDelayedTask_Basic) { 1392 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_DEFAULT); 1393 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_UI); 1394 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_IO); 1395 } 1396 1397 TEST(MessageLoopTest, PostDelayedTask_InDelayOrder) { 1398 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_DEFAULT); 1399 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_UI); 1400 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_IO); 1401 } 1402 1403 TEST(MessageLoopTest, PostDelayedTask_InPostOrder) { 1404 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_DEFAULT); 1405 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_UI); 1406 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_IO); 1407 } 1408 1409 TEST(MessageLoopTest, PostDelayedTask_InPostOrder_2) { 1410 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_DEFAULT); 1411 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_UI); 1412 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_IO); 1413 } 1414 1415 TEST(MessageLoopTest, PostDelayedTask_InPostOrder_3) { 1416 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_DEFAULT); 1417 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_UI); 1418 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_IO); 1419 } 1420 1421 TEST(MessageLoopTest, PostDelayedTask_SharedTimer) { 1422 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_DEFAULT); 1423 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_UI); 1424 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_IO); 1425 } 1426 1427 #if defined(OS_WIN) 1428 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) { 1429 RunTest_PostDelayedTask_SharedTimer_SubPump(); 1430 } 1431 #endif 1432 1433 // TODO(darin): MessageLoop does not support deleting all tasks in the 1434 // destructor. 1435 // Fails, http://crbug.com/50272. 1436 TEST(MessageLoopTest, FAILS_EnsureTaskDeletion) { 1437 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT); 1438 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI); 1439 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO); 1440 } 1441 1442 // TODO(darin): MessageLoop does not support deleting all tasks in the 1443 // destructor. 1444 // Fails, http://crbug.com/50272. 1445 TEST(MessageLoopTest, FAILS_EnsureTaskDeletion_Chain) { 1446 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT); 1447 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI); 1448 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO); 1449 } 1450 1451 #if defined(OS_WIN) 1452 TEST(MessageLoopTest, Crasher) { 1453 RunTest_Crasher(MessageLoop::TYPE_DEFAULT); 1454 RunTest_Crasher(MessageLoop::TYPE_UI); 1455 RunTest_Crasher(MessageLoop::TYPE_IO); 1456 } 1457 1458 TEST(MessageLoopTest, CrasherNasty) { 1459 RunTest_CrasherNasty(MessageLoop::TYPE_DEFAULT); 1460 RunTest_CrasherNasty(MessageLoop::TYPE_UI); 1461 RunTest_CrasherNasty(MessageLoop::TYPE_IO); 1462 } 1463 #endif // defined(OS_WIN) 1464 1465 TEST(MessageLoopTest, Nesting) { 1466 RunTest_Nesting(MessageLoop::TYPE_DEFAULT); 1467 RunTest_Nesting(MessageLoop::TYPE_UI); 1468 RunTest_Nesting(MessageLoop::TYPE_IO); 1469 } 1470 1471 TEST(MessageLoopTest, RecursiveDenial1) { 1472 RunTest_RecursiveDenial1(MessageLoop::TYPE_DEFAULT); 1473 RunTest_RecursiveDenial1(MessageLoop::TYPE_UI); 1474 RunTest_RecursiveDenial1(MessageLoop::TYPE_IO); 1475 } 1476 1477 TEST(MessageLoopTest, RecursiveDenial3) { 1478 RunTest_RecursiveDenial3(MessageLoop::TYPE_DEFAULT); 1479 RunTest_RecursiveDenial3(MessageLoop::TYPE_UI); 1480 RunTest_RecursiveDenial3(MessageLoop::TYPE_IO); 1481 } 1482 1483 TEST(MessageLoopTest, RecursiveSupport1) { 1484 RunTest_RecursiveSupport1(MessageLoop::TYPE_DEFAULT); 1485 RunTest_RecursiveSupport1(MessageLoop::TYPE_UI); 1486 RunTest_RecursiveSupport1(MessageLoop::TYPE_IO); 1487 } 1488 1489 #if defined(OS_WIN) 1490 // This test occasionally hangs http://crbug.com/44567 1491 TEST(MessageLoopTest, DISABLED_RecursiveDenial2) { 1492 RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT); 1493 RunTest_RecursiveDenial2(MessageLoop::TYPE_UI); 1494 RunTest_RecursiveDenial2(MessageLoop::TYPE_IO); 1495 } 1496 1497 TEST(MessageLoopTest, RecursiveSupport2) { 1498 // This test requires a UI loop 1499 RunTest_RecursiveSupport2(MessageLoop::TYPE_UI); 1500 } 1501 #endif // defined(OS_WIN) 1502 1503 TEST(MessageLoopTest, NonNestableWithNoNesting) { 1504 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_DEFAULT); 1505 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_UI); 1506 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO); 1507 } 1508 1509 TEST(MessageLoopTest, NonNestableInNestedLoop) { 1510 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, false); 1511 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); 1512 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); 1513 } 1514 1515 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { 1516 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); 1517 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); 1518 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); 1519 } 1520 1521 class DummyTask : public Task { 1522 public: 1523 explicit DummyTask(int num_tasks) : num_tasks_(num_tasks) {} 1524 1525 virtual void Run() { 1526 if (num_tasks_ > 1) { 1527 MessageLoop::current()->PostTask( 1528 FROM_HERE, 1529 new DummyTask(num_tasks_ - 1)); 1530 } else { 1531 MessageLoop::current()->Quit(); 1532 } 1533 } 1534 1535 private: 1536 const int num_tasks_; 1537 }; 1538 1539 class DummyTaskObserver : public MessageLoop::TaskObserver { 1540 public: 1541 explicit DummyTaskObserver(int num_tasks) 1542 : num_tasks_started_(0), 1543 num_tasks_processed_(0), 1544 num_tasks_(num_tasks) {} 1545 1546 virtual ~DummyTaskObserver() {} 1547 1548 virtual void WillProcessTask(const Task* task) { 1549 num_tasks_started_++; 1550 EXPECT_TRUE(task != NULL); 1551 EXPECT_LE(num_tasks_started_, num_tasks_); 1552 EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1); 1553 } 1554 1555 virtual void DidProcessTask(const Task* task) { 1556 num_tasks_processed_++; 1557 EXPECT_TRUE(task != NULL); 1558 EXPECT_LE(num_tasks_started_, num_tasks_); 1559 EXPECT_EQ(num_tasks_started_, num_tasks_processed_); 1560 } 1561 1562 int num_tasks_started() const { return num_tasks_started_; } 1563 int num_tasks_processed() const { return num_tasks_processed_; } 1564 1565 private: 1566 int num_tasks_started_; 1567 int num_tasks_processed_; 1568 const int num_tasks_; 1569 1570 DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver); 1571 }; 1572 1573 TEST(MessageLoopTest, TaskObserver) { 1574 const int kNumTasks = 6; 1575 DummyTaskObserver observer(kNumTasks); 1576 1577 MessageLoop loop; 1578 loop.AddTaskObserver(&observer); 1579 loop.PostTask(FROM_HERE, new DummyTask(kNumTasks)); 1580 loop.Run(); 1581 loop.RemoveTaskObserver(&observer); 1582 1583 EXPECT_EQ(kNumTasks, observer.num_tasks_started()); 1584 EXPECT_EQ(kNumTasks, observer.num_tasks_processed()); 1585 } 1586 1587 #if defined(OS_WIN) 1588 TEST(MessageLoopTest, Dispatcher) { 1589 // This test requires a UI loop 1590 RunTest_Dispatcher(MessageLoop::TYPE_UI); 1591 } 1592 1593 TEST(MessageLoopTest, DispatcherWithMessageHook) { 1594 // This test requires a UI loop 1595 RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI); 1596 } 1597 1598 TEST(MessageLoopTest, IOHandler) { 1599 RunTest_IOHandler(); 1600 } 1601 1602 TEST(MessageLoopTest, WaitForIO) { 1603 RunTest_WaitForIO(); 1604 } 1605 1606 TEST(MessageLoopTest, HighResolutionTimer) { 1607 MessageLoop loop; 1608 1609 const int kFastTimerMs = 5; 1610 const int kSlowTimerMs = 100; 1611 1612 EXPECT_FALSE(loop.high_resolution_timers_enabled()); 1613 1614 // Post a fast task to enable the high resolution timers. 1615 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kFastTimerMs); 1616 loop.Run(); 1617 EXPECT_TRUE(loop.high_resolution_timers_enabled()); 1618 1619 // Post a slow task and verify high resolution timers 1620 // are still enabled. 1621 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs); 1622 loop.Run(); 1623 EXPECT_TRUE(loop.high_resolution_timers_enabled()); 1624 1625 // Wait for a while so that high-resolution mode elapses. 1626 Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs); 1627 1628 // Post a slow task to disable the high resolution timers. 1629 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs); 1630 loop.Run(); 1631 EXPECT_FALSE(loop.high_resolution_timers_enabled()); 1632 } 1633 1634 #endif // defined(OS_WIN) 1635 1636 #if defined(OS_POSIX) && !defined(OS_NACL) 1637 1638 namespace { 1639 1640 class QuitDelegate : public base::MessagePumpLibevent::Watcher { 1641 public: 1642 virtual void OnFileCanWriteWithoutBlocking(int fd) { 1643 MessageLoop::current()->Quit(); 1644 } 1645 virtual void OnFileCanReadWithoutBlocking(int fd) { 1646 MessageLoop::current()->Quit(); 1647 } 1648 }; 1649 1650 TEST(MessageLoopTest, FileDescriptorWatcherOutlivesMessageLoop) { 1651 // Simulate a MessageLoop that dies before an FileDescriptorWatcher. 1652 // This could happen when people use the Singleton pattern or atexit. 1653 1654 // Create a file descriptor. Doesn't need to be readable or writable, 1655 // as we don't need to actually get any notifications. 1656 // pipe() is just the easiest way to do it. 1657 int pipefds[2]; 1658 int err = pipe(pipefds); 1659 ASSERT_EQ(0, err); 1660 int fd = pipefds[1]; 1661 { 1662 // Arrange for controller to live longer than message loop. 1663 base::MessagePumpLibevent::FileDescriptorWatcher controller; 1664 { 1665 MessageLoopForIO message_loop; 1666 1667 QuitDelegate delegate; 1668 message_loop.WatchFileDescriptor(fd, 1669 true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate); 1670 // and don't run the message loop, just destroy it. 1671 } 1672 } 1673 if (HANDLE_EINTR(close(pipefds[0])) < 0) 1674 PLOG(ERROR) << "close"; 1675 if (HANDLE_EINTR(close(pipefds[1])) < 0) 1676 PLOG(ERROR) << "close"; 1677 } 1678 1679 TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) { 1680 // Verify that it's ok to call StopWatchingFileDescriptor(). 1681 // (Errors only showed up in valgrind.) 1682 int pipefds[2]; 1683 int err = pipe(pipefds); 1684 ASSERT_EQ(0, err); 1685 int fd = pipefds[1]; 1686 { 1687 // Arrange for message loop to live longer than controller. 1688 MessageLoopForIO message_loop; 1689 { 1690 base::MessagePumpLibevent::FileDescriptorWatcher controller; 1691 1692 QuitDelegate delegate; 1693 message_loop.WatchFileDescriptor(fd, 1694 true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate); 1695 controller.StopWatchingFileDescriptor(); 1696 } 1697 } 1698 if (HANDLE_EINTR(close(pipefds[0])) < 0) 1699 PLOG(ERROR) << "close"; 1700 if (HANDLE_EINTR(close(pipefds[1])) < 0) 1701 PLOG(ERROR) << "close"; 1702 } 1703 1704 } // namespace 1705 1706 #endif // defined(OS_POSIX) && !defined(OS_NACL) 1707 1708 namespace { 1709 class RunAtDestructionTask : public Task { 1710 public: 1711 RunAtDestructionTask(bool* task_destroyed, bool* destruction_observer_called) 1712 : task_destroyed_(task_destroyed), 1713 destruction_observer_called_(destruction_observer_called) { 1714 } 1715 ~RunAtDestructionTask() { 1716 EXPECT_FALSE(*destruction_observer_called_); 1717 *task_destroyed_ = true; 1718 } 1719 virtual void Run() { 1720 // This task should never run. 1721 ADD_FAILURE(); 1722 } 1723 private: 1724 bool* task_destroyed_; 1725 bool* destruction_observer_called_; 1726 }; 1727 1728 class MLDestructionObserver : public MessageLoop::DestructionObserver { 1729 public: 1730 MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called) 1731 : task_destroyed_(task_destroyed), 1732 destruction_observer_called_(destruction_observer_called), 1733 task_destroyed_before_message_loop_(false) { 1734 } 1735 virtual void WillDestroyCurrentMessageLoop() { 1736 task_destroyed_before_message_loop_ = *task_destroyed_; 1737 *destruction_observer_called_ = true; 1738 } 1739 bool task_destroyed_before_message_loop() const { 1740 return task_destroyed_before_message_loop_; 1741 } 1742 private: 1743 bool* task_destroyed_; 1744 bool* destruction_observer_called_; 1745 bool task_destroyed_before_message_loop_; 1746 }; 1747 1748 } // namespace 1749 1750 TEST(MessageLoopTest, DestructionObserverTest) { 1751 // Verify that the destruction observer gets called at the very end (after 1752 // all the pending tasks have been destroyed). 1753 MessageLoop* loop = new MessageLoop; 1754 const int kDelayMS = 100; 1755 1756 bool task_destroyed = false; 1757 bool destruction_observer_called = false; 1758 1759 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called); 1760 loop->AddDestructionObserver(&observer); 1761 loop->PostDelayedTask( 1762 FROM_HERE, 1763 new RunAtDestructionTask(&task_destroyed, &destruction_observer_called), 1764 kDelayMS); 1765 delete loop; 1766 EXPECT_TRUE(observer.task_destroyed_before_message_loop()); 1767 // The task should have been destroyed when we deleted the loop. 1768 EXPECT_TRUE(task_destroyed); 1769 EXPECT_TRUE(destruction_observer_called); 1770 } 1771