Upstream version 10.38.208.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/pending_task.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "base/run_loop.h"
18 #include "base/synchronization/waitable_event.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "base/threading/platform_thread.h"
21 #include "base/threading/thread.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 #if defined(OS_WIN)
25 #include "base/message_loop/message_pump_dispatcher.h"
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   Time::EnableHighResolutionTimer(true);
730
731   const TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5);
732   const TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100);
733
734   EXPECT_FALSE(loop.HasHighResolutionTasks());
735   // Post a fast task to enable the high resolution timers.
736   loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1),
737                        kFastTimer);
738   EXPECT_TRUE(loop.HasHighResolutionTasks());
739   loop.Run();
740   EXPECT_FALSE(loop.HasHighResolutionTasks());
741   EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
742   // Check that a slow task does not trigger the high resolution logic.
743   loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1),
744                        kSlowTimer);
745   EXPECT_FALSE(loop.HasHighResolutionTasks());
746   loop.Run();
747   EXPECT_FALSE(loop.HasHighResolutionTasks());
748   Time::EnableHighResolutionTimer(false);
749 }
750
751 #endif  // defined(OS_WIN)
752
753 #if defined(OS_POSIX) && !defined(OS_NACL)
754
755 namespace {
756
757 class QuitDelegate : public MessageLoopForIO::Watcher {
758  public:
759   virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {
760     MessageLoop::current()->QuitWhenIdle();
761   }
762   virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
763     MessageLoop::current()->QuitWhenIdle();
764   }
765 };
766
767 TEST(MessageLoopTest, FileDescriptorWatcherOutlivesMessageLoop) {
768   // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
769   // This could happen when people use the Singleton pattern or atexit.
770
771   // Create a file descriptor.  Doesn't need to be readable or writable,
772   // as we don't need to actually get any notifications.
773   // pipe() is just the easiest way to do it.
774   int pipefds[2];
775   int err = pipe(pipefds);
776   ASSERT_EQ(0, err);
777   int fd = pipefds[1];
778   {
779     // Arrange for controller to live longer than message loop.
780     MessageLoopForIO::FileDescriptorWatcher controller;
781     {
782       MessageLoopForIO message_loop;
783
784       QuitDelegate delegate;
785       message_loop.WatchFileDescriptor(fd,
786           true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
787       // and don't run the message loop, just destroy it.
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 TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) {
797   // Verify that it's ok to call StopWatchingFileDescriptor().
798   // (Errors only showed up in valgrind.)
799   int pipefds[2];
800   int err = pipe(pipefds);
801   ASSERT_EQ(0, err);
802   int fd = pipefds[1];
803   {
804     // Arrange for message loop to live longer than controller.
805     MessageLoopForIO message_loop;
806     {
807       MessageLoopForIO::FileDescriptorWatcher controller;
808
809       QuitDelegate delegate;
810       message_loop.WatchFileDescriptor(fd,
811           true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
812       controller.StopWatchingFileDescriptor();
813     }
814   }
815   if (IGNORE_EINTR(close(pipefds[0])) < 0)
816     PLOG(ERROR) << "close";
817   if (IGNORE_EINTR(close(pipefds[1])) < 0)
818     PLOG(ERROR) << "close";
819 }
820
821 }  // namespace
822
823 #endif  // defined(OS_POSIX) && !defined(OS_NACL)
824
825 namespace {
826 // Inject a test point for recording the destructor calls for Closure objects
827 // send to MessageLoop::PostTask(). It is awkward usage since we are trying to
828 // hook the actual destruction, which is not a common operation.
829 class DestructionObserverProbe :
830   public RefCounted<DestructionObserverProbe> {
831  public:
832   DestructionObserverProbe(bool* task_destroyed,
833                            bool* destruction_observer_called)
834       : task_destroyed_(task_destroyed),
835         destruction_observer_called_(destruction_observer_called) {
836   }
837   virtual void Run() {
838     // This task should never run.
839     ADD_FAILURE();
840   }
841  private:
842   friend class RefCounted<DestructionObserverProbe>;
843
844   virtual ~DestructionObserverProbe() {
845     EXPECT_FALSE(*destruction_observer_called_);
846     *task_destroyed_ = true;
847   }
848
849   bool* task_destroyed_;
850   bool* destruction_observer_called_;
851 };
852
853 class MLDestructionObserver : public MessageLoop::DestructionObserver {
854  public:
855   MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
856       : task_destroyed_(task_destroyed),
857         destruction_observer_called_(destruction_observer_called),
858         task_destroyed_before_message_loop_(false) {
859   }
860   virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
861     task_destroyed_before_message_loop_ = *task_destroyed_;
862     *destruction_observer_called_ = true;
863   }
864   bool task_destroyed_before_message_loop() const {
865     return task_destroyed_before_message_loop_;
866   }
867  private:
868   bool* task_destroyed_;
869   bool* destruction_observer_called_;
870   bool task_destroyed_before_message_loop_;
871 };
872
873 }  // namespace
874
875 TEST(MessageLoopTest, DestructionObserverTest) {
876   // Verify that the destruction observer gets called at the very end (after
877   // all the pending tasks have been destroyed).
878   MessageLoop* loop = new MessageLoop;
879   const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
880
881   bool task_destroyed = false;
882   bool destruction_observer_called = false;
883
884   MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
885   loop->AddDestructionObserver(&observer);
886   loop->PostDelayedTask(
887       FROM_HERE,
888       Bind(&DestructionObserverProbe::Run,
889                  new DestructionObserverProbe(&task_destroyed,
890                                               &destruction_observer_called)),
891       kDelay);
892   delete loop;
893   EXPECT_TRUE(observer.task_destroyed_before_message_loop());
894   // The task should have been destroyed when we deleted the loop.
895   EXPECT_TRUE(task_destroyed);
896   EXPECT_TRUE(destruction_observer_called);
897 }
898
899
900 // Verify that MessageLoop sets ThreadMainTaskRunner::current() and it
901 // posts tasks on that message loop.
902 TEST(MessageLoopTest, ThreadMainTaskRunner) {
903   MessageLoop loop;
904
905   scoped_refptr<Foo> foo(new Foo());
906   std::string a("a");
907   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(
908       &Foo::Test1ConstRef, foo.get(), a));
909
910   // Post quit task;
911   MessageLoop::current()->PostTask(FROM_HERE, Bind(
912       &MessageLoop::Quit, Unretained(MessageLoop::current())));
913
914   // Now kick things off
915   MessageLoop::current()->Run();
916
917   EXPECT_EQ(foo->test_count(), 1);
918   EXPECT_EQ(foo->result(), "a");
919 }
920
921 TEST(MessageLoopTest, IsType) {
922   MessageLoop loop(MessageLoop::TYPE_UI);
923   EXPECT_TRUE(loop.IsType(MessageLoop::TYPE_UI));
924   EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_IO));
925   EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT));
926 }
927
928 #if defined(OS_WIN)
929 void EmptyFunction() {}
930
931 void PostMultipleTasks() {
932   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
933   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
934 }
935
936 static const int kSignalMsg = WM_USER + 2;
937
938 void PostWindowsMessage(HWND message_hwnd) {
939   PostMessage(message_hwnd, kSignalMsg, 0, 2);
940 }
941
942 void EndTest(bool* did_run, HWND hwnd) {
943   *did_run = true;
944   PostMessage(hwnd, WM_CLOSE, 0, 0);
945 }
946
947 int kMyMessageFilterCode = 0x5002;
948
949 LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
950                                   WPARAM wparam, LPARAM lparam) {
951   if (message == WM_CLOSE)
952     EXPECT_TRUE(DestroyWindow(hwnd));
953   if (message != kSignalMsg)
954     return DefWindowProc(hwnd, message, wparam, lparam);
955
956   switch (lparam) {
957   case 1:
958     // First, we post a task that will post multiple no-op tasks to make sure
959     // that the pump's incoming task queue does not become empty during the
960     // test.
961     MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&PostMultipleTasks));
962     // Next, we post a task that posts a windows message to trigger the second
963     // stage of the test.
964     MessageLoop::current()->PostTask(FROM_HERE,
965                                      base::Bind(&PostWindowsMessage, hwnd));
966     break;
967   case 2:
968     // Since we're about to enter a modal loop, tell the message loop that we
969     // intend to nest tasks.
970     MessageLoop::current()->SetNestableTasksAllowed(true);
971     bool did_run = false;
972     MessageLoop::current()->PostTask(FROM_HERE,
973                                      base::Bind(&EndTest, &did_run, hwnd));
974     // Run a nested windows-style message loop and verify that our task runs. If
975     // it doesn't, then we'll loop here until the test times out.
976     MSG msg;
977     while (GetMessage(&msg, 0, 0, 0)) {
978       if (!CallMsgFilter(&msg, kMyMessageFilterCode))
979         DispatchMessage(&msg);
980       // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting
981       // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats
982       // WM_QUIT messages even when running inside a modal loop.
983       if (msg.message == WM_CLOSE)
984         break;
985     }
986     EXPECT_TRUE(did_run);
987     MessageLoop::current()->Quit();
988     break;
989   }
990   return 0;
991 }
992
993 TEST(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) {
994   MessageLoop loop(MessageLoop::TYPE_UI);
995   HINSTANCE instance = GetModuleFromAddress(&TestWndProcThunk);
996   WNDCLASSEX wc = {0};
997   wc.cbSize = sizeof(wc);
998   wc.lpfnWndProc = TestWndProcThunk;
999   wc.hInstance = instance;
1000   wc.lpszClassName = L"MessageLoopTest_HWND";
1001   ATOM atom = RegisterClassEx(&wc);
1002   ASSERT_TRUE(atom);
1003
1004   HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
1005                                    HWND_MESSAGE, 0, instance, 0);
1006   ASSERT_TRUE(message_hwnd) << GetLastError();
1007
1008   ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
1009
1010   loop.Run();
1011
1012   ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
1013 }
1014 #endif  // defined(OS_WIN)
1015
1016 }  // namespace base