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