• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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