Add commit SHA1 as this information is used to mark issues as dup by perf dashboard
[chromium-blink-merge.git] / base / message_loop / message_pump_libevent_unittest.cc
blob9298d687609cff87a05f43f1a1c55e728ef8fb5a
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.
5 #include "base/message_loop/message_pump_libevent.h"
7 #include <unistd.h>
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"
17 namespace base {
19 class MessagePumpLibeventTest : public testing::Test {
20 protected:
21 MessagePumpLibeventTest()
22 : ui_loop_(MessageLoop::TYPE_UI),
23 io_thread_("MessagePumpLibeventTestIOThread") {}
24 virtual ~MessagePumpLibeventTest() {}
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);
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";
41 MessageLoop* ui_loop() { return &ui_loop_; }
42 MessageLoopForIO* io_loop() const {
43 return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
46 void OnLibeventNotification(
47 MessagePumpLibevent* pump,
48 MessagePumpLibevent::FileDescriptorWatcher* controller) {
49 pump->OnLibeventNotification(0, EV_WRITE | EV_READ, controller);
52 int pipefds_[2];
54 private:
55 MessageLoop ui_loop_;
56 Thread io_thread_;
59 namespace {
61 // Concrete implementation of MessagePumpLibevent::Watcher that does
62 // nothing useful.
63 class StupidWatcher : public MessagePumpLibevent::Watcher {
64 public:
65 virtual ~StupidWatcher() {}
67 // base:MessagePumpLibevent::Watcher interface
68 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {}
69 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
72 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
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;
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\\(\\)");
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!");
92 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
94 class BaseWatcher : public MessagePumpLibevent::Watcher {
95 public:
96 explicit BaseWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller)
97 : controller_(controller) {
98 DCHECK(controller_);
100 virtual ~BaseWatcher() {}
102 // base:MessagePumpLibevent::Watcher interface
103 virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {
104 NOTREACHED();
107 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
108 NOTREACHED();
111 protected:
112 MessagePumpLibevent::FileDescriptorWatcher* controller_;
115 class DeleteWatcher : public BaseWatcher {
116 public:
117 explicit DeleteWatcher(
118 MessagePumpLibevent::FileDescriptorWatcher* controller)
119 : BaseWatcher(controller) {}
121 virtual ~DeleteWatcher() {
122 DCHECK(!controller_);
125 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
126 DCHECK(controller_);
127 delete controller_;
128 controller_ = NULL;
132 TEST_F(MessagePumpLibeventTest, DeleteWatcher) {
133 scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
134 MessagePumpLibevent::FileDescriptorWatcher* watcher =
135 new MessagePumpLibevent::FileDescriptorWatcher;
136 DeleteWatcher delegate(watcher);
137 pump->WatchFileDescriptor(pipefds_[1],
138 false, MessagePumpLibevent::WATCH_READ_WRITE, watcher, &delegate);
140 // Spoof a libevent notification.
141 OnLibeventNotification(pump.get(), watcher);
144 class StopWatcher : public BaseWatcher {
145 public:
146 explicit StopWatcher(
147 MessagePumpLibevent::FileDescriptorWatcher* controller)
148 : BaseWatcher(controller) {}
150 virtual ~StopWatcher() {}
152 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
153 controller_->StopWatchingFileDescriptor();
157 TEST_F(MessagePumpLibeventTest, StopWatcher) {
158 scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
159 MessagePumpLibevent::FileDescriptorWatcher watcher;
160 StopWatcher delegate(&watcher);
161 pump->WatchFileDescriptor(pipefds_[1],
162 false, MessagePumpLibevent::WATCH_READ_WRITE, &watcher, &delegate);
164 // Spoof a libevent notification.
165 OnLibeventNotification(pump.get(), &watcher);
168 void QuitMessageLoopAndStart(const Closure& quit_closure) {
169 quit_closure.Run();
171 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
172 RunLoop runloop;
173 MessageLoop::current()->PostTask(FROM_HERE, runloop.QuitClosure());
174 runloop.Run();
177 class NestedPumpWatcher : public MessagePumpLibevent::Watcher {
178 public:
179 NestedPumpWatcher() {}
180 virtual ~NestedPumpWatcher() {}
182 virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {
183 RunLoop runloop;
184 MessageLoop::current()->PostTask(FROM_HERE, Bind(&QuitMessageLoopAndStart,
185 runloop.QuitClosure()));
186 runloop.Run();
189 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {}
192 TEST_F(MessagePumpLibeventTest, NestedPumpWatcher) {
193 scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
194 MessagePumpLibevent::FileDescriptorWatcher watcher;
195 NestedPumpWatcher delegate;
196 pump->WatchFileDescriptor(pipefds_[1],
197 false, MessagePumpLibevent::WATCH_READ, &watcher, &delegate);
199 // Spoof a libevent notification.
200 OnLibeventNotification(pump.get(), &watcher);
203 } // namespace
205 } // namespace base