1 // Copyright 2017 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_loop.h"
6
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_file.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/message_loop/message_loop_current.h"
15 #include "base/message_loop/message_pump_for_io.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "base/run_loop.h"
18 #include "base/test/gtest_util.h"
19 #include "build/build_config.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace base {
23
24 #if !defined(OS_NACL)
25
26 namespace {
27
28 class MessageLoopForIoPosixTest : public testing::Test {
29 public:
30 MessageLoopForIoPosixTest() = default;
31
32 // testing::Test interface.
SetUp()33 void SetUp() override {
34 // Create a file descriptor. Doesn't need to be readable or writable,
35 // as we don't need to actually get any notifications.
36 // pipe() is just the easiest way to do it.
37 int pipefds[2];
38 int err = pipe(pipefds);
39 ASSERT_EQ(0, err);
40 read_fd_ = ScopedFD(pipefds[0]);
41 write_fd_ = ScopedFD(pipefds[1]);
42 }
43
TriggerReadEvent()44 void TriggerReadEvent() {
45 // Write from the other end of the pipe to trigger the event.
46 char c = '\0';
47 EXPECT_EQ(1, HANDLE_EINTR(write(write_fd_.get(), &c, 1)));
48 }
49
50 protected:
51 ScopedFD read_fd_;
52 ScopedFD write_fd_;
53
54 DISALLOW_COPY_AND_ASSIGN(MessageLoopForIoPosixTest);
55 };
56
57 class TestHandler : public MessagePumpForIO::FdWatcher {
58 public:
OnFileCanReadWithoutBlocking(int fd)59 void OnFileCanReadWithoutBlocking(int fd) override {
60 watcher_to_delete_ = nullptr;
61 is_readable_ = true;
62 RunLoop::QuitCurrentWhenIdleDeprecated();
63 }
OnFileCanWriteWithoutBlocking(int fd)64 void OnFileCanWriteWithoutBlocking(int fd) override {
65 watcher_to_delete_ = nullptr;
66 is_writable_ = true;
67 RunLoop::QuitCurrentWhenIdleDeprecated();
68 }
69
70 bool is_readable_ = false;
71 bool is_writable_ = false;
72
73 // If set then the contained watcher will be deleted on notification.
74 std::unique_ptr<MessagePumpForIO::FdWatchController> watcher_to_delete_;
75 };
76
77 // Watcher that calls specified closures when read/write events occur. Verifies
78 // that each non-null closure passed to this class is called once and only once.
79 // Also resets the read event by reading from the FD.
80 class CallClosureHandler : public MessagePumpForIO::FdWatcher {
81 public:
CallClosureHandler(OnceClosure read_closure,OnceClosure write_closure)82 CallClosureHandler(OnceClosure read_closure, OnceClosure write_closure)
83 : read_closure_(std::move(read_closure)),
84 write_closure_(std::move(write_closure)) {}
85
~CallClosureHandler()86 ~CallClosureHandler() override {
87 EXPECT_TRUE(read_closure_.is_null());
88 EXPECT_TRUE(write_closure_.is_null());
89 }
90
SetReadClosure(OnceClosure read_closure)91 void SetReadClosure(OnceClosure read_closure) {
92 EXPECT_TRUE(read_closure_.is_null());
93 read_closure_ = std::move(read_closure);
94 }
95
SetWriteClosure(OnceClosure write_closure)96 void SetWriteClosure(OnceClosure write_closure) {
97 EXPECT_TRUE(write_closure_.is_null());
98 write_closure_ = std::move(write_closure);
99 }
100
101 // base:MessagePumpFuchsia::Watcher interface.
OnFileCanReadWithoutBlocking(int fd)102 void OnFileCanReadWithoutBlocking(int fd) override {
103 // Empty the pipe buffer to reset the event. Otherwise libevent
104 // implementation of MessageLoop may call the event handler again even if
105 // |read_closure_| below quits the RunLoop.
106 char c;
107 int result = HANDLE_EINTR(read(fd, &c, 1));
108 if (result == -1) {
109 PLOG(ERROR) << "read";
110 FAIL();
111 }
112 EXPECT_EQ(result, 1);
113
114 ASSERT_FALSE(read_closure_.is_null());
115 std::move(read_closure_).Run();
116 }
117
OnFileCanWriteWithoutBlocking(int fd)118 void OnFileCanWriteWithoutBlocking(int fd) override {
119 ASSERT_FALSE(write_closure_.is_null());
120 std::move(write_closure_).Run();
121 }
122
123 private:
124 OnceClosure read_closure_;
125 OnceClosure write_closure_;
126 };
127
TEST_F(MessageLoopForIoPosixTest,FileDescriptorWatcherOutlivesMessageLoop)128 TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherOutlivesMessageLoop) {
129 // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
130 // This could happen when people use the Singleton pattern or atexit.
131
132 // Arrange for watcher to live longer than message loop.
133 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
134 TestHandler handler;
135 {
136 MessageLoopForIO message_loop;
137
138 MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
139 write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
140 &handler);
141 // Don't run the message loop, just destroy it.
142 }
143
144 ASSERT_FALSE(handler.is_readable_);
145 ASSERT_FALSE(handler.is_writable_);
146 }
147
TEST_F(MessageLoopForIoPosixTest,FileDescriptorWatcherDoubleStop)148 TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherDoubleStop) {
149 // Verify that it's ok to call StopWatchingFileDescriptor().
150
151 // Arrange for message loop to live longer than watcher.
152 MessageLoopForIO message_loop;
153 {
154 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
155
156 TestHandler handler;
157 MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
158 write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
159 &handler);
160 ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
161 ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
162 }
163 }
164
TEST_F(MessageLoopForIoPosixTest,FileDescriptorWatcherDeleteInCallback)165 TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherDeleteInCallback) {
166 // Verify that it is OK to delete the FileDescriptorWatcher from within a
167 // callback.
168 MessageLoopForIO message_loop;
169
170 TestHandler handler;
171 handler.watcher_to_delete_ =
172 std::make_unique<MessagePumpForIO::FdWatchController>(FROM_HERE);
173
174 MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
175 write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE,
176 handler.watcher_to_delete_.get(), &handler);
177 RunLoop().Run();
178 }
179
180 // Verify that basic readable notification works.
TEST_F(MessageLoopForIoPosixTest,WatchReadable)181 TEST_F(MessageLoopForIoPosixTest, WatchReadable) {
182 MessageLoopForIO message_loop;
183 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
184 TestHandler handler;
185
186 // Watch the pipe for readability.
187 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
188 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
189 &watcher, &handler));
190
191 // The pipe should not be readable when first created.
192 RunLoop().RunUntilIdle();
193 ASSERT_FALSE(handler.is_readable_);
194 ASSERT_FALSE(handler.is_writable_);
195
196 TriggerReadEvent();
197
198 // We don't want to assume that the read fd becomes readable the
199 // instant a bytes is written, so Run until quit by an event.
200 RunLoop().Run();
201
202 ASSERT_TRUE(handler.is_readable_);
203 ASSERT_FALSE(handler.is_writable_);
204 }
205
206 // Verify that watching a file descriptor for writability succeeds.
TEST_F(MessageLoopForIoPosixTest,WatchWritable)207 TEST_F(MessageLoopForIoPosixTest, WatchWritable) {
208 MessageLoopForIO message_loop;
209 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
210 TestHandler handler;
211
212 // Watch the pipe for writability.
213 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
214 write_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_WRITE,
215 &watcher, &handler));
216
217 // We should not receive a writable notification until we process events.
218 ASSERT_FALSE(handler.is_readable_);
219 ASSERT_FALSE(handler.is_writable_);
220
221 // The pipe should be writable immediately, but wait for the quit closure
222 // anyway, to be sure.
223 RunLoop().Run();
224
225 ASSERT_FALSE(handler.is_readable_);
226 ASSERT_TRUE(handler.is_writable_);
227 }
228
229 // Verify that RunUntilIdle() receives IO notifications.
TEST_F(MessageLoopForIoPosixTest,RunUntilIdle)230 TEST_F(MessageLoopForIoPosixTest, RunUntilIdle) {
231 MessageLoopForIO message_loop;
232 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
233 TestHandler handler;
234
235 // Watch the pipe for readability.
236 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
237 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
238 &watcher, &handler));
239
240 // The pipe should not be readable when first created.
241 RunLoop().RunUntilIdle();
242 ASSERT_FALSE(handler.is_readable_);
243
244 TriggerReadEvent();
245
246 while (!handler.is_readable_)
247 RunLoop().RunUntilIdle();
248 }
249
StopWatching(MessagePumpForIO::FdWatchController * controller,RunLoop * run_loop)250 void StopWatching(MessagePumpForIO::FdWatchController* controller,
251 RunLoop* run_loop) {
252 controller->StopWatchingFileDescriptor();
253 run_loop->Quit();
254 }
255
256 // Verify that StopWatchingFileDescriptor() works from an event handler.
TEST_F(MessageLoopForIoPosixTest,StopFromHandler)257 TEST_F(MessageLoopForIoPosixTest, StopFromHandler) {
258 MessageLoopForIO message_loop;
259 RunLoop run_loop;
260 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
261 CallClosureHandler handler(BindOnce(&StopWatching, &watcher, &run_loop),
262 OnceClosure());
263
264 // Create persistent watcher.
265 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
266 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
267 &watcher, &handler));
268
269 TriggerReadEvent();
270 run_loop.Run();
271
272 // Trigger the event again. The event handler should not be called again.
273 TriggerReadEvent();
274 RunLoop().RunUntilIdle();
275 }
276
277 // Verify that non-persistent watcher is called only once.
TEST_F(MessageLoopForIoPosixTest,NonPersistentWatcher)278 TEST_F(MessageLoopForIoPosixTest, NonPersistentWatcher) {
279 MessageLoopForIO message_loop;
280 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
281
282 RunLoop run_loop;
283 CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
284
285 // Create a non-persistent watcher.
286 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
287 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
288 &watcher, &handler));
289
290 TriggerReadEvent();
291 run_loop.Run();
292
293 // Trigger the event again. handler should not be called again.
294 TriggerReadEvent();
295 RunLoop().RunUntilIdle();
296 }
297
298 // Verify that persistent watcher is called every time the event is triggered.
TEST_F(MessageLoopForIoPosixTest,PersistentWatcher)299 TEST_F(MessageLoopForIoPosixTest, PersistentWatcher) {
300 MessageLoopForIO message_loop;
301 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
302
303 RunLoop run_loop1;
304 CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure());
305
306 // Create persistent watcher.
307 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
308 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
309 &watcher, &handler));
310
311 TriggerReadEvent();
312 run_loop1.Run();
313
314 RunLoop run_loop2;
315 handler.SetReadClosure(run_loop2.QuitClosure());
316
317 // Trigger the event again. handler should be called now, which will quit
318 // run_loop2.
319 TriggerReadEvent();
320 run_loop2.Run();
321 }
322
StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController * controller,int fd,MessagePumpForIO::FdWatcher * new_handler,RunLoop * run_loop)323 void StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController* controller,
324 int fd,
325 MessagePumpForIO::FdWatcher* new_handler,
326 RunLoop* run_loop) {
327 controller->StopWatchingFileDescriptor();
328
329 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
330 fd, /*persistent=*/true, MessagePumpForIO::WATCH_READ, controller,
331 new_handler));
332
333 run_loop->Quit();
334 }
335
336 // Verify that a watcher can be stopped and reused from an event handler.
TEST_F(MessageLoopForIoPosixTest,StopAndRestartFromHandler)337 TEST_F(MessageLoopForIoPosixTest, StopAndRestartFromHandler) {
338 MessageLoopForIO message_loop;
339 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
340
341 RunLoop run_loop1;
342 RunLoop run_loop2;
343 CallClosureHandler handler2(run_loop2.QuitClosure(), OnceClosure());
344 CallClosureHandler handler1(BindOnce(&StopWatchingAndWatchAgain, &watcher,
345 read_fd_.get(), &handler2, &run_loop1),
346 OnceClosure());
347
348 // Create persistent watcher.
349 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
350 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
351 &watcher, &handler1));
352
353 TriggerReadEvent();
354 run_loop1.Run();
355
356 // Trigger the event again. handler2 should be called now, which will quit
357 // run_loop2
358 TriggerReadEvent();
359 run_loop2.Run();
360 }
361
362 // Verify that the pump properly handles a delayed task after an IO event.
TEST_F(MessageLoopForIoPosixTest,IoEventThenTimer)363 TEST_F(MessageLoopForIoPosixTest, IoEventThenTimer) {
364 MessageLoopForIO message_loop;
365 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
366
367 RunLoop timer_run_loop;
368 message_loop.task_runner()->PostDelayedTask(
369 FROM_HERE, timer_run_loop.QuitClosure(),
370 base::TimeDelta::FromMilliseconds(10));
371
372 RunLoop watcher_run_loop;
373 CallClosureHandler handler(watcher_run_loop.QuitClosure(), OnceClosure());
374
375 // Create a non-persistent watcher.
376 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
377 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
378 &watcher, &handler));
379
380 TriggerReadEvent();
381
382 // Normally the IO event will be received before the delayed task is
383 // executed, so this run loop will first handle the IO event and then quit on
384 // the timer.
385 timer_run_loop.Run();
386
387 // Run watcher_run_loop in case the IO event wasn't received before the
388 // delayed task.
389 watcher_run_loop.Run();
390 }
391
392 // Verify that the pipe can handle an IO event after a delayed task.
TEST_F(MessageLoopForIoPosixTest,TimerThenIoEvent)393 TEST_F(MessageLoopForIoPosixTest, TimerThenIoEvent) {
394 MessageLoopForIO message_loop;
395 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
396
397 // Trigger read event from a delayed task.
398 message_loop.task_runner()->PostDelayedTask(
399 FROM_HERE,
400 BindOnce(&MessageLoopForIoPosixTest::TriggerReadEvent, Unretained(this)),
401 TimeDelta::FromMilliseconds(1));
402
403 RunLoop run_loop;
404 CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
405
406 // Create a non-persistent watcher.
407 ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
408 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
409 &watcher, &handler));
410
411 run_loop.Run();
412 }
413
414 } // namespace
415
416 #endif // !defined(OS_NACL)
417
418 } // namespace base
419