Index: base/message_loop/message_pump_libevent_unittest.cc |
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc |
index 1058ee8697671e97d5671689568b1bb6dd8bb56c..65d721727284f35cfdc3ad621c63ddb5fa51e9e7 100644 |
--- a/base/message_loop/message_pump_libevent_unittest.cc |
+++ b/base/message_loop/message_pump_libevent_unittest.cc |
@@ -7,9 +7,14 @@ |
#include <unistd.h> |
#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/files/file_util.h" |
+#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop.h" |
#include "base/posix/eintr_wrapper.h" |
#include "base/run_loop.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "base/synchronization/waitable_event_watcher.h" |
#include "base/threading/thread.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "third_party/libevent/event.h" |
@@ -19,7 +24,7 @@ namespace base { |
class MessagePumpLibeventTest : public testing::Test { |
protected: |
MessagePumpLibeventTest() |
- : ui_loop_(MessageLoop::TYPE_UI), |
+ : ui_loop_(new MessageLoop(MessageLoop::TYPE_UI)), |
io_thread_("MessagePumpLibeventTestIOThread") {} |
~MessagePumpLibeventTest() override {} |
@@ -38,7 +43,6 @@ class MessagePumpLibeventTest : public testing::Test { |
PLOG(ERROR) << "close"; |
} |
- MessageLoop* ui_loop() { return &ui_loop_; } |
MessageLoopForIO* io_loop() const { |
return static_cast<MessageLoopForIO*>(io_thread_.message_loop()); |
} |
@@ -50,9 +54,9 @@ class MessagePumpLibeventTest : public testing::Test { |
} |
int pipefds_[2]; |
+ scoped_ptr<MessageLoop> ui_loop_; |
private: |
- MessageLoop ui_loop_; |
Thread io_thread_; |
}; |
@@ -194,6 +198,69 @@ TEST_F(MessagePumpLibeventTest, NestedPumpWatcher) { |
OnLibeventNotification(pump.get(), &watcher); |
} |
+void FatalClosure() { |
+ FAIL() << "Reached fatal closure."; |
+} |
+ |
+class QuitWatcher : public BaseWatcher { |
+ public: |
+ QuitWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller, |
+ RunLoop* run_loop) |
+ : BaseWatcher(controller), run_loop_(run_loop) {} |
+ ~QuitWatcher() override {} |
+ |
+ void OnFileCanReadWithoutBlocking(int /* fd */) override { |
+ // Post a fatal closure to the MessageLoop before we quit it. |
+ MessageLoop::current()->PostTask(FROM_HERE, Bind(&FatalClosure)); |
+ |
+ // Now quit the MessageLoop. |
+ run_loop_->Quit(); |
+ } |
+ |
+ private: |
+ RunLoop* run_loop_; // weak |
+}; |
+ |
+void WriteFDWrapper(const int fd, |
+ const char* buf, |
+ int size, |
+ WaitableEvent* event) { |
+ ASSERT_TRUE(WriteFileDescriptor(fd, buf, size)); |
+} |
+ |
+// Tests that MessagePumpLibevent quits immediately when it is quit from |
+// libevent's event_base_loop(). |
+TEST_F(MessagePumpLibeventTest, QuitWatcher) { |
+ // Delete the old MessageLoop so that we can manage our own one here. |
+ ui_loop_.reset(); |
+ |
+ MessagePumpLibevent* pump = new MessagePumpLibevent; // owned by |loop|. |
+ MessageLoop loop(make_scoped_ptr(pump)); |
+ RunLoop run_loop; |
+ MessagePumpLibevent::FileDescriptorWatcher controller; |
+ QuitWatcher delegate(&controller, &run_loop); |
+ WaitableEvent event(false /* manual_reset */, false /* initially_signaled */); |
+ WaitableEventWatcher watcher; |
+ |
+ // Tell the pump to watch the pipe. |
+ pump->WatchFileDescriptor(pipefds_[0], false, MessagePumpLibevent::WATCH_READ, |
+ &controller, &delegate); |
+ |
+ // Make the IO thread wait for |event| before writing to pipefds[1]. |
+ const char buf = 0; |
+ const WaitableEventWatcher::EventCallback write_fd_task = |
+ Bind(&WriteFDWrapper, pipefds_[1], &buf, 1); |
+ io_loop()->PostTask(FROM_HERE, |
+ Bind(IgnoreResult(&WaitableEventWatcher::StartWatching), |
+ Unretained(&watcher), &event, write_fd_task)); |
+ |
+ // Queue |event| to signal on |loop|. |
+ loop.PostTask(FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&event))); |
+ |
+ // Now run the MessageLoop. |
+ run_loop.Run(); |
+} |
+ |
} // namespace |
} // namespace base |