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