Index: ipc/unix_domain_socket_util_unittest.cc |
diff --git a/ipc/unix_domain_socket_util_unittest.cc b/ipc/unix_domain_socket_util_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..82aa03c69d445608042059dea2fd376cf61c0476 |
--- /dev/null |
+++ b/ipc/unix_domain_socket_util_unittest.cc |
@@ -0,0 +1,156 @@ |
+// Copyright 2013 The Chromium 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 <sys/socket.h> |
+ |
+#include "base/bind.h" |
+#include "base/file_util.h" |
+#include "base/files/file_path.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "base/threading/thread.h" |
+#include "base/threading/thread_restrictions.h" |
+#include "ipc/unix_domain_socket_util.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace { |
+ |
+class SocketAcceptor : public MessageLoopForIO::Watcher { |
+ public: |
+ SocketAcceptor(int fd, base::MessageLoopProxy* target_thread) |
+ : server_fd_(-1), |
+ started_watching_event_(false, false), |
+ accepted_event_(false, false) { |
+ target_thread->PostTask(FROM_HERE, |
+ base::Bind(&SocketAcceptor::StartWatching, base::Unretained(this), fd)); |
+ } |
+ |
+ virtual ~SocketAcceptor() { |
+ watcher_.StopWatchingFileDescriptor(); |
+ } |
+ |
+ int server_fd() { return server_fd_; } |
+ |
+ void WaitUntilReady() { |
+ started_watching_event_.Wait(); |
+ } |
+ void WaitForAccept() { |
+ accepted_event_.Wait(); |
+ } |
+ |
+ private: |
+ void StartWatching(int fd) { |
+ MessageLoopForIO::current()->WatchFileDescriptor( |
+ fd, |
+ true, |
+ MessageLoopForIO::WATCH_READ, |
+ &watcher_, |
+ this); |
+ started_watching_event_.Signal(); |
+ } |
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { |
+ ASSERT_EQ(-1, server_fd_); |
+ IPC::ServerAcceptConnection(fd, &server_fd_); |
+ watcher_.StopWatchingFileDescriptor(); |
+ accepted_event_.Signal(); |
+ } |
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} |
+ |
+ int server_fd_; |
+ MessageLoopForIO::FileDescriptorWatcher watcher_; |
+ base::WaitableEvent started_watching_event_; |
+ base::WaitableEvent accepted_event_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SocketAcceptor); |
+}; |
+ |
+base::FilePath GetChannelDir() { |
+ return base::FilePath("/var/tmp"); |
+} |
+ |
+class TestUnixSocketConnection { |
+ public: |
+ TestUnixSocketConnection() |
+ : worker_("WorkerThread"), |
+ server_listen_fd_(-1), |
+ server_fd_(-1), |
+ client_fd_(-1), |
+ acceptor_(NULL) { |
+ socket_name_ = GetChannelDir().Append("TestSocket"); |
+ base::Thread::Options options; |
+ options.message_loop_type = MessageLoop::TYPE_IO; |
+ worker_.StartWithOptions(options); |
+ } |
+ |
+ bool CreateServerSocket() { |
+ IPC::CreateServerUnixDomainSocket(socket_name_, &server_listen_fd_); |
+ if (server_listen_fd_ < 0) |
+ return false; |
+ // TODO stat socket_name and check that there's a socket present |
+ acceptor_ = new SocketAcceptor(server_listen_fd_, |
+ worker_.message_loop_proxy()); |
+ acceptor_->WaitUntilReady(); |
+ return true; |
+ } |
+ |
+ bool CreateClientSocket() { |
+ DCHECK(server_listen_fd_ >= 0); |
+ IPC::CreateClientUnixDomainSocket(socket_name_, &client_fd_); |
+ if (client_fd_ < 0) |
+ return false; |
+ acceptor_->WaitForAccept(); |
+ server_fd_ = acceptor_->server_fd(); |
+ return server_fd_ >= 0; |
+ } |
+ |
+ virtual ~TestUnixSocketConnection() { |
+ if (acceptor_) |
+ delete acceptor_; |
+ if (client_fd_) |
+ close(client_fd_); |
+ if (server_fd_) |
+ close(server_fd_); |
+ if (server_listen_fd_) { |
+ close(server_listen_fd_); |
+ unlink(socket_name_.value().c_str()); |
+ } |
+ } |
+ |
+ int client_fd() { return client_fd_; } |
+ int server_fd() { return server_fd_; } |
+ |
+ private: |
+ base::Thread worker_; |
+ base::FilePath socket_name_; |
+ int server_listen_fd_; |
+ int server_fd_; |
+ int client_fd_; |
+ SocketAcceptor* acceptor_; |
+}; |
+ |
+// Ensure that IPC::CreateServerUnixDomainSocket creates a socket that |
+// IPC::CreateClientUnixDomainSocket can successfully connect to. |
+TEST(UnixDomainSocketUtil, Connect) { |
+ TestUnixSocketConnection connection; |
+ ASSERT_TRUE(connection.CreateServerSocket()); |
+ ASSERT_TRUE(connection.CreateClientSocket()); |
+} |
+ |
+// Ensure that messages can be sent across the resulting socket. |
+TEST(UnixDomainSocketUtil, SendReceive) { |
+ TestUnixSocketConnection connection; |
+ ASSERT_TRUE(connection.CreateServerSocket()); |
+ ASSERT_TRUE(connection.CreateClientSocket()); |
+ |
+ const char buffer[] = "Hello, server!"; |
+ size_t buf_len = strlen(buffer) + 1; |
+ size_t sent_bytes = send(connection.client_fd(), buffer, buf_len, 0); |
+ ASSERT_EQ(buf_len, sent_bytes); |
+ scoped_array<char> recv_buf(new char[buf_len]); |
+ size_t received_bytes = |
+ recv(connection.server_fd(), recv_buf.get(), buf_len, 0); |
+ ASSERT_EQ(buf_len, received_bytes); |
+ ASSERT_EQ(0, strncmp(recv_buf.get(), buffer, buf_len)); |
+} |
+ |
+} |