1 // Copyright 2012 The Chromium Authors
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_io_ios.h"
6
7 #include <unistd.h>
8
9 #include "base/logging.h"
10 #include "base/message_loop/message_pump_for_io.h"
11 #include "base/posix/eintr_wrapper.h"
12 #include "base/test/gtest_util.h"
13 #include "base/threading/thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17
18 class MessagePumpIOSForIOTest : public testing::Test {
19 public:
20 MessagePumpIOSForIOTest(const MessagePumpIOSForIOTest&) = delete;
21 MessagePumpIOSForIOTest& operator=(const MessagePumpIOSForIOTest&) = delete;
22
23 protected:
24 MessagePumpIOSForIOTest() = default;
25 ~MessagePumpIOSForIOTest() override = default;
26
SetUp()27 void SetUp() override {
28 int ret = pipe(pipefds_);
29 ASSERT_EQ(0, ret);
30 ret = pipe(alternate_pipefds_);
31 ASSERT_EQ(0, ret);
32 }
33
TearDown()34 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
HandleFdIOEvent(MessagePumpForIO::FdWatchController * watcher)41 void HandleFdIOEvent(MessagePumpForIO::FdWatchController* watcher) {
42 MessagePumpIOSForIO::HandleFdIOEvent(watcher->fdref_.get(),
43 kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack,
44 watcher);
45 }
46
47 int pipefds_[2];
48 int alternate_pipefds_[2];
49 };
50
51 namespace {
52
53 class BaseWatcher : public MessagePumpIOSForIO::FdWatcher {
54 public:
BaseWatcher(MessagePumpIOSForIO::FdWatchController * controller)55 BaseWatcher(MessagePumpIOSForIO::FdWatchController* controller)
56 : controller_(controller) {
57 DCHECK(controller_);
58 }
59 ~BaseWatcher() override = default;
60
61 // MessagePumpIOSForIO::FdWatcher interface
OnFileCanReadWithoutBlocking(int)62 void OnFileCanReadWithoutBlocking(int /* fd */) override { NOTREACHED(); }
63
OnFileCanWriteWithoutBlocking(int)64 void OnFileCanWriteWithoutBlocking(int /* fd */) override { NOTREACHED(); }
65
66 protected:
67 MessagePumpIOSForIO::FdWatchController* controller_;
68 };
69
70 class DeleteWatcher : public BaseWatcher {
71 public:
DeleteWatcher(MessagePumpIOSForIO::FdWatchController * controller)72 explicit DeleteWatcher(MessagePumpIOSForIO::FdWatchController* controller)
73 : BaseWatcher(controller) {}
74
~DeleteWatcher()75 ~DeleteWatcher() override { DCHECK(!controller_); }
76
OnFileCanWriteWithoutBlocking(int)77 void OnFileCanWriteWithoutBlocking(int /* fd */) override {
78 DCHECK(controller_);
79 delete controller_;
80 controller_ = NULL;
81 }
82 };
83
TEST_F(MessagePumpIOSForIOTest,DeleteWatcher)84 TEST_F(MessagePumpIOSForIOTest, DeleteWatcher) {
85 std::unique_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO);
86 MessagePumpIOSForIO::FdWatchController* watcher =
87 new MessagePumpIOSForIO::FdWatchController(FROM_HERE);
88 DeleteWatcher delegate(watcher);
89 pump->WatchFileDescriptor(pipefds_[1],
90 false, MessagePumpIOSForIO::WATCH_READ_WRITE, watcher, &delegate);
91
92 // Spoof a callback.
93 HandleFdIOEvent(watcher);
94 }
95
96 class StopWatcher : public BaseWatcher {
97 public:
StopWatcher(MessagePumpIOSForIO::FdWatchController * controller,MessagePumpIOSForIO * pump,int fd_to_start_watching=-1)98 StopWatcher(MessagePumpIOSForIO::FdWatchController* controller,
99 MessagePumpIOSForIO* pump,
100 int fd_to_start_watching = -1)
101 : BaseWatcher(controller),
102 pump_(pump),
103 fd_to_start_watching_(fd_to_start_watching) {}
104
105 ~StopWatcher() override = default;
106
OnFileCanWriteWithoutBlocking(int)107 void OnFileCanWriteWithoutBlocking(int /* fd */) override {
108 controller_->StopWatchingFileDescriptor();
109 if (fd_to_start_watching_ >= 0) {
110 pump_->WatchFileDescriptor(fd_to_start_watching_,
111 false, MessagePumpIOSForIO::WATCH_READ_WRITE, controller_, this);
112 }
113 }
114
115 private:
116 MessagePumpIOSForIO* pump_;
117 int fd_to_start_watching_;
118 };
119
TEST_F(MessagePumpIOSForIOTest,StopWatcher)120 TEST_F(MessagePumpIOSForIOTest, StopWatcher) {
121 std::unique_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO);
122 MessagePumpIOSForIO::FdWatchController watcher(FROM_HERE);
123 StopWatcher delegate(&watcher, pump.get());
124 pump->WatchFileDescriptor(pipefds_[1],
125 false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate);
126
127 // Spoof a callback.
128 HandleFdIOEvent(&watcher);
129 }
130
TEST_F(MessagePumpIOSForIOTest,StopWatcherAndWatchSomethingElse)131 TEST_F(MessagePumpIOSForIOTest, StopWatcherAndWatchSomethingElse) {
132 std::unique_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO);
133 MessagePumpIOSForIO::FdWatchController watcher(FROM_HERE);
134 StopWatcher delegate(&watcher, pump.get(), alternate_pipefds_[1]);
135 pump->WatchFileDescriptor(pipefds_[1],
136 false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate);
137
138 // Spoof a callback.
139 HandleFdIOEvent(&watcher);
140 }
141
142 } // namespace
143
144 } // namespace base
145