1 // Copyright 2017 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 <sys/socket.h>
6
7 #include "base/compiler_specific.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_file.h"
10 #include "base/functional/bind.h"
11 #include "base/logging.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/message_loop/message_pump_for_io.h"
14 #include "base/posix/eintr_wrapper.h"
15 #include "base/run_loop.h"
16 #include "base/task/current_thread.h"
17 #include "base/test/gtest_util.h"
18 #include "base/test/scoped_feature_list.h"
19 #include "base/test/task_environment.h"
20 #include "build/build_config.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
24 #include "base/message_loop/message_pump_epoll.h"
25 #endif
26
27 namespace base {
28
29 #if !BUILDFLAG(IS_NACL)
30
31 namespace {
32
33 class FdWatchControllerPosixTest : public testing::Test,
34 public testing::WithParamInterface<bool> {
35 public:
36 FdWatchControllerPosixTest() = default;
37
38 FdWatchControllerPosixTest(const FdWatchControllerPosixTest&) = delete;
39 FdWatchControllerPosixTest& operator=(const FdWatchControllerPosixTest&) =
40 delete;
41
42 // testing::Test interface.
SetUp()43 void SetUp() override {
44 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
45 features_.InitWithFeatureStates(
46 {{kUsePollForMessagePumpEpoll, GetParam()}});
47 MessagePumpEpoll::InitializeFeatures();
48 #endif
49
50 // Create a file descriptor. Doesn't need to be readable or writable,
51 // as we don't need to actually get any notifications.
52 // pipe() is just the easiest way to do it.
53 int pipefds[2];
54 int err = pipe(pipefds);
55 ASSERT_EQ(0, err);
56 read_fd_ = ScopedFD(pipefds[0]);
57 write_fd_ = ScopedFD(pipefds[1]);
58 }
59
TriggerReadEvent()60 void TriggerReadEvent() {
61 // Write from the other end of the pipe to trigger the event.
62 char c = '\0';
63 EXPECT_EQ(1, HANDLE_EINTR(write(write_fd_.get(), &c, 1)));
64 }
65
66 protected:
67 ScopedFD read_fd_;
68 ScopedFD write_fd_;
69 base::test::ScopedFeatureList features_;
70 };
71
72 class TestHandler : public MessagePumpForIO::FdWatcher {
73 public:
OnFileCanReadWithoutBlocking(int fd)74 void OnFileCanReadWithoutBlocking(int fd) override {
75 watcher_to_delete_ = nullptr;
76 is_readable_ = true;
77 loop_->QuitWhenIdle();
78 }
OnFileCanWriteWithoutBlocking(int fd)79 void OnFileCanWriteWithoutBlocking(int fd) override {
80 watcher_to_delete_ = nullptr;
81 is_writable_ = true;
82 loop_->QuitWhenIdle();
83 }
set_run_loop(base::RunLoop * loop)84 void set_run_loop(base::RunLoop* loop) { loop_ = loop; }
85
86 bool is_readable_ = false;
87 bool is_writable_ = false;
88 raw_ptr<base::RunLoop> loop_;
89
90 // If set then the contained watcher will be deleted on notification.
91 std::unique_ptr<MessagePumpForIO::FdWatchController> watcher_to_delete_;
92 };
93
94 // Watcher that calls specified closures when read/write events occur. Verifies
95 // that each non-null closure passed to this class is called once and only once.
96 // Also resets the read event by reading from the FD.
97 class CallClosureHandler : public MessagePumpForIO::FdWatcher {
98 public:
CallClosureHandler(OnceClosure read_closure,OnceClosure write_closure)99 CallClosureHandler(OnceClosure read_closure, OnceClosure write_closure)
100 : read_closure_(std::move(read_closure)),
101 write_closure_(std::move(write_closure)) {}
102
~CallClosureHandler()103 ~CallClosureHandler() override {
104 EXPECT_TRUE(read_closure_.is_null());
105 EXPECT_TRUE(write_closure_.is_null());
106 }
107
SetReadClosure(OnceClosure read_closure)108 void SetReadClosure(OnceClosure read_closure) {
109 EXPECT_TRUE(read_closure_.is_null());
110 read_closure_ = std::move(read_closure);
111 }
112
SetWriteClosure(OnceClosure write_closure)113 void SetWriteClosure(OnceClosure write_closure) {
114 EXPECT_TRUE(write_closure_.is_null());
115 write_closure_ = std::move(write_closure);
116 }
117
118 // base::WatchableIOMessagePumpPosix::FdWatcher:
OnFileCanReadWithoutBlocking(int fd)119 void OnFileCanReadWithoutBlocking(int fd) override {
120 // Empty the pipe buffer to reset the event. Otherwise MessagePumpEpoll
121 // call the event handler again even if |read_closure_| below quits the
122 // RunLoop.
123 char c;
124 int result = HANDLE_EINTR(read(fd, &c, 1));
125 if (result == -1) {
126 PLOG(ERROR) << "read";
127 FAIL();
128 }
129 EXPECT_EQ(result, 1);
130
131 ASSERT_FALSE(read_closure_.is_null());
132 std::move(read_closure_).Run();
133 }
134
OnFileCanWriteWithoutBlocking(int fd)135 void OnFileCanWriteWithoutBlocking(int fd) override {
136 ASSERT_FALSE(write_closure_.is_null());
137 std::move(write_closure_).Run();
138 }
139
140 private:
141 OnceClosure read_closure_;
142 OnceClosure write_closure_;
143 };
144
TEST_P(FdWatchControllerPosixTest,FileDescriptorWatcherOutlivesMessageLoop)145 TEST_P(FdWatchControllerPosixTest, FileDescriptorWatcherOutlivesMessageLoop) {
146 // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
147 // This could happen when people use the Singleton pattern or atexit.
148 TestHandler handler;
149
150 // Arrange for watcher to live longer than message loop.
151 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
152 {
153 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
154
155 CurrentIOThread::Get()->WatchFileDescriptor(write_fd_.get(), true,
156 MessagePumpForIO::WATCH_WRITE,
157 &watcher, &handler);
158 // Don't run the message loop, just destroy it.
159 }
160
161 ASSERT_FALSE(handler.is_readable_);
162 ASSERT_FALSE(handler.is_writable_);
163 }
164
TEST_P(FdWatchControllerPosixTest,FileDescriptorWatcherDoubleStop)165 TEST_P(FdWatchControllerPosixTest, FileDescriptorWatcherDoubleStop) {
166 // Verify that it's ok to call StopWatchingFileDescriptor().
167
168 // Arrange for message loop to live longer than watcher.
169 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
170 {
171 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
172
173 TestHandler handler;
174 CurrentIOThread::Get()->WatchFileDescriptor(write_fd_.get(), true,
175 MessagePumpForIO::WATCH_WRITE,
176 &watcher, &handler);
177 ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
178 ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
179 }
180 }
181
TEST_P(FdWatchControllerPosixTest,FileDescriptorWatcherDeleteInCallback)182 TEST_P(FdWatchControllerPosixTest, FileDescriptorWatcherDeleteInCallback) {
183 // Verify that it is OK to delete the FileDescriptorWatcher from within a
184 // callback.
185 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
186
187 TestHandler handler;
188 base::RunLoop loop;
189 handler.set_run_loop(&loop);
190
191 handler.watcher_to_delete_ =
192 std::make_unique<MessagePumpForIO::FdWatchController>(FROM_HERE);
193
194 CurrentIOThread::Get()->WatchFileDescriptor(
195 write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE,
196 handler.watcher_to_delete_.get(), &handler);
197 loop.Run();
198 }
199
200 // A watcher that owns its controller and will either delete itself or stop
201 // watching the FD after observing the specified event type.
202 class ReaderWriterHandler : public MessagePumpForIO::FdWatcher {
203 public:
204 enum Action {
205 // Just call StopWatchingFileDescriptor().
206 kStopWatching,
207 // Delete |this| and its owned controller.
208 kDelete,
209 };
210 enum ActWhen {
211 // Take the Action after observing a read event.
212 kOnReadEvent,
213 // Take the Action after observing a write event.
214 kOnWriteEvent,
215 };
216
ReaderWriterHandler(Action action,ActWhen when,OnceClosure idle_quit_closure)217 ReaderWriterHandler(Action action,
218 ActWhen when,
219 OnceClosure idle_quit_closure)
220 : action_(action),
221 when_(when),
222 controller_(FROM_HERE),
223 idle_quit_closure_(std::move(idle_quit_closure)) {}
224
225 ReaderWriterHandler(const ReaderWriterHandler&) = delete;
226 ReaderWriterHandler& operator=(const ReaderWriterHandler&) = delete;
227
228 // base::WatchableIOMessagePumpPosix::FdWatcher:
OnFileCanReadWithoutBlocking(int fd)229 void OnFileCanReadWithoutBlocking(int fd) override {
230 if (when_ == kOnReadEvent) {
231 DoAction();
232 } else {
233 char c;
234 EXPECT_EQ(1, HANDLE_EINTR(read(fd, &c, 1)));
235 }
236 }
237
OnFileCanWriteWithoutBlocking(int fd)238 void OnFileCanWriteWithoutBlocking(int fd) override {
239 if (when_ == kOnWriteEvent) {
240 DoAction();
241 } else {
242 char c = '\0';
243 EXPECT_EQ(1, HANDLE_EINTR(write(fd, &c, 1)));
244 }
245 }
246
controller()247 MessagePumpForIO::FdWatchController* controller() { return &controller_; }
248
249 private:
DoAction()250 void DoAction() {
251 OnceClosure idle_quit_closure = std::move(idle_quit_closure_);
252 if (action_ == kDelete) {
253 delete this;
254 } else if (action_ == kStopWatching) {
255 controller_.StopWatchingFileDescriptor();
256 }
257 std::move(idle_quit_closure).Run();
258 }
259
260 Action action_;
261 ActWhen when_;
262 MessagePumpForIO::FdWatchController controller_;
263 OnceClosure idle_quit_closure_;
264 };
265
266 class MessageLoopForIoPosixReadAndWriteTest
267 : public testing::TestWithParam<ReaderWriterHandler::Action> {
268 protected:
CreateSocketPair(ScopedFD * one,ScopedFD * two)269 bool CreateSocketPair(ScopedFD* one, ScopedFD* two) {
270 int fds[2];
271 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
272 return false;
273 one->reset(fds[0]);
274 two->reset(fds[1]);
275 return true;
276 }
277 };
278
279 INSTANTIATE_TEST_SUITE_P(StopWatchingOrDelete,
280 MessageLoopForIoPosixReadAndWriteTest,
281 testing::Values(ReaderWriterHandler::kStopWatching,
282 ReaderWriterHandler::kDelete));
283
284 // Test deleting or stopping watch after a read event for a watcher that is
285 // registered for both read and write.
TEST_P(MessageLoopForIoPosixReadAndWriteTest,AfterRead)286 TEST_P(MessageLoopForIoPosixReadAndWriteTest, AfterRead) {
287 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
288 ScopedFD one, two;
289 ASSERT_TRUE(CreateSocketPair(&one, &two));
290
291 RunLoop run_loop;
292 ReaderWriterHandler* handler =
293 new ReaderWriterHandler(GetParam(), ReaderWriterHandler::kOnReadEvent,
294 run_loop.QuitWhenIdleClosure());
295
296 // Trigger a read event on |one| by writing to |two|.
297 char c = '\0';
298 EXPECT_EQ(1, HANDLE_EINTR(write(two.get(), &c, 1)));
299
300 // The triggered read will cause the watcher action to run. |one| would
301 // also be immediately available for writing, so this should not cause a
302 // use-after-free on the |handler|.
303 CurrentIOThread::Get()->WatchFileDescriptor(
304 one.get(), true, MessagePumpForIO::WATCH_READ_WRITE,
305 handler->controller(), handler);
306 run_loop.Run();
307
308 if (GetParam() == ReaderWriterHandler::kStopWatching) {
309 delete handler;
310 }
311 }
312
313 // Test deleting or stopping watch after a write event for a watcher that is
314 // registered for both read and write.
TEST_P(MessageLoopForIoPosixReadAndWriteTest,AfterWrite)315 TEST_P(MessageLoopForIoPosixReadAndWriteTest, AfterWrite) {
316 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
317 ScopedFD one, two;
318 ASSERT_TRUE(CreateSocketPair(&one, &two));
319
320 RunLoop run_loop;
321 ReaderWriterHandler* handler =
322 new ReaderWriterHandler(GetParam(), ReaderWriterHandler::kOnWriteEvent,
323 run_loop.QuitWhenIdleClosure());
324
325 // Trigger two read events on |one| by writing to |two|. Because each read
326 // event only reads one char, |one| will be available for reading again after
327 // the first read event is handled.
328 char c = '\0';
329 EXPECT_EQ(1, HANDLE_EINTR(write(two.get(), &c, 1)));
330 EXPECT_EQ(1, HANDLE_EINTR(write(two.get(), &c, 1)));
331
332 // The triggered read and the immediate availability of |one| for writing
333 // should cause both the read and write watchers to be triggered. The
334 // |handler| will do its action in response to the write event, which should
335 // not trigger a use-after-free for the second read that was queued.
336 CurrentIOThread::Get()->WatchFileDescriptor(
337 one.get(), true, MessagePumpForIO::WATCH_READ_WRITE,
338 handler->controller(), handler);
339 run_loop.Run();
340
341 if (GetParam() == ReaderWriterHandler::kStopWatching) {
342 delete handler;
343 }
344 }
345
346 INSTANTIATE_TEST_SUITE_P(All, FdWatchControllerPosixTest, ::testing::Bool());
347
348 // Verify that basic readable notification works.
TEST_P(FdWatchControllerPosixTest,WatchReadable)349 TEST_P(FdWatchControllerPosixTest, WatchReadable) {
350 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
351 TestHandler handler;
352 base::RunLoop loop;
353 handler.set_run_loop(&loop);
354 // Watch the pipe for readability.
355 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
356 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
357 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
358 &watcher, &handler));
359
360 // The pipe should not be readable when first created.
361 loop.RunUntilIdle();
362 ASSERT_FALSE(handler.is_readable_);
363 ASSERT_FALSE(handler.is_writable_);
364
365 TriggerReadEvent();
366
367 // We don't want to assume that the read fd becomes readable the
368 // instant a bytes is written, so Run until quit by an event.
369 loop.Run();
370
371 ASSERT_TRUE(handler.is_readable_);
372 ASSERT_FALSE(handler.is_writable_);
373 }
374
375 // Verify that you can re-add the same FD with the same watcher.
TEST_P(FdWatchControllerPosixTest,WatchReadableTwiceSameWatcher)376 TEST_P(FdWatchControllerPosixTest, WatchReadableTwiceSameWatcher) {
377 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
378 TestHandler handler;
379 base::RunLoop loop;
380 handler.set_run_loop(&loop);
381 // Watch the pipe for readability.
382 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
383 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
384 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
385 &watcher, &handler));
386
387 // The pipe should not be readable when first created.
388 loop.RunUntilIdle();
389 ASSERT_FALSE(handler.is_readable_);
390 ASSERT_FALSE(handler.is_writable_);
391
392 TriggerReadEvent();
393
394 // We don't want to assume that the read fd becomes readable the
395 // instant a bytes is written, so Run until quit by an event.
396 loop.Run();
397
398 ASSERT_TRUE(handler.is_readable_);
399 ASSERT_FALSE(handler.is_writable_);
400
401 // Clear the write and run the test again.
402 char c;
403 int result = HANDLE_EINTR(read(read_fd_.get(), &c, 1));
404 if (result == -1) {
405 PLOG(ERROR) << "read";
406 FAIL();
407 }
408 TestHandler handler2;
409 base::RunLoop loop2;
410 handler2.set_run_loop(&loop2);
411
412 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
413 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
414 &watcher, &handler2));
415
416 loop2.RunUntilIdle();
417 ASSERT_FALSE(handler2.is_readable_);
418 ASSERT_FALSE(handler2.is_writable_);
419
420 TriggerReadEvent();
421
422 // We don't want to assume that the read fd becomes readable the
423 // instant a bytes is written, so Run until quit by an event.
424 loop2.Run();
425
426 ASSERT_TRUE(handler2.is_readable_);
427 ASSERT_FALSE(handler2.is_writable_);
428 }
429
430 // Verify that you can re-add the same FD with a different watcher.
TEST_P(FdWatchControllerPosixTest,WatchReadableTwiceDifferentWatcher)431 TEST_P(FdWatchControllerPosixTest, WatchReadableTwiceDifferentWatcher) {
432 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
433 TestHandler handler;
434 base::RunLoop loop;
435 handler.set_run_loop(&loop);
436 // Watch the pipe for readability.
437 {
438 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
439 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
440 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
441 &watcher, &handler));
442
443 // The pipe should not be readable when first created.
444 loop.RunUntilIdle();
445 ASSERT_FALSE(handler.is_readable_);
446 ASSERT_FALSE(handler.is_writable_);
447
448 TriggerReadEvent();
449
450 // We don't want to assume that the read fd becomes readable the
451 // instant a bytes is written, so Run until quit by an event.
452 loop.Run();
453
454 ASSERT_TRUE(handler.is_readable_);
455 ASSERT_FALSE(handler.is_writable_);
456 }
457
458 // Clear the write and run the test again.
459 char c;
460 int result = HANDLE_EINTR(read(read_fd_.get(), &c, 1));
461 if (result == -1) {
462 PLOG(ERROR) << "read";
463 FAIL();
464 }
465 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
466 TestHandler handler2;
467 base::RunLoop loop2;
468 handler2.set_run_loop(&loop2);
469
470 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
471 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
472 &watcher, &handler2));
473
474 loop2.RunUntilIdle();
475 ASSERT_FALSE(handler2.is_readable_);
476 ASSERT_FALSE(handler2.is_writable_);
477
478 TriggerReadEvent();
479
480 // We don't want to assume that the read fd becomes readable the
481 // instant a bytes is written, so Run until quit by an event.
482 loop2.Run();
483
484 ASSERT_TRUE(handler2.is_readable_);
485 ASSERT_FALSE(handler2.is_writable_);
486 }
487
488 // Verify that watching a file descriptor for writability succeeds.
TEST_P(FdWatchControllerPosixTest,WatchWritable)489 TEST_P(FdWatchControllerPosixTest, WatchWritable) {
490 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
491 TestHandler handler;
492 base::RunLoop loop;
493
494 handler.set_run_loop(&loop);
495 // Watch the pipe for writability.
496 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
497 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
498 write_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_WRITE,
499 &watcher, &handler));
500
501 // We should not receive a writable notification until we process events.
502 ASSERT_FALSE(handler.is_readable_);
503 ASSERT_FALSE(handler.is_writable_);
504
505 // The pipe should be writable immediately, but wait for the quit closure
506 // anyway, to be sure.
507 loop.Run();
508
509 ASSERT_FALSE(handler.is_readable_);
510 ASSERT_TRUE(handler.is_writable_);
511 }
512
513 // Verify that RunUntilIdle() receives IO notifications.
TEST_P(FdWatchControllerPosixTest,RunUntilIdle)514 TEST_P(FdWatchControllerPosixTest, RunUntilIdle) {
515 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
516 TestHandler handler;
517 base::RunLoop loop;
518 handler.set_run_loop(&loop);
519 // Watch the pipe for readability.
520 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
521 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
522 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
523 &watcher, &handler));
524
525 // The pipe should not be readable when first created.
526 loop.RunUntilIdle();
527 ASSERT_FALSE(handler.is_readable_);
528
529 TriggerReadEvent();
530
531 while (!handler.is_readable_)
532 loop.RunUntilIdle();
533 }
534
StopWatching(MessagePumpForIO::FdWatchController * controller,RunLoop * run_loop)535 void StopWatching(MessagePumpForIO::FdWatchController* controller,
536 RunLoop* run_loop) {
537 controller->StopWatchingFileDescriptor();
538 run_loop->Quit();
539 }
540
541 // Verify that StopWatchingFileDescriptor() works from an event handler.
TEST_P(FdWatchControllerPosixTest,StopFromHandler)542 TEST_P(FdWatchControllerPosixTest, StopFromHandler) {
543 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
544 RunLoop run_loop;
545 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
546 CallClosureHandler handler(BindOnce(&StopWatching, &watcher, &run_loop),
547 OnceClosure());
548
549 // Create persistent watcher.
550 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
551 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
552 &watcher, &handler));
553
554 TriggerReadEvent();
555 run_loop.Run();
556
557 // Trigger the event again. The event handler should not be called again.
558 TriggerReadEvent();
559 RunLoop().RunUntilIdle();
560 }
561
562 // Verify that non-persistent watcher is called only once.
TEST_P(FdWatchControllerPosixTest,NonPersistentWatcher)563 TEST_P(FdWatchControllerPosixTest, NonPersistentWatcher) {
564 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
565
566 RunLoop run_loop;
567 CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
568
569 // Create a non-persistent watcher.
570 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
571 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
572 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
573 &watcher, &handler));
574
575 TriggerReadEvent();
576 run_loop.Run();
577
578 // Trigger the event again. handler should not be called again.
579 TriggerReadEvent();
580 RunLoop().RunUntilIdle();
581 }
582
583 // Verify that persistent watcher is called every time the event is triggered.
TEST_P(FdWatchControllerPosixTest,PersistentWatcher)584 TEST_P(FdWatchControllerPosixTest, PersistentWatcher) {
585 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
586
587 RunLoop run_loop1;
588 CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure());
589
590 // Create persistent watcher.
591 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
592 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
593 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
594 &watcher, &handler));
595
596 TriggerReadEvent();
597 run_loop1.Run();
598
599 RunLoop run_loop2;
600 handler.SetReadClosure(run_loop2.QuitClosure());
601
602 // Trigger the event again. handler should be called now, which will quit
603 // run_loop2.
604 TriggerReadEvent();
605 run_loop2.Run();
606 }
607
StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController * controller,int fd,MessagePumpForIO::FdWatcher * new_handler,RunLoop * run_loop)608 void StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController* controller,
609 int fd,
610 MessagePumpForIO::FdWatcher* new_handler,
611 RunLoop* run_loop) {
612 controller->StopWatchingFileDescriptor();
613
614 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
615 fd, /*persistent=*/true, MessagePumpForIO::WATCH_READ, controller,
616 new_handler));
617
618 run_loop->Quit();
619 }
620
621 // Verify that a watcher can be stopped and reused from an event handler.
TEST_P(FdWatchControllerPosixTest,StopAndRestartFromHandler)622 TEST_P(FdWatchControllerPosixTest, StopAndRestartFromHandler) {
623 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
624
625 RunLoop run_loop1;
626 RunLoop run_loop2;
627 CallClosureHandler handler2(run_loop2.QuitClosure(), OnceClosure());
628 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
629
630 CallClosureHandler handler1(BindOnce(&StopWatchingAndWatchAgain, &watcher,
631 read_fd_.get(), &handler2, &run_loop1),
632 OnceClosure());
633
634 // Create persistent watcher.
635 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
636 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
637 &watcher, &handler1));
638
639 TriggerReadEvent();
640 run_loop1.Run();
641
642 // Trigger the event again. handler2 should be called now, which will quit
643 // run_loop2
644 TriggerReadEvent();
645 run_loop2.Run();
646 }
647
648 // Verify that the pump properly handles a delayed task after an IO event.
TEST_P(FdWatchControllerPosixTest,IoEventThenTimer)649 TEST_P(FdWatchControllerPosixTest, IoEventThenTimer) {
650 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
651
652 RunLoop timer_run_loop;
653 env.GetMainThreadTaskRunner()->PostDelayedTask(
654 FROM_HERE, timer_run_loop.QuitClosure(), base::Milliseconds(10));
655
656 RunLoop watcher_run_loop;
657 CallClosureHandler handler(watcher_run_loop.QuitClosure(), OnceClosure());
658
659 // Create a non-persistent watcher.
660 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
661 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
662 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
663 &watcher, &handler));
664
665 TriggerReadEvent();
666
667 // Normally the IO event will be received before the delayed task is
668 // executed, so this run loop will first handle the IO event and then quit on
669 // the timer.
670 timer_run_loop.Run();
671
672 // Run watcher_run_loop in case the IO event wasn't received before the
673 // delayed task.
674 watcher_run_loop.Run();
675 }
676
677 // Verify that the pipe can handle an IO event after a delayed task.
TEST_P(FdWatchControllerPosixTest,TimerThenIoEvent)678 TEST_P(FdWatchControllerPosixTest, TimerThenIoEvent) {
679 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
680
681 // Trigger read event from a delayed task.
682 env.GetMainThreadTaskRunner()->PostDelayedTask(
683 FROM_HERE,
684 BindOnce(&FdWatchControllerPosixTest::TriggerReadEvent, Unretained(this)),
685 Milliseconds(1));
686
687 RunLoop run_loop;
688 CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
689
690 // Create a non-persistent watcher.
691 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
692 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
693 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
694 &watcher, &handler));
695
696 run_loop.Run();
697 }
698
699 } // namespace
700
701 #endif // !BUILDFLAG(IS_NACL)
702
703 } // namespace base
704