OLD | NEW |
| (Empty) |
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/message_loop.h" | |
10 #include "base/posix/eintr_wrapper.h" | |
11 #include "base/threading/thread.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 namespace base { | |
15 | |
16 class MessagePumpIOSForIOTest : public testing::Test { | |
17 protected: | |
18 MessagePumpIOSForIOTest() | |
19 : ui_loop_(MessageLoop::TYPE_UI), | |
20 io_thread_("MessagePumpIOSForIOTestIOThread") {} | |
21 virtual ~MessagePumpIOSForIOTest() {} | |
22 | |
23 virtual void SetUp() OVERRIDE { | |
24 Thread::Options options(MessageLoop::TYPE_IO, 0); | |
25 ASSERT_TRUE(io_thread_.StartWithOptions(options)); | |
26 ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type()); | |
27 int ret = pipe(pipefds_); | |
28 ASSERT_EQ(0, ret); | |
29 ret = pipe(alternate_pipefds_); | |
30 ASSERT_EQ(0, ret); | |
31 } | |
32 | |
33 virtual void TearDown() OVERRIDE { | |
34 if (HANDLE_EINTR(close(pipefds_[0])) < 0) | |
35 PLOG(ERROR) << "close"; | |
36 if (HANDLE_EINTR(close(pipefds_[1])) < 0) | |
37 PLOG(ERROR) << "close"; | |
38 } | |
39 | |
40 MessageLoop* ui_loop() { return &ui_loop_; } | |
41 MessageLoopForIO* io_loop() const { | |
42 return static_cast<MessageLoopForIO*>(io_thread_.message_loop()); | |
43 } | |
44 | |
45 void HandleFdIOEvent(MessageLoopForIO::FileDescriptorWatcher* watcher) { | |
46 MessagePumpIOSForIO::HandleFdIOEvent(watcher->fdref_, | |
47 kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack, | |
48 watcher); | |
49 } | |
50 | |
51 int pipefds_[2]; | |
52 int alternate_pipefds_[2]; | |
53 | |
54 private: | |
55 MessageLoop ui_loop_; | |
56 Thread io_thread_; | |
57 | |
58 DISALLOW_COPY_AND_ASSIGN(MessagePumpIOSForIOTest); | |
59 }; | |
60 | |
61 namespace { | |
62 | |
63 // Concrete implementation of MessagePumpIOSForIO::Watcher that does | |
64 // nothing useful. | |
65 class StupidWatcher : public MessagePumpIOSForIO::Watcher { | |
66 public: | |
67 virtual ~StupidWatcher() {} | |
68 | |
69 // base:MessagePumpIOSForIO::Watcher interface | |
70 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {} | |
71 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} | |
72 }; | |
73 | |
74 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) | |
75 | |
76 // Test to make sure that we catch calling WatchFileDescriptor off of the | |
77 // wrong thread. | |
78 TEST_F(MessagePumpIOSForIOTest, TestWatchingFromBadThread) { | |
79 MessagePumpIOSForIO::FileDescriptorWatcher watcher; | |
80 StupidWatcher delegate; | |
81 | |
82 ASSERT_DEBUG_DEATH(io_loop()->WatchFileDescriptor( | |
83 STDOUT_FILENO, false, MessageLoopForIO::WATCH_READ, &watcher, &delegate), | |
84 "Check failed: " | |
85 "watch_file_descriptor_caller_checker_.CalledOnValidThread()"); | |
86 } | |
87 | |
88 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) | |
89 | |
90 class BaseWatcher : public MessagePumpIOSForIO::Watcher { | |
91 public: | |
92 BaseWatcher(MessagePumpIOSForIO::FileDescriptorWatcher* controller) | |
93 : controller_(controller) { | |
94 DCHECK(controller_); | |
95 } | |
96 virtual ~BaseWatcher() {} | |
97 | |
98 // MessagePumpIOSForIO::Watcher interface | |
99 virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE { | |
100 NOTREACHED(); | |
101 } | |
102 | |
103 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { | |
104 NOTREACHED(); | |
105 } | |
106 | |
107 protected: | |
108 MessagePumpIOSForIO::FileDescriptorWatcher* controller_; | |
109 }; | |
110 | |
111 class DeleteWatcher : public BaseWatcher { | |
112 public: | |
113 explicit DeleteWatcher( | |
114 MessagePumpIOSForIO::FileDescriptorWatcher* controller) | |
115 : BaseWatcher(controller) {} | |
116 | |
117 virtual ~DeleteWatcher() { | |
118 DCHECK(!controller_); | |
119 } | |
120 | |
121 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { | |
122 DCHECK(controller_); | |
123 delete controller_; | |
124 controller_ = NULL; | |
125 } | |
126 }; | |
127 | |
128 TEST_F(MessagePumpIOSForIOTest, DeleteWatcher) { | |
129 scoped_refptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO); | |
130 MessagePumpIOSForIO::FileDescriptorWatcher* watcher = | |
131 new MessagePumpIOSForIO::FileDescriptorWatcher; | |
132 DeleteWatcher delegate(watcher); | |
133 pump->WatchFileDescriptor(pipefds_[1], | |
134 false, MessagePumpIOSForIO::WATCH_READ_WRITE, watcher, &delegate); | |
135 | |
136 // Spoof a callback. | |
137 HandleFdIOEvent(watcher); | |
138 } | |
139 | |
140 class StopWatcher : public BaseWatcher { | |
141 public: | |
142 StopWatcher(MessagePumpIOSForIO::FileDescriptorWatcher* controller, | |
143 MessagePumpIOSForIO* pump, | |
144 int fd_to_start_watching = -1) | |
145 : BaseWatcher(controller), | |
146 pump_(pump), | |
147 fd_to_start_watching_(fd_to_start_watching) {} | |
148 | |
149 virtual ~StopWatcher() {} | |
150 | |
151 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { | |
152 controller_->StopWatchingFileDescriptor(); | |
153 if (fd_to_start_watching_ >= 0) { | |
154 pump_->WatchFileDescriptor(fd_to_start_watching_, | |
155 false, MessagePumpIOSForIO::WATCH_READ_WRITE, controller_, this); | |
156 } | |
157 } | |
158 | |
159 private: | |
160 MessagePumpIOSForIO* pump_; | |
161 int fd_to_start_watching_; | |
162 }; | |
163 | |
164 TEST_F(MessagePumpIOSForIOTest, StopWatcher) { | |
165 scoped_refptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO); | |
166 MessagePumpIOSForIO::FileDescriptorWatcher watcher; | |
167 StopWatcher delegate(&watcher, pump); | |
168 pump->WatchFileDescriptor(pipefds_[1], | |
169 false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate); | |
170 | |
171 // Spoof a callback. | |
172 HandleFdIOEvent(&watcher); | |
173 } | |
174 | |
175 TEST_F(MessagePumpIOSForIOTest, StopWatcherAndWatchSomethingElse) { | |
176 scoped_refptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO); | |
177 MessagePumpIOSForIO::FileDescriptorWatcher watcher; | |
178 StopWatcher delegate(&watcher, pump, alternate_pipefds_[1]); | |
179 pump->WatchFileDescriptor(pipefds_[1], | |
180 false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate); | |
181 | |
182 // Spoof a callback. | |
183 HandleFdIOEvent(&watcher); | |
184 } | |
185 | |
186 } // namespace | |
187 | |
188 } // namespace base | |
OLD | NEW |