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