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