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/message_loop/message_loop_test.h" 15#include "base/pending_task.h" 16#include "base/posix/eintr_wrapper.h" 17#include "base/run_loop.h" 18#include "base/synchronization/waitable_event.h" 19#include "base/thread_task_runner_handle.h" 20#include "base/threading/platform_thread.h" 21#include "base/threading/thread.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24#if defined(OS_WIN) 25#include "base/message_loop/message_pump_win.h" 26#include "base/process/memory.h" 27#include "base/strings/string16.h" 28#include "base/win/scoped_handle.h" 29#endif 30 31namespace base { 32 33// TODO(darin): Platform-specific MessageLoop tests should be grouped together 34// to avoid chopping this file up with so many #ifdefs. 35 36namespace { 37 38MessagePump* TypeDefaultMessagePumpFactory() { 39 return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_DEFAULT); 40} 41 42MessagePump* TypeIOMessagePumpFactory() { 43 return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_IO); 44} 45 46MessagePump* TypeUIMessagePumpFactory() { 47 return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_UI); 48} 49 50class Foo : public RefCounted<Foo> { 51 public: 52 Foo() : test_count_(0) { 53 } 54 55 void Test0() { 56 ++test_count_; 57 } 58 59 void Test1ConstRef(const std::string& a) { 60 ++test_count_; 61 result_.append(a); 62 } 63 64 void Test1Ptr(std::string* a) { 65 ++test_count_; 66 result_.append(*a); 67 } 68 69 void Test1Int(int a) { 70 test_count_ += a; 71 } 72 73 void Test2Ptr(std::string* a, std::string* b) { 74 ++test_count_; 75 result_.append(*a); 76 result_.append(*b); 77 } 78 79 void Test2Mixed(const std::string& a, std::string* b) { 80 ++test_count_; 81 result_.append(a); 82 result_.append(*b); 83 } 84 85 int test_count() const { return test_count_; } 86 const std::string& result() const { return result_; } 87 88 private: 89 friend class RefCounted<Foo>; 90 91 ~Foo() {} 92 93 int test_count_; 94 std::string result_; 95}; 96 97#if defined(OS_WIN) 98 99// This function runs slowly to simulate a large amount of work being done. 100static void SlowFunc(TimeDelta pause, int* quit_counter) { 101 PlatformThread::Sleep(pause); 102 if (--(*quit_counter) == 0) 103 MessageLoop::current()->QuitWhenIdle(); 104} 105 106// This function records the time when Run was called in a Time object, which is 107// useful for building a variety of MessageLoop tests. 108static void RecordRunTimeFunc(Time* run_time, int* quit_counter) { 109 *run_time = Time::Now(); 110 111 // Cause our Run function to take some time to execute. As a result we can 112 // count on subsequent RecordRunTimeFunc()s running at a future time, 113 // without worry about the resolution of our system clock being an issue. 114 SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter); 115} 116 117void SubPumpFunc() { 118 MessageLoop::current()->SetNestableTasksAllowed(true); 119 MSG msg; 120 while (GetMessage(&msg, NULL, 0, 0)) { 121 TranslateMessage(&msg); 122 DispatchMessage(&msg); 123 } 124 MessageLoop::current()->QuitWhenIdle(); 125} 126 127void RunTest_PostDelayedTask_SharedTimer_SubPump() { 128 MessageLoop loop(MessageLoop::TYPE_UI); 129 130 // Test that the interval of the timer, used to run the next delayed task, is 131 // set to a value corresponding to when the next delayed task should run. 132 133 // By setting num_tasks to 1, we ensure that the first task to run causes the 134 // run loop to exit. 135 int num_tasks = 1; 136 Time run_time; 137 138 loop.PostTask(FROM_HERE, Bind(&SubPumpFunc)); 139 140 // This very delayed task should never run. 141 loop.PostDelayedTask( 142 FROM_HERE, 143 Bind(&RecordRunTimeFunc, &run_time, &num_tasks), 144 TimeDelta::FromSeconds(1000)); 145 146 // This slightly delayed task should run from within SubPumpFunc). 147 loop.PostDelayedTask( 148 FROM_HERE, 149 Bind(&PostQuitMessage, 0), 150 TimeDelta::FromMilliseconds(10)); 151 152 Time start_time = Time::Now(); 153 154 loop.Run(); 155 EXPECT_EQ(1, num_tasks); 156 157 // Ensure that we ran in far less time than the slower timer. 158 TimeDelta total_time = Time::Now() - start_time; 159 EXPECT_GT(5000, total_time.InMilliseconds()); 160 161 // In case both timers somehow run at nearly the same time, sleep a little 162 // and then run all pending to force them both to have run. This is just 163 // encouraging flakiness if there is any. 164 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); 165 RunLoop().RunUntilIdle(); 166 167 EXPECT_TRUE(run_time.is_null()); 168} 169 170LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) { 171 ADD_FAILURE() << "bad exception handler"; 172 ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode); 173 return EXCEPTION_EXECUTE_HANDLER; 174} 175 176// This task throws an SEH exception: initially write to an invalid address. 177// If the right SEH filter is installed, it will fix the error. 178class Crasher : public RefCounted<Crasher> { 179 public: 180 // Ctor. If trash_SEH_handler is true, the task will override the unhandled 181 // exception handler with one sure to crash this test. 182 explicit Crasher(bool trash_SEH_handler) 183 : trash_SEH_handler_(trash_SEH_handler) { 184 } 185 186 void Run() { 187 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); 188 if (trash_SEH_handler_) 189 ::SetUnhandledExceptionFilter(&BadExceptionHandler); 190 // Generate a SEH fault. We do it in asm to make sure we know how to undo 191 // the damage. 192 193#if defined(_M_IX86) 194 195 __asm { 196 mov eax, dword ptr [Crasher::bad_array_] 197 mov byte ptr [eax], 66 198 } 199 200#elif defined(_M_X64) 201 202 bad_array_[0] = 66; 203 204#else 205#error "needs architecture support" 206#endif 207 208 MessageLoop::current()->QuitWhenIdle(); 209 } 210 // Points the bad array to a valid memory location. 211 static void FixError() { 212 bad_array_ = &valid_store_; 213 } 214 215 private: 216 bool trash_SEH_handler_; 217 static volatile char* bad_array_; 218 static char valid_store_; 219}; 220 221volatile char* Crasher::bad_array_ = 0; 222char Crasher::valid_store_ = 0; 223 224// This SEH filter fixes the problem and retries execution. Fixing requires 225// that the last instruction: mov eax, [Crasher::bad_array_] to be retried 226// so we move the instruction pointer 5 bytes back. 227LONG WINAPI HandleCrasherException(EXCEPTION_POINTERS *ex_info) { 228 if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) 229 return EXCEPTION_EXECUTE_HANDLER; 230 231 Crasher::FixError(); 232 233#if defined(_M_IX86) 234 235 ex_info->ContextRecord->Eip -= 5; 236 237#elif defined(_M_X64) 238 239 ex_info->ContextRecord->Rip -= 5; 240 241#endif 242 243 return EXCEPTION_CONTINUE_EXECUTION; 244} 245 246void RunTest_Crasher(MessageLoop::Type message_loop_type) { 247 MessageLoop loop(message_loop_type); 248 249 if (::IsDebuggerPresent()) 250 return; 251 252 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = 253 ::SetUnhandledExceptionFilter(&HandleCrasherException); 254 255 MessageLoop::current()->PostTask( 256 FROM_HERE, 257 Bind(&Crasher::Run, new Crasher(false))); 258 MessageLoop::current()->set_exception_restoration(true); 259 MessageLoop::current()->Run(); 260 MessageLoop::current()->set_exception_restoration(false); 261 262 ::SetUnhandledExceptionFilter(old_SEH_filter); 263} 264 265void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) { 266 MessageLoop loop(message_loop_type); 267 268 if (::IsDebuggerPresent()) 269 return; 270 271 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = 272 ::SetUnhandledExceptionFilter(&HandleCrasherException); 273 274 MessageLoop::current()->PostTask( 275 FROM_HERE, 276 Bind(&Crasher::Run, new Crasher(true))); 277 MessageLoop::current()->set_exception_restoration(true); 278 MessageLoop::current()->Run(); 279 MessageLoop::current()->set_exception_restoration(false); 280 281 ::SetUnhandledExceptionFilter(old_SEH_filter); 282} 283 284const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test"; 285 286enum TaskType { 287 MESSAGEBOX, 288 ENDDIALOG, 289 RECURSIVE, 290 TIMEDMESSAGELOOP, 291 QUITMESSAGELOOP, 292 ORDERED, 293 PUMPS, 294 SLEEP, 295 RUNS, 296}; 297 298// Saves the order in which the tasks executed. 299struct TaskItem { 300 TaskItem(TaskType t, int c, bool s) 301 : type(t), 302 cookie(c), 303 start(s) { 304 } 305 306 TaskType type; 307 int cookie; 308 bool start; 309 310 bool operator == (const TaskItem& other) const { 311 return type == other.type && cookie == other.cookie && start == other.start; 312 } 313}; 314 315std::ostream& operator <<(std::ostream& os, TaskType type) { 316 switch (type) { 317 case MESSAGEBOX: os << "MESSAGEBOX"; break; 318 case ENDDIALOG: os << "ENDDIALOG"; break; 319 case RECURSIVE: os << "RECURSIVE"; break; 320 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; 321 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; 322 case ORDERED: os << "ORDERED"; break; 323 case PUMPS: os << "PUMPS"; break; 324 case SLEEP: os << "SLEEP"; break; 325 default: 326 NOTREACHED(); 327 os << "Unknown TaskType"; 328 break; 329 } 330 return os; 331} 332 333std::ostream& operator <<(std::ostream& os, const TaskItem& item) { 334 if (item.start) 335 return os << item.type << " " << item.cookie << " starts"; 336 else 337 return os << item.type << " " << item.cookie << " ends"; 338} 339 340class TaskList { 341 public: 342 void RecordStart(TaskType type, int cookie) { 343 TaskItem item(type, cookie, true); 344 DVLOG(1) << item; 345 task_list_.push_back(item); 346 } 347 348 void RecordEnd(TaskType type, int cookie) { 349 TaskItem item(type, cookie, false); 350 DVLOG(1) << item; 351 task_list_.push_back(item); 352 } 353 354 size_t Size() { 355 return task_list_.size(); 356 } 357 358 TaskItem Get(int n) { 359 return task_list_[n]; 360 } 361 362 private: 363 std::vector<TaskItem> task_list_; 364}; 365 366// MessageLoop implicitly start a "modal message loop". Modal dialog boxes, 367// common controls (like OpenFile) and StartDoc printing function can cause 368// implicit message loops. 369void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) { 370 order->RecordStart(MESSAGEBOX, cookie); 371 if (is_reentrant) 372 MessageLoop::current()->SetNestableTasksAllowed(true); 373 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK); 374 order->RecordEnd(MESSAGEBOX, cookie); 375} 376 377// Will end the MessageBox. 378void EndDialogFunc(TaskList* order, int cookie) { 379 order->RecordStart(ENDDIALOG, cookie); 380 HWND window = GetActiveWindow(); 381 if (window != NULL) { 382 EXPECT_NE(EndDialog(window, IDCONTINUE), 0); 383 // Cheap way to signal that the window wasn't found if RunEnd() isn't 384 // called. 385 order->RecordEnd(ENDDIALOG, cookie); 386 } 387} 388 389void RecursiveFunc(TaskList* order, int cookie, int depth, 390 bool is_reentrant) { 391 order->RecordStart(RECURSIVE, cookie); 392 if (depth > 0) { 393 if (is_reentrant) 394 MessageLoop::current()->SetNestableTasksAllowed(true); 395 MessageLoop::current()->PostTask( 396 FROM_HERE, 397 Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant)); 398 } 399 order->RecordEnd(RECURSIVE, cookie); 400} 401 402void QuitFunc(TaskList* order, int cookie) { 403 order->RecordStart(QUITMESSAGELOOP, cookie); 404 MessageLoop::current()->QuitWhenIdle(); 405 order->RecordEnd(QUITMESSAGELOOP, cookie); 406} 407 408void RecursiveFuncWin(MessageLoop* target, 409 HANDLE event, 410 bool expect_window, 411 TaskList* order, 412 bool is_reentrant) { 413 target->PostTask(FROM_HERE, 414 Bind(&RecursiveFunc, order, 1, 2, is_reentrant)); 415 target->PostTask(FROM_HERE, 416 Bind(&MessageBoxFunc, order, 2, is_reentrant)); 417 target->PostTask(FROM_HERE, 418 Bind(&RecursiveFunc, order, 3, 2, is_reentrant)); 419 // The trick here is that for recursive task processing, this task will be 420 // ran _inside_ the MessageBox message loop, dismissing the MessageBox 421 // without a chance. 422 // For non-recursive task processing, this will be executed _after_ the 423 // MessageBox will have been dismissed by the code below, where 424 // expect_window_ is true. 425 target->PostTask(FROM_HERE, 426 Bind(&EndDialogFunc, order, 4)); 427 target->PostTask(FROM_HERE, 428 Bind(&QuitFunc, order, 5)); 429 430 // Enforce that every tasks are sent before starting to run the main thread 431 // message loop. 432 ASSERT_TRUE(SetEvent(event)); 433 434 // Poll for the MessageBox. Don't do this at home! At the speed we do it, 435 // you will never realize one MessageBox was shown. 436 for (; expect_window;) { 437 HWND window = FindWindow(L"#32770", kMessageBoxTitle); 438 if (window) { 439 // Dismiss it. 440 for (;;) { 441 HWND button = FindWindowEx(window, NULL, L"Button", NULL); 442 if (button != NULL) { 443 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0)); 444 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0)); 445 break; 446 } 447 } 448 break; 449 } 450 } 451} 452 453// TODO(darin): These tests need to be ported since they test critical 454// message loop functionality. 455 456// A side effect of this test is the generation a beep. Sorry. 457void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { 458 MessageLoop loop(message_loop_type); 459 460 Thread worker("RecursiveDenial2_worker"); 461 Thread::Options options; 462 options.message_loop_type = message_loop_type; 463 ASSERT_EQ(true, worker.StartWithOptions(options)); 464 TaskList order; 465 win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 466 worker.message_loop()->PostTask(FROM_HERE, 467 Bind(&RecursiveFuncWin, 468 MessageLoop::current(), 469 event.Get(), 470 true, 471 &order, 472 false)); 473 // Let the other thread execute. 474 WaitForSingleObject(event, INFINITE); 475 MessageLoop::current()->Run(); 476 477 ASSERT_EQ(order.Size(), 17); 478 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); 479 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); 480 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); 481 EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false)); 482 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true)); 483 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false)); 484 // When EndDialogFunc is processed, the window is already dismissed, hence no 485 // "end" entry. 486 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true)); 487 EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true)); 488 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false)); 489 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true)); 490 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false)); 491 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true)); 492 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false)); 493 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true)); 494 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false)); 495 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true)); 496 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false)); 497} 498 499// A side effect of this test is the generation a beep. Sorry. This test also 500// needs to process windows messages on the current thread. 501void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { 502 MessageLoop loop(message_loop_type); 503 504 Thread worker("RecursiveSupport2_worker"); 505 Thread::Options options; 506 options.message_loop_type = message_loop_type; 507 ASSERT_EQ(true, worker.StartWithOptions(options)); 508 TaskList order; 509 win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 510 worker.message_loop()->PostTask(FROM_HERE, 511 Bind(&RecursiveFuncWin, 512 MessageLoop::current(), 513 event.Get(), 514 false, 515 &order, 516 true)); 517 // Let the other thread execute. 518 WaitForSingleObject(event, INFINITE); 519 MessageLoop::current()->Run(); 520 521 ASSERT_EQ(order.Size(), 18); 522 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); 523 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); 524 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); 525 // Note that this executes in the MessageBox modal loop. 526 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true)); 527 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false)); 528 EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true)); 529 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false)); 530 EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false)); 531 /* The order can subtly change here. The reason is that when RecursiveFunc(1) 532 is called in the main thread, if it is faster than getting to the 533 PostTask(FROM_HERE, Bind(&QuitFunc) execution, the order of task 534 execution can change. We don't care anyway that the order isn't correct. 535 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true)); 536 EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false)); 537 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); 538 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); 539 */ 540 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true)); 541 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false)); 542 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true)); 543 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false)); 544 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true)); 545 EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false)); 546} 547 548#endif // defined(OS_WIN) 549 550void PostNTasksThenQuit(int posts_remaining) { 551 if (posts_remaining > 1) { 552 MessageLoop::current()->PostTask( 553 FROM_HERE, 554 Bind(&PostNTasksThenQuit, posts_remaining - 1)); 555 } else { 556 MessageLoop::current()->QuitWhenIdle(); 557 } 558} 559 560#if defined(OS_WIN) 561 562class DispatcherImpl : public MessageLoopForUI::Dispatcher { 563 public: 564 DispatcherImpl() : dispatch_count_(0) {} 565 566 virtual bool Dispatch(const NativeEvent& msg) OVERRIDE { 567 ::TranslateMessage(&msg); 568 ::DispatchMessage(&msg); 569 // Do not count WM_TIMER since it is not what we post and it will cause 570 // flakiness. 571 if (msg.message != WM_TIMER) 572 ++dispatch_count_; 573 // We treat WM_LBUTTONUP as the last message. 574 return msg.message != WM_LBUTTONUP; 575 } 576 577 int dispatch_count_; 578}; 579 580void MouseDownUp() { 581 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); 582 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); 583} 584 585void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { 586 MessageLoop loop(message_loop_type); 587 588 MessageLoop::current()->PostDelayedTask( 589 FROM_HERE, 590 Bind(&MouseDownUp), 591 TimeDelta::FromMilliseconds(100)); 592 DispatcherImpl dispatcher; 593 RunLoop run_loop(&dispatcher); 594 run_loop.Run(); 595 ASSERT_EQ(2, dispatcher.dispatch_count_); 596} 597 598LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { 599 if (code == MessagePumpForUI::kMessageFilterCode) { 600 MSG* msg = reinterpret_cast<MSG*>(lparam); 601 if (msg->message == WM_LBUTTONDOWN) 602 return TRUE; 603 } 604 return FALSE; 605} 606 607void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { 608 MessageLoop loop(message_loop_type); 609 610 MessageLoop::current()->PostDelayedTask( 611 FROM_HERE, 612 Bind(&MouseDownUp), 613 TimeDelta::FromMilliseconds(100)); 614 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, 615 MsgFilterProc, 616 NULL, 617 GetCurrentThreadId()); 618 DispatcherImpl dispatcher; 619 RunLoop run_loop(&dispatcher); 620 run_loop.Run(); 621 ASSERT_EQ(1, dispatcher.dispatch_count_); 622 UnhookWindowsHookEx(msg_hook); 623} 624 625class TestIOHandler : public MessageLoopForIO::IOHandler { 626 public: 627 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait); 628 629 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 630 DWORD bytes_transfered, DWORD error); 631 632 void Init(); 633 void WaitForIO(); 634 OVERLAPPED* context() { return &context_.overlapped; } 635 DWORD size() { return sizeof(buffer_); } 636 637 private: 638 char buffer_[48]; 639 MessageLoopForIO::IOContext context_; 640 HANDLE signal_; 641 win::ScopedHandle file_; 642 bool wait_; 643}; 644 645TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait) 646 : signal_(signal), wait_(wait) { 647 memset(buffer_, 0, sizeof(buffer_)); 648 memset(&context_, 0, sizeof(context_)); 649 context_.handler = this; 650 651 file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 652 FILE_FLAG_OVERLAPPED, NULL)); 653 EXPECT_TRUE(file_.IsValid()); 654} 655 656void TestIOHandler::Init() { 657 MessageLoopForIO::current()->RegisterIOHandler(file_, this); 658 659 DWORD read; 660 EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context())); 661 EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); 662 if (wait_) 663 WaitForIO(); 664} 665 666void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context, 667 DWORD bytes_transfered, DWORD error) { 668 ASSERT_TRUE(context == &context_); 669 ASSERT_TRUE(SetEvent(signal_)); 670} 671 672void TestIOHandler::WaitForIO() { 673 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this)); 674 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this)); 675} 676 677void RunTest_IOHandler() { 678 win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 679 ASSERT_TRUE(callback_called.IsValid()); 680 681 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; 682 win::ScopedHandle server( 683 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 684 ASSERT_TRUE(server.IsValid()); 685 686 Thread thread("IOHandler test"); 687 Thread::Options options; 688 options.message_loop_type = MessageLoop::TYPE_IO; 689 ASSERT_TRUE(thread.StartWithOptions(options)); 690 691 MessageLoop* thread_loop = thread.message_loop(); 692 ASSERT_TRUE(NULL != thread_loop); 693 694 TestIOHandler handler(kPipeName, callback_called, false); 695 thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init, 696 Unretained(&handler))); 697 // Make sure the thread runs and sleeps for lack of work. 698 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); 699 700 const char buffer[] = "Hello there!"; 701 DWORD written; 702 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); 703 704 DWORD result = WaitForSingleObject(callback_called, 1000); 705 EXPECT_EQ(WAIT_OBJECT_0, result); 706 707 thread.Stop(); 708} 709 710void RunTest_WaitForIO() { 711 win::ScopedHandle callback1_called( 712 CreateEvent(NULL, TRUE, FALSE, NULL)); 713 win::ScopedHandle callback2_called( 714 CreateEvent(NULL, TRUE, FALSE, NULL)); 715 ASSERT_TRUE(callback1_called.IsValid()); 716 ASSERT_TRUE(callback2_called.IsValid()); 717 718 const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1"; 719 const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2"; 720 win::ScopedHandle server1( 721 CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 722 win::ScopedHandle server2( 723 CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 724 ASSERT_TRUE(server1.IsValid()); 725 ASSERT_TRUE(server2.IsValid()); 726 727 Thread thread("IOHandler test"); 728 Thread::Options options; 729 options.message_loop_type = MessageLoop::TYPE_IO; 730 ASSERT_TRUE(thread.StartWithOptions(options)); 731 732 MessageLoop* thread_loop = thread.message_loop(); 733 ASSERT_TRUE(NULL != thread_loop); 734 735 TestIOHandler handler1(kPipeName1, callback1_called, false); 736 TestIOHandler handler2(kPipeName2, callback2_called, true); 737 thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init, 738 Unretained(&handler1))); 739 // TODO(ajwong): Do we really need such long Sleeps in ths function? 740 // Make sure the thread runs and sleeps for lack of work. 741 TimeDelta delay = TimeDelta::FromMilliseconds(100); 742 PlatformThread::Sleep(delay); 743 thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init, 744 Unretained(&handler2))); 745 PlatformThread::Sleep(delay); 746 747 // At this time handler1 is waiting to be called, and the thread is waiting 748 // on the Init method of handler2, filtering only handler2 callbacks. 749 750 const char buffer[] = "Hello there!"; 751 DWORD written; 752 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); 753 PlatformThread::Sleep(2 * delay); 754 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << 755 "handler1 has not been called"; 756 757 EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL)); 758 759 HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() }; 760 DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000); 761 EXPECT_EQ(WAIT_OBJECT_0, result); 762 763 thread.Stop(); 764} 765 766#endif // defined(OS_WIN) 767 768} // namespace 769 770//----------------------------------------------------------------------------- 771// Each test is run against each type of MessageLoop. That way we are sure 772// that message loops work properly in all configurations. Of course, in some 773// cases, a unit test may only be for a particular type of loop. 774 775RUN_MESSAGE_LOOP_TESTS(Default, &TypeDefaultMessagePumpFactory); 776RUN_MESSAGE_LOOP_TESTS(UI, &TypeUIMessagePumpFactory); 777RUN_MESSAGE_LOOP_TESTS(IO, &TypeIOMessagePumpFactory); 778 779#if defined(OS_WIN) 780TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) { 781 RunTest_PostDelayedTask_SharedTimer_SubPump(); 782} 783 784TEST(MessageLoopTest, Crasher) { 785 RunTest_Crasher(MessageLoop::TYPE_DEFAULT); 786 RunTest_Crasher(MessageLoop::TYPE_UI); 787 RunTest_Crasher(MessageLoop::TYPE_IO); 788} 789 790TEST(MessageLoopTest, CrasherNasty) { 791 RunTest_CrasherNasty(MessageLoop::TYPE_DEFAULT); 792 RunTest_CrasherNasty(MessageLoop::TYPE_UI); 793 RunTest_CrasherNasty(MessageLoop::TYPE_IO); 794} 795 796// This test occasionally hangs http://crbug.com/44567 797TEST(MessageLoopTest, DISABLED_RecursiveDenial2) { 798 RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT); 799 RunTest_RecursiveDenial2(MessageLoop::TYPE_UI); 800 RunTest_RecursiveDenial2(MessageLoop::TYPE_IO); 801} 802 803TEST(MessageLoopTest, RecursiveSupport2) { 804 // This test requires a UI loop 805 RunTest_RecursiveSupport2(MessageLoop::TYPE_UI); 806} 807#endif // defined(OS_WIN) 808 809class DummyTaskObserver : public MessageLoop::TaskObserver { 810 public: 811 explicit DummyTaskObserver(int num_tasks) 812 : num_tasks_started_(0), 813 num_tasks_processed_(0), 814 num_tasks_(num_tasks) {} 815 816 virtual ~DummyTaskObserver() {} 817 818 virtual void WillProcessTask(const PendingTask& pending_task) OVERRIDE { 819 num_tasks_started_++; 820 EXPECT_TRUE(pending_task.time_posted != TimeTicks()); 821 EXPECT_LE(num_tasks_started_, num_tasks_); 822 EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1); 823 } 824 825 virtual void DidProcessTask(const PendingTask& pending_task) OVERRIDE { 826 num_tasks_processed_++; 827 EXPECT_TRUE(pending_task.time_posted != TimeTicks()); 828 EXPECT_LE(num_tasks_started_, num_tasks_); 829 EXPECT_EQ(num_tasks_started_, num_tasks_processed_); 830 } 831 832 int num_tasks_started() const { return num_tasks_started_; } 833 int num_tasks_processed() const { return num_tasks_processed_; } 834 835 private: 836 int num_tasks_started_; 837 int num_tasks_processed_; 838 const int num_tasks_; 839 840 DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver); 841}; 842 843TEST(MessageLoopTest, TaskObserver) { 844 const int kNumPosts = 6; 845 DummyTaskObserver observer(kNumPosts); 846 847 MessageLoop loop; 848 loop.AddTaskObserver(&observer); 849 loop.PostTask(FROM_HERE, Bind(&PostNTasksThenQuit, kNumPosts)); 850 loop.Run(); 851 loop.RemoveTaskObserver(&observer); 852 853 EXPECT_EQ(kNumPosts, observer.num_tasks_started()); 854 EXPECT_EQ(kNumPosts, observer.num_tasks_processed()); 855} 856 857#if defined(OS_WIN) 858TEST(MessageLoopTest, Dispatcher) { 859 // This test requires a UI loop 860 RunTest_Dispatcher(MessageLoop::TYPE_UI); 861} 862 863TEST(MessageLoopTest, DispatcherWithMessageHook) { 864 // This test requires a UI loop 865 RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI); 866} 867 868TEST(MessageLoopTest, IOHandler) { 869 RunTest_IOHandler(); 870} 871 872TEST(MessageLoopTest, WaitForIO) { 873 RunTest_WaitForIO(); 874} 875 876TEST(MessageLoopTest, HighResolutionTimer) { 877 MessageLoop loop; 878 879 const TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5); 880 const TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100); 881 882 EXPECT_FALSE(loop.IsHighResolutionTimerEnabledForTesting()); 883 884 // Post a fast task to enable the high resolution timers. 885 loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1), 886 kFastTimer); 887 loop.Run(); 888 EXPECT_TRUE(loop.IsHighResolutionTimerEnabledForTesting()); 889 890 // Post a slow task and verify high resolution timers 891 // are still enabled. 892 loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1), 893 kSlowTimer); 894 loop.Run(); 895 EXPECT_TRUE(loop.IsHighResolutionTimerEnabledForTesting()); 896 897 // Wait for a while so that high-resolution mode elapses. 898 PlatformThread::Sleep(TimeDelta::FromMilliseconds( 899 MessageLoop::kHighResolutionTimerModeLeaseTimeMs)); 900 901 // Post a slow task to disable the high resolution timers. 902 loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1), 903 kSlowTimer); 904 loop.Run(); 905 EXPECT_FALSE(loop.IsHighResolutionTimerEnabledForTesting()); 906} 907 908#endif // defined(OS_WIN) 909 910#if defined(OS_POSIX) && !defined(OS_NACL) 911 912namespace { 913 914class QuitDelegate : public MessageLoopForIO::Watcher { 915 public: 916 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE { 917 MessageLoop::current()->QuitWhenIdle(); 918 } 919 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { 920 MessageLoop::current()->QuitWhenIdle(); 921 } 922}; 923 924TEST(MessageLoopTest, FileDescriptorWatcherOutlivesMessageLoop) { 925 // Simulate a MessageLoop that dies before an FileDescriptorWatcher. 926 // This could happen when people use the Singleton pattern or atexit. 927 928 // Create a file descriptor. Doesn't need to be readable or writable, 929 // as we don't need to actually get any notifications. 930 // pipe() is just the easiest way to do it. 931 int pipefds[2]; 932 int err = pipe(pipefds); 933 ASSERT_EQ(0, err); 934 int fd = pipefds[1]; 935 { 936 // Arrange for controller to live longer than message loop. 937 MessageLoopForIO::FileDescriptorWatcher controller; 938 { 939 MessageLoopForIO message_loop; 940 941 QuitDelegate delegate; 942 message_loop.WatchFileDescriptor(fd, 943 true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate); 944 // and don't run the message loop, just destroy it. 945 } 946 } 947 if (IGNORE_EINTR(close(pipefds[0])) < 0) 948 PLOG(ERROR) << "close"; 949 if (IGNORE_EINTR(close(pipefds[1])) < 0) 950 PLOG(ERROR) << "close"; 951} 952 953TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) { 954 // Verify that it's ok to call StopWatchingFileDescriptor(). 955 // (Errors only showed up in valgrind.) 956 int pipefds[2]; 957 int err = pipe(pipefds); 958 ASSERT_EQ(0, err); 959 int fd = pipefds[1]; 960 { 961 // Arrange for message loop to live longer than controller. 962 MessageLoopForIO message_loop; 963 { 964 MessageLoopForIO::FileDescriptorWatcher controller; 965 966 QuitDelegate delegate; 967 message_loop.WatchFileDescriptor(fd, 968 true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate); 969 controller.StopWatchingFileDescriptor(); 970 } 971 } 972 if (IGNORE_EINTR(close(pipefds[0])) < 0) 973 PLOG(ERROR) << "close"; 974 if (IGNORE_EINTR(close(pipefds[1])) < 0) 975 PLOG(ERROR) << "close"; 976} 977 978} // namespace 979 980#endif // defined(OS_POSIX) && !defined(OS_NACL) 981 982namespace { 983// Inject a test point for recording the destructor calls for Closure objects 984// send to MessageLoop::PostTask(). It is awkward usage since we are trying to 985// hook the actual destruction, which is not a common operation. 986class DestructionObserverProbe : 987 public RefCounted<DestructionObserverProbe> { 988 public: 989 DestructionObserverProbe(bool* task_destroyed, 990 bool* destruction_observer_called) 991 : task_destroyed_(task_destroyed), 992 destruction_observer_called_(destruction_observer_called) { 993 } 994 virtual void Run() { 995 // This task should never run. 996 ADD_FAILURE(); 997 } 998 private: 999 friend class RefCounted<DestructionObserverProbe>; 1000 1001 virtual ~DestructionObserverProbe() { 1002 EXPECT_FALSE(*destruction_observer_called_); 1003 *task_destroyed_ = true; 1004 } 1005 1006 bool* task_destroyed_; 1007 bool* destruction_observer_called_; 1008}; 1009 1010class MLDestructionObserver : public MessageLoop::DestructionObserver { 1011 public: 1012 MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called) 1013 : task_destroyed_(task_destroyed), 1014 destruction_observer_called_(destruction_observer_called), 1015 task_destroyed_before_message_loop_(false) { 1016 } 1017 virtual void WillDestroyCurrentMessageLoop() OVERRIDE { 1018 task_destroyed_before_message_loop_ = *task_destroyed_; 1019 *destruction_observer_called_ = true; 1020 } 1021 bool task_destroyed_before_message_loop() const { 1022 return task_destroyed_before_message_loop_; 1023 } 1024 private: 1025 bool* task_destroyed_; 1026 bool* destruction_observer_called_; 1027 bool task_destroyed_before_message_loop_; 1028}; 1029 1030} // namespace 1031 1032TEST(MessageLoopTest, DestructionObserverTest) { 1033 // Verify that the destruction observer gets called at the very end (after 1034 // all the pending tasks have been destroyed). 1035 MessageLoop* loop = new MessageLoop; 1036 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); 1037 1038 bool task_destroyed = false; 1039 bool destruction_observer_called = false; 1040 1041 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called); 1042 loop->AddDestructionObserver(&observer); 1043 loop->PostDelayedTask( 1044 FROM_HERE, 1045 Bind(&DestructionObserverProbe::Run, 1046 new DestructionObserverProbe(&task_destroyed, 1047 &destruction_observer_called)), 1048 kDelay); 1049 delete loop; 1050 EXPECT_TRUE(observer.task_destroyed_before_message_loop()); 1051 // The task should have been destroyed when we deleted the loop. 1052 EXPECT_TRUE(task_destroyed); 1053 EXPECT_TRUE(destruction_observer_called); 1054} 1055 1056 1057// Verify that MessageLoop sets ThreadMainTaskRunner::current() and it 1058// posts tasks on that message loop. 1059TEST(MessageLoopTest, ThreadMainTaskRunner) { 1060 MessageLoop loop; 1061 1062 scoped_refptr<Foo> foo(new Foo()); 1063 std::string a("a"); 1064 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind( 1065 &Foo::Test1ConstRef, foo.get(), a)); 1066 1067 // Post quit task; 1068 MessageLoop::current()->PostTask(FROM_HERE, Bind( 1069 &MessageLoop::Quit, Unretained(MessageLoop::current()))); 1070 1071 // Now kick things off 1072 MessageLoop::current()->Run(); 1073 1074 EXPECT_EQ(foo->test_count(), 1); 1075 EXPECT_EQ(foo->result(), "a"); 1076} 1077 1078TEST(MessageLoopTest, IsType) { 1079 MessageLoop loop(MessageLoop::TYPE_UI); 1080 EXPECT_TRUE(loop.IsType(MessageLoop::TYPE_UI)); 1081 EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_IO)); 1082 EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT)); 1083} 1084 1085#if defined(OS_WIN) 1086void EmptyFunction() {} 1087 1088void PostMultipleTasks() { 1089 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction)); 1090 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction)); 1091} 1092 1093static const int kSignalMsg = WM_USER + 2; 1094 1095void PostWindowsMessage(HWND message_hwnd) { 1096 PostMessage(message_hwnd, kSignalMsg, 0, 2); 1097} 1098 1099void EndTest(bool* did_run, HWND hwnd) { 1100 *did_run = true; 1101 PostMessage(hwnd, WM_CLOSE, 0, 0); 1102} 1103 1104int kMyMessageFilterCode = 0x5002; 1105 1106LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message, 1107 WPARAM wparam, LPARAM lparam) { 1108 if (message == WM_CLOSE) 1109 EXPECT_TRUE(DestroyWindow(hwnd)); 1110 if (message != kSignalMsg) 1111 return DefWindowProc(hwnd, message, wparam, lparam); 1112 1113 switch (lparam) { 1114 case 1: 1115 // First, we post a task that will post multiple no-op tasks to make sure 1116 // that the pump's incoming task queue does not become empty during the 1117 // test. 1118 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&PostMultipleTasks)); 1119 // Next, we post a task that posts a windows message to trigger the second 1120 // stage of the test. 1121 MessageLoop::current()->PostTask(FROM_HERE, 1122 base::Bind(&PostWindowsMessage, hwnd)); 1123 break; 1124 case 2: 1125 // Since we're about to enter a modal loop, tell the message loop that we 1126 // intend to nest tasks. 1127 MessageLoop::current()->SetNestableTasksAllowed(true); 1128 bool did_run = false; 1129 MessageLoop::current()->PostTask(FROM_HERE, 1130 base::Bind(&EndTest, &did_run, hwnd)); 1131 // Run a nested windows-style message loop and verify that our task runs. If 1132 // it doesn't, then we'll loop here until the test times out. 1133 MSG msg; 1134 while (GetMessage(&msg, 0, 0, 0)) { 1135 if (!CallMsgFilter(&msg, kMyMessageFilterCode)) 1136 DispatchMessage(&msg); 1137 // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting 1138 // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats 1139 // WM_QUIT messages even when running inside a modal loop. 1140 if (msg.message == WM_CLOSE) 1141 break; 1142 } 1143 EXPECT_TRUE(did_run); 1144 MessageLoop::current()->Quit(); 1145 break; 1146 } 1147 return 0; 1148} 1149 1150TEST(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) { 1151 MessageLoop loop(MessageLoop::TYPE_UI); 1152 HINSTANCE instance = GetModuleFromAddress(&TestWndProcThunk); 1153 WNDCLASSEX wc = {0}; 1154 wc.cbSize = sizeof(wc); 1155 wc.lpfnWndProc = TestWndProcThunk; 1156 wc.hInstance = instance; 1157 wc.lpszClassName = L"MessageLoopTest_HWND"; 1158 ATOM atom = RegisterClassEx(&wc); 1159 ASSERT_TRUE(atom); 1160 1161 HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0, 1162 HWND_MESSAGE, 0, instance, 0); 1163 ASSERT_TRUE(message_hwnd) << GetLastError(); 1164 1165 ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1)); 1166 1167 loop.Run(); 1168 1169 ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance)); 1170} 1171#endif // defined(OS_WIN) 1172 1173} // namespace base 1174