| 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));
|
| +}
|
| +
|
| +}
|
|
|