Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / base / message_loop / message_pump_libevent_unittest.cc
1 // Copyright (c) 2012 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 "base/message_loop/message_pump_libevent.h"
6
7 #include <unistd.h>
8
9 #include "base/bind.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/posix/eintr_wrapper.h"
12 #include "base/run_loop.h"
13 #include "base/threading/thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/libevent/event.h"
16
17 namespace base {
18
19 class MessagePumpLibeventTest : public testing::Test {
20  protected:
21   MessagePumpLibeventTest()
22       : ui_loop_(MessageLoop::TYPE_UI),
23         io_thread_("MessagePumpLibeventTestIOThread") {}
24   virtual ~MessagePumpLibeventTest() {}
25
26   virtual void SetUp() override {
27     Thread::Options options(MessageLoop::TYPE_IO, 0);
28     ASSERT_TRUE(io_thread_.StartWithOptions(options));
29     ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type());
30     int ret = pipe(pipefds_);
31     ASSERT_EQ(0, ret);
32   }
33
34   virtual void TearDown() override {
35     if (IGNORE_EINTR(close(pipefds_[0])) < 0)
36       PLOG(ERROR) << "close";
37     if (IGNORE_EINTR(close(pipefds_[1])) < 0)
38       PLOG(ERROR) << "close";
39   }
40
41   MessageLoop* ui_loop() { return &ui_loop_; }
42   MessageLoopForIO* io_loop() const {
43     return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
44   }
45
46   void OnLibeventNotification(
47       MessagePumpLibevent* pump,
48       MessagePumpLibevent::FileDescriptorWatcher* controller) {
49     pump->OnLibeventNotification(0, EV_WRITE | EV_READ, controller);
50   }
51
52   int pipefds_[2];
53
54  private:
55   MessageLoop ui_loop_;
56   Thread io_thread_;
57 };
58
59 namespace {
60
61 // Concrete implementation of MessagePumpLibevent::Watcher that does
62 // nothing useful.
63 class StupidWatcher : public MessagePumpLibevent::Watcher {
64  public:
65   ~StupidWatcher() override {}
66
67   // base:MessagePumpLibevent::Watcher interface
68   void OnFileCanReadWithoutBlocking(int fd) override {}
69   void OnFileCanWriteWithoutBlocking(int fd) override {}
70 };
71
72 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
73
74 // Test to make sure that we catch calling WatchFileDescriptor off of the
75 // wrong thread.
76 TEST_F(MessagePumpLibeventTest, TestWatchingFromBadThread) {
77   MessagePumpLibevent::FileDescriptorWatcher watcher;
78   StupidWatcher delegate;
79
80   ASSERT_DEATH(io_loop()->WatchFileDescriptor(
81       STDOUT_FILENO, false, MessageLoopForIO::WATCH_READ, &watcher, &delegate),
82       "Check failed: "
83       "watch_file_descriptor_caller_checker_.CalledOnValidThread\\(\\)");
84 }
85
86 TEST_F(MessagePumpLibeventTest, QuitOutsideOfRun) {
87   scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
88   ASSERT_DEATH(pump->Quit(), "Check failed: in_run_. "
89                              "Quit was called outside of Run!");
90 }
91
92 #endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
93
94 class BaseWatcher : public MessagePumpLibevent::Watcher {
95  public:
96   explicit BaseWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller)
97       : controller_(controller) {
98     DCHECK(controller_);
99   }
100   ~BaseWatcher() override {}
101
102   // base:MessagePumpLibevent::Watcher interface
103   void OnFileCanReadWithoutBlocking(int /* fd */) override { NOTREACHED(); }
104
105   void OnFileCanWriteWithoutBlocking(int /* fd */) override { NOTREACHED(); }
106
107  protected:
108   MessagePumpLibevent::FileDescriptorWatcher* controller_;
109 };
110
111 class DeleteWatcher : public BaseWatcher {
112  public:
113   explicit DeleteWatcher(
114       MessagePumpLibevent::FileDescriptorWatcher* controller)
115       : BaseWatcher(controller) {}
116
117   ~DeleteWatcher() override { DCHECK(!controller_); }
118
119   void OnFileCanWriteWithoutBlocking(int /* fd */) override {
120     DCHECK(controller_);
121     delete controller_;
122     controller_ = NULL;
123   }
124 };
125
126 TEST_F(MessagePumpLibeventTest, DeleteWatcher) {
127   scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
128   MessagePumpLibevent::FileDescriptorWatcher* watcher =
129       new MessagePumpLibevent::FileDescriptorWatcher;
130   DeleteWatcher delegate(watcher);
131   pump->WatchFileDescriptor(pipefds_[1],
132       false, MessagePumpLibevent::WATCH_READ_WRITE, watcher, &delegate);
133
134   // Spoof a libevent notification.
135   OnLibeventNotification(pump.get(), watcher);
136 }
137
138 class StopWatcher : public BaseWatcher {
139  public:
140   explicit StopWatcher(
141       MessagePumpLibevent::FileDescriptorWatcher* controller)
142       : BaseWatcher(controller) {}
143
144   ~StopWatcher() override {}
145
146   void OnFileCanWriteWithoutBlocking(int /* fd */) override {
147     controller_->StopWatchingFileDescriptor();
148   }
149 };
150
151 TEST_F(MessagePumpLibeventTest, StopWatcher) {
152   scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
153   MessagePumpLibevent::FileDescriptorWatcher watcher;
154   StopWatcher delegate(&watcher);
155   pump->WatchFileDescriptor(pipefds_[1],
156       false, MessagePumpLibevent::WATCH_READ_WRITE, &watcher, &delegate);
157
158   // Spoof a libevent notification.
159   OnLibeventNotification(pump.get(), &watcher);
160 }
161
162 void QuitMessageLoopAndStart(const Closure& quit_closure) {
163   quit_closure.Run();
164
165   MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
166   RunLoop runloop;
167   MessageLoop::current()->PostTask(FROM_HERE, runloop.QuitClosure());
168   runloop.Run();
169 }
170
171 class NestedPumpWatcher : public MessagePumpLibevent::Watcher {
172  public:
173   NestedPumpWatcher() {}
174   ~NestedPumpWatcher() override {}
175
176   void OnFileCanReadWithoutBlocking(int /* fd */) override {
177     RunLoop runloop;
178     MessageLoop::current()->PostTask(FROM_HERE, Bind(&QuitMessageLoopAndStart,
179                                                      runloop.QuitClosure()));
180     runloop.Run();
181   }
182
183   void OnFileCanWriteWithoutBlocking(int /* fd */) override {}
184 };
185
186 TEST_F(MessagePumpLibeventTest, NestedPumpWatcher) {
187   scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
188   MessagePumpLibevent::FileDescriptorWatcher watcher;
189   NestedPumpWatcher delegate;
190   pump->WatchFileDescriptor(pipefds_[1],
191       false, MessagePumpLibevent::WATCH_READ, &watcher, &delegate);
192
193   // Spoof a libevent notification.
194   OnLibeventNotification(pump.get(), &watcher);
195 }
196
197 }  // namespace
198
199 }  // namespace base