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