| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <fcntl.h> |
| #include <unistd.h> |
| |
| #include "garnet/lib/debug_ipc/helper/fd_watcher.h" |
| #include "garnet/lib/debug_ipc/helper/platform_message_loop.h" |
| #include "gtest/gtest.h" |
| |
| #if defined(__Fuchsia__) |
| #include <zx/socket.h> |
| |
| #include "garnet/lib/debug_ipc/helper/socket_watcher.h" |
| #endif |
| |
| namespace debug_ipc { |
| |
| // This test either passes or hangs forever because the post didn't work. |
| // TODO(brettw) add a timeout when timers are supported in the message loop. |
| TEST(MessageLoop, PostQuit) { |
| PlatformMessageLoop loop; |
| loop.Init(); |
| |
| loop.PostTask(FROM_HERE, [loop_ptr = &loop]() { loop_ptr->QuitNow(); }); |
| loop.Run(); |
| |
| loop.Cleanup(); |
| } |
| |
| TEST(MessageLoop, WatchPipeFD) { |
| // Make a pipe to talk about. |
| int pipefd[2] = {-1, -1}; |
| ASSERT_EQ(0, pipe(pipefd)); |
| ASSERT_NE(-1, pipefd[0]); |
| ASSERT_NE(-1, pipefd[1]); |
| |
| int flags = fcntl(pipefd[0], F_GETFD); |
| flags |= O_NONBLOCK; |
| ASSERT_EQ(0, fcntl(pipefd[0], F_SETFD, flags)); |
| |
| flags = fcntl(pipefd[1], F_GETFD); |
| flags |= O_NONBLOCK; |
| ASSERT_EQ(0, fcntl(pipefd[1], F_SETFD, flags)); |
| |
| class ReadableWatcher : public FDWatcher { |
| public: |
| explicit ReadableWatcher(MessageLoop* loop) : loop_(loop) {} |
| void OnFDReadable(int fd) override { loop_->QuitNow(); } |
| |
| private: |
| MessageLoop* loop_; |
| }; |
| |
| PlatformMessageLoop loop; |
| loop.Init(); |
| |
| // Scope everything to before MessageLoop::Cleanup(). |
| { |
| ReadableWatcher watcher(&loop); |
| |
| // Going to write to pipefd[0] -> read from pipefd[1]. |
| MessageLoop::WatchHandle watch_handle = |
| loop.WatchFD(MessageLoop::WatchMode::kRead, pipefd[0], &watcher); |
| ASSERT_TRUE(watch_handle.watching()); |
| |
| // Enqueue a task that should cause pipefd[1] to become readable. |
| loop.PostTask(FROM_HERE, |
| [write_fd = pipefd[1]]() { write(write_fd, "Hello", 5); }); |
| |
| // This will quit on success because the OnFDReadable callback called |
| // QuitNow, or hang forever on failure. |
| // TODO(brettw) add a timeout when timers are supported in the message loop. |
| loop.Run(); |
| } |
| loop.Cleanup(); |
| } |
| |
| #if defined(__Fuchsia__) |
| TEST(MessageLoop, ZirconSocket) { |
| zx::socket sender, receiver; |
| ASSERT_EQ(ZX_OK, zx::socket::create(ZX_SOCKET_STREAM, &sender, &receiver)); |
| |
| class ReadableWatcher : public SocketWatcher { |
| public: |
| explicit ReadableWatcher(MessageLoop* loop) : loop_(loop) {} |
| void OnSocketReadable(zx_handle_t socket_handle) override { |
| loop_->QuitNow(); |
| } |
| |
| private: |
| MessageLoop* loop_; |
| }; |
| |
| PlatformMessageLoop loop; |
| loop.Init(); |
| |
| // Scope everything to before MessageLoop::Cleanup(). |
| { |
| ReadableWatcher watcher(&loop); |
| |
| MessageLoop::WatchHandle watch_handle = loop.WatchSocket( |
| MessageLoop::WatchMode::kRead, receiver.get(), &watcher); |
| ASSERT_TRUE(watch_handle.watching()); |
| |
| // Enqueue a task that should cause receiver to become readable. |
| loop.PostTask(FROM_HERE, |
| [&sender]() { sender.write(0, "Hello", 5, nullptr); }); |
| |
| // This will quit on success because the OnSocketReadable callback called |
| // QuitNow, or hang forever on failure. |
| // TODO(brettw) add a timeout when timers are supported in the message loop. |
| loop.Run(); |
| } |
| loop.Cleanup(); |
| } |
| #endif |
| |
| } // namespace debug_ipc |