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