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