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