• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 namespace 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 
43 namespace {
44 
TypeDefaultMessagePumpFactory()45 std::unique_ptr<MessagePump> TypeDefaultMessagePumpFactory() {
46   return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_DEFAULT);
47 }
48 
TypeIOMessagePumpFactory()49 std::unique_ptr<MessagePump> TypeIOMessagePumpFactory() {
50   return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_IO);
51 }
52 
TypeUIMessagePumpFactory()53 std::unique_ptr<MessagePump> TypeUIMessagePumpFactory() {
54   return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_UI);
55 }
56 
57 class Foo : public RefCounted<Foo> {
58  public:
Foo()59   Foo() : test_count_(0) {
60   }
61 
Test1ConstRef(const std::string & a)62   void Test1ConstRef(const std::string& a) {
63     ++test_count_;
64     result_.append(a);
65   }
66 
test_count() const67   int test_count() const { return test_count_; }
result() const68   const std::string& result() const { return result_; }
69 
70  private:
71   friend class RefCounted<Foo>;
72 
~Foo()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.
SlowFunc(TimeDelta pause,int * quit_counter)82 static 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.
RecordRunTimeFunc(Time * run_time,int * quit_counter)90 static 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 
SubPumpFunc()99 void 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 
RunTest_PostDelayedTask_SharedTimer_SubPump()109 void 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 
152 const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test";
153 
154 enum 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.
167 struct TaskItem {
TaskItembase::__anona43c38fc0111::TaskItem168   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 
operator ==base::__anona43c38fc0111::TaskItem178   bool operator == (const TaskItem& other) const {
179     return type == other.type && cookie == other.cookie && start == other.start;
180   }
181 };
182 
operator <<(std::ostream & os,TaskType type)183 std::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 
operator <<(std::ostream & os,const TaskItem & item)201 std::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 
208 class TaskList {
209  public:
RecordStart(TaskType type,int cookie)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 
RecordEnd(TaskType type,int cookie)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 
Size()222   size_t Size() {
223     return task_list_.size();
224   }
225 
Get(int n)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.
MessageBoxFunc(TaskList * order,int cookie,bool is_reentrant)237 void 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.
EndDialogFunc(TaskList * order,int cookie)246 void 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 
RecursiveFunc(TaskList * order,int cookie,int depth,bool is_reentrant)257 void 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 
QuitFunc(TaskList * order,int cookie)270 void QuitFunc(TaskList* order, int cookie) {
271   order->RecordStart(QUITMESSAGELOOP, cookie);
272   MessageLoop::current()->QuitWhenIdle();
273   order->RecordEnd(QUITMESSAGELOOP, cookie);
274 }
275 
RecursiveFuncWin(MessageLoop * target,HANDLE event,bool expect_window,TaskList * order,bool is_reentrant)276 void 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.
RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type)325 void 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.
RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type)369 void 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 
PostNTasksThenQuit(int posts_remaining)418 void 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 
429 class 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();
context()439   OVERLAPPED* context() { return &context_.overlapped; }
size()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 
TestIOHandler(const wchar_t * name,HANDLE signal,bool wait)450 TestIOHandler::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 
Init()459 void 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 
OnIOCompleted(MessageLoopForIO::IOContext * context,DWORD bytes_transfered,DWORD error)469 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
470                                   DWORD bytes_transfered, DWORD error) {
471   ASSERT_TRUE(context == &context_);
472   ASSERT_TRUE(SetEvent(signal_));
473 }
474 
WaitForIO()475 void TestIOHandler::WaitForIO() {
476   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
477   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
478 }
479 
RunTest_IOHandler()480 void 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 
RunTest_WaitForIO()513 void 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 
579 RUN_MESSAGE_LOOP_TESTS(Default, &TypeDefaultMessagePumpFactory);
580 RUN_MESSAGE_LOOP_TESTS(UI, &TypeUIMessagePumpFactory);
581 RUN_MESSAGE_LOOP_TESTS(IO, &TypeIOMessagePumpFactory);
582 
583 #if defined(OS_WIN)
584 // Additional set of tests for GPU version of UI message loop.
585 RUN_MESSAGE_LOOP_TESTS(GPU, &MessagePumpForGpu::CreateMessagePumpForGpu);
586 
TEST(MessageLoopTest,PostDelayedTask_SharedTimer_SubPump)587 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
588   RunTest_PostDelayedTask_SharedTimer_SubPump();
589 }
590 
591 // This test occasionally hangs. See http://crbug.com/44567.
TEST(MessageLoopTest,DISABLED_RecursiveDenial2)592 TEST(MessageLoopTest, DISABLED_RecursiveDenial2) {
593   RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
594   RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
595   RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
596 }
597 
TEST(MessageLoopTest,RecursiveSupport2)598 TEST(MessageLoopTest, RecursiveSupport2) {
599   // This test requires a UI loop.
600   RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
601 }
602 #endif  // defined(OS_WIN)
603 
604 class DummyTaskObserver : public MessageLoop::TaskObserver {
605  public:
DummyTaskObserver(int num_tasks)606   explicit DummyTaskObserver(int num_tasks)
607       : num_tasks_started_(0),
608         num_tasks_processed_(0),
609         num_tasks_(num_tasks) {}
610 
~DummyTaskObserver()611   ~DummyTaskObserver() override {}
612 
WillProcessTask(const PendingTask & pending_task)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 
DidProcessTask(const PendingTask & pending_task)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 
num_tasks_started() const625   int num_tasks_started() const { return num_tasks_started_; }
num_tasks_processed() const626   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 
TEST(MessageLoopTest,TaskObserver)636 TEST(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)
TEST(MessageLoopTest,IOHandler)651 TEST(MessageLoopTest, IOHandler) {
652   RunTest_IOHandler();
653 }
654 
TEST(MessageLoopTest,WaitForIO)655 TEST(MessageLoopTest, WaitForIO) {
656   RunTest_WaitForIO();
657 }
658 
TEST(MessageLoopTest,HighResolutionTimer)659 TEST(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 
687 namespace {
688 
689 class QuitDelegate : public MessageLoopForIO::Watcher {
690  public:
OnFileCanWriteWithoutBlocking(int fd)691   void OnFileCanWriteWithoutBlocking(int fd) override {
692     MessageLoop::current()->QuitWhenIdle();
693   }
OnFileCanReadWithoutBlocking(int fd)694   void OnFileCanReadWithoutBlocking(int fd) override {
695     MessageLoop::current()->QuitWhenIdle();
696   }
697 };
698 
TEST(MessageLoopTest,FileDescriptorWatcherOutlivesMessageLoop)699 TEST(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 
TEST(MessageLoopTest,FileDescriptorWatcherDoubleStop)728 TEST(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 
757 namespace {
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.
761 class DestructionObserverProbe :
762   public RefCounted<DestructionObserverProbe> {
763  public:
DestructionObserverProbe(bool * task_destroyed,bool * destruction_observer_called)764   DestructionObserverProbe(bool* task_destroyed,
765                            bool* destruction_observer_called)
766       : task_destroyed_(task_destroyed),
767         destruction_observer_called_(destruction_observer_called) {
768   }
Run()769   virtual void Run() {
770     // This task should never run.
771     ADD_FAILURE();
772   }
773  private:
774   friend class RefCounted<DestructionObserverProbe>;
775 
~DestructionObserverProbe()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 
785 class MLDestructionObserver : public MessageLoop::DestructionObserver {
786  public:
MLDestructionObserver(bool * task_destroyed,bool * destruction_observer_called)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   }
WillDestroyCurrentMessageLoop()792   void WillDestroyCurrentMessageLoop() override {
793     task_destroyed_before_message_loop_ = *task_destroyed_;
794     *destruction_observer_called_ = true;
795   }
task_destroyed_before_message_loop() const796   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 
TEST(MessageLoopTest,DestructionObserverTest)807 TEST(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.
TEST(MessageLoopTest,ThreadMainTaskRunner)833 TEST(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 
TEST(MessageLoopTest,IsType)853 TEST(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)
EmptyFunction()861 void EmptyFunction() {}
862 
PostMultipleTasks()863 void PostMultipleTasks() {
864   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
865   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
866 }
867 
868 static const int kSignalMsg = WM_USER + 2;
869 
PostWindowsMessage(HWND message_hwnd)870 void PostWindowsMessage(HWND message_hwnd) {
871   PostMessage(message_hwnd, kSignalMsg, 0, 2);
872 }
873 
EndTest(bool * did_run,HWND hwnd)874 void EndTest(bool* did_run, HWND hwnd) {
875   *did_run = true;
876   PostMessage(hwnd, WM_CLOSE, 0, 0);
877 }
878 
879 int kMyMessageFilterCode = 0x5002;
880 
TestWndProcThunk(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)881 LRESULT 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 
TEST(MessageLoopTest,AlwaysHaveUserMessageWhenNesting)925 TEST(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 
TEST(MessageLoopTest,SetTaskRunner)948 TEST(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 
TEST(MessageLoopTest,OriginalRunnerWorks)957 TEST(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 
TEST(MessageLoopTest,DeleteUnboundLoop)970 TEST(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 
TEST(MessageLoopTest,ThreadName)981 TEST(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