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