summaryrefslogtreecommitdiffstats
path: root/base/message_loop/message_pump_libevent_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/message_loop/message_pump_libevent_unittest.cc')
-rw-r--r--base/message_loop/message_pump_libevent_unittest.cc162
1 files changed, 162 insertions, 0 deletions
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc
new file mode 100644
index 0000000..657ac7d
--- /dev/null
+++ b/base/message_loop/message_pump_libevent_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_pump_libevent.h"
+
+#include <unistd.h>
+
+#include "base/message_loop/message_loop.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libevent/event.h"
+
+namespace base {
+
+class MessagePumpLibeventTest : public testing::Test {
+ protected:
+ MessagePumpLibeventTest()
+ : ui_loop_(MessageLoop::TYPE_UI),
+ io_thread_("MessagePumpLibeventTestIOThread") {}
+ virtual ~MessagePumpLibeventTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ Thread::Options options(MessageLoop::TYPE_IO, 0);
+ ASSERT_TRUE(io_thread_.StartWithOptions(options));
+ ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type());
+ int ret = pipe(pipefds_);
+ ASSERT_EQ(0, ret);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ if (HANDLE_EINTR(close(pipefds_[0])) < 0)
+ PLOG(ERROR) << "close";
+ if (HANDLE_EINTR(close(pipefds_[1])) < 0)
+ PLOG(ERROR) << "close";
+ }
+
+ MessageLoop* ui_loop() { return &ui_loop_; }
+ MessageLoopForIO* io_loop() const {
+ return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
+ }
+
+ void OnLibeventNotification(
+ MessagePumpLibevent* pump,
+ MessagePumpLibevent::FileDescriptorWatcher* controller) {
+ pump->OnLibeventNotification(0, EV_WRITE | EV_READ, controller);
+ }
+
+ int pipefds_[2];
+
+ private:
+ MessageLoop ui_loop_;
+ Thread io_thread_;
+};
+
+namespace {
+
+// Concrete implementation of MessagePumpLibevent::Watcher that does
+// nothing useful.
+class StupidWatcher : public MessagePumpLibevent::Watcher {
+ public:
+ virtual ~StupidWatcher() {}
+
+ // base:MessagePumpLibevent::Watcher interface
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {}
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
+};
+
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+// Test to make sure that we catch calling WatchFileDescriptor off of the
+// wrong thread.
+TEST_F(MessagePumpLibeventTest, TestWatchingFromBadThread) {
+ MessagePumpLibevent::FileDescriptorWatcher watcher;
+ StupidWatcher delegate;
+
+ ASSERT_DEATH(io_loop()->WatchFileDescriptor(
+ STDOUT_FILENO, false, MessageLoopForIO::WATCH_READ, &watcher, &delegate),
+ "Check failed: "
+ "watch_file_descriptor_caller_checker_.CalledOnValidThread()");
+}
+
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+
+class BaseWatcher : public MessagePumpLibevent::Watcher {
+ public:
+ explicit BaseWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller)
+ : controller_(controller) {
+ DCHECK(controller_);
+ }
+ virtual ~BaseWatcher() {}
+
+ // base:MessagePumpLibevent::Watcher interface
+ virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {
+ NOTREACHED();
+ }
+
+ virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
+ NOTREACHED();
+ }
+
+ protected:
+ MessagePumpLibevent::FileDescriptorWatcher* controller_;
+};
+
+class DeleteWatcher : public BaseWatcher {
+ public:
+ explicit DeleteWatcher(
+ MessagePumpLibevent::FileDescriptorWatcher* controller)
+ : BaseWatcher(controller) {}
+
+ virtual ~DeleteWatcher() {
+ DCHECK(!controller_);
+ }
+
+ virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
+ DCHECK(controller_);
+ delete controller_;
+ controller_ = NULL;
+ }
+};
+
+TEST_F(MessagePumpLibeventTest, DeleteWatcher) {
+ scoped_refptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
+ MessagePumpLibevent::FileDescriptorWatcher* watcher =
+ new MessagePumpLibevent::FileDescriptorWatcher;
+ DeleteWatcher delegate(watcher);
+ pump->WatchFileDescriptor(pipefds_[1],
+ false, MessagePumpLibevent::WATCH_READ_WRITE, watcher, &delegate);
+
+ // Spoof a libevent notification.
+ OnLibeventNotification(pump.get(), watcher);
+}
+
+class StopWatcher : public BaseWatcher {
+ public:
+ explicit StopWatcher(
+ MessagePumpLibevent::FileDescriptorWatcher* controller)
+ : BaseWatcher(controller) {}
+
+ virtual ~StopWatcher() {}
+
+ virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
+ controller_->StopWatchingFileDescriptor();
+ }
+};
+
+TEST_F(MessagePumpLibeventTest, StopWatcher) {
+ scoped_refptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
+ MessagePumpLibevent::FileDescriptorWatcher watcher;
+ StopWatcher delegate(&watcher);
+ pump->WatchFileDescriptor(pipefds_[1],
+ false, MessagePumpLibevent::WATCH_READ_WRITE, &watcher, &delegate);
+
+ // Spoof a libevent notification.
+ OnLibeventNotification(pump.get(), &watcher);
+}
+
+} // namespace
+
+} // namespace base