| Index: net/socket/unix_domain_socket_posix_unittest.cc
|
| diff --git a/net/socket/unix_domain_socket_posix_unittest.cc b/net/socket/unix_domain_socket_posix_unittest.cc
|
| deleted file mode 100644
|
| index b1857e62e0e19df8f1d226def89fc954d4f8f951..0000000000000000000000000000000000000000
|
| --- a/net/socket/unix_domain_socket_posix_unittest.cc
|
| +++ /dev/null
|
| @@ -1,338 +0,0 @@
|
| -// Copyright (c) 2012 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 <errno.h>
|
| -#include <fcntl.h>
|
| -#include <poll.h>
|
| -#include <sys/socket.h>
|
| -#include <sys/stat.h>
|
| -#include <sys/time.h>
|
| -#include <sys/types.h>
|
| -#include <sys/un.h>
|
| -#include <unistd.h>
|
| -
|
| -#include <cstring>
|
| -#include <queue>
|
| -#include <string>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/callback.h"
|
| -#include "base/compiler_specific.h"
|
| -#include "base/file_util.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/memory/ref_counted.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/posix/eintr_wrapper.h"
|
| -#include "base/synchronization/condition_variable.h"
|
| -#include "base/synchronization/lock.h"
|
| -#include "base/threading/platform_thread.h"
|
| -#include "base/threading/thread.h"
|
| -#include "net/socket/socket_descriptor.h"
|
| -#include "net/socket/unix_domain_socket_posix.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -using std::queue;
|
| -using std::string;
|
| -
|
| -namespace net {
|
| -namespace {
|
| -
|
| -const char kSocketFilename[] = "unix_domain_socket_for_testing";
|
| -const char kInvalidSocketPath[] = "/invalid/path";
|
| -const char kMsg[] = "hello";
|
| -
|
| -enum EventType {
|
| - EVENT_ACCEPT,
|
| - EVENT_AUTH_DENIED,
|
| - EVENT_AUTH_GRANTED,
|
| - EVENT_CLOSE,
|
| - EVENT_LISTEN,
|
| - EVENT_READ,
|
| -};
|
| -
|
| -string MakeSocketPath(const string& socket_file_name) {
|
| - base::FilePath temp_dir;
|
| - base::GetTempDir(&temp_dir);
|
| - return temp_dir.Append(socket_file_name).value();
|
| -}
|
| -
|
| -string MakeSocketPath() {
|
| - return MakeSocketPath(kSocketFilename);
|
| -}
|
| -
|
| -class EventManager : public base::RefCounted<EventManager> {
|
| - public:
|
| - EventManager() : condition_(&mutex_) {}
|
| -
|
| - bool HasPendingEvent() {
|
| - base::AutoLock lock(mutex_);
|
| - return !events_.empty();
|
| - }
|
| -
|
| - void Notify(EventType event) {
|
| - base::AutoLock lock(mutex_);
|
| - events_.push(event);
|
| - condition_.Broadcast();
|
| - }
|
| -
|
| - EventType WaitForEvent() {
|
| - base::AutoLock lock(mutex_);
|
| - while (events_.empty())
|
| - condition_.Wait();
|
| - EventType event = events_.front();
|
| - events_.pop();
|
| - return event;
|
| - }
|
| -
|
| - private:
|
| - friend class base::RefCounted<EventManager>;
|
| - virtual ~EventManager() {}
|
| -
|
| - queue<EventType> events_;
|
| - base::Lock mutex_;
|
| - base::ConditionVariable condition_;
|
| -};
|
| -
|
| -class TestListenSocketDelegate : public StreamListenSocket::Delegate {
|
| - public:
|
| - explicit TestListenSocketDelegate(
|
| - const scoped_refptr<EventManager>& event_manager)
|
| - : event_manager_(event_manager) {}
|
| -
|
| - virtual void DidAccept(StreamListenSocket* server,
|
| - scoped_ptr<StreamListenSocket> connection) OVERRIDE {
|
| - LOG(ERROR) << __PRETTY_FUNCTION__;
|
| - connection_ = connection.Pass();
|
| - Notify(EVENT_ACCEPT);
|
| - }
|
| -
|
| - virtual void DidRead(StreamListenSocket* connection,
|
| - const char* data,
|
| - int len) OVERRIDE {
|
| - {
|
| - base::AutoLock lock(mutex_);
|
| - DCHECK(len);
|
| - data_.assign(data, len - 1);
|
| - }
|
| - Notify(EVENT_READ);
|
| - }
|
| -
|
| - virtual void DidClose(StreamListenSocket* sock) OVERRIDE {
|
| - Notify(EVENT_CLOSE);
|
| - }
|
| -
|
| - void OnListenCompleted() {
|
| - Notify(EVENT_LISTEN);
|
| - }
|
| -
|
| - string ReceivedData() {
|
| - base::AutoLock lock(mutex_);
|
| - return data_;
|
| - }
|
| -
|
| - private:
|
| - void Notify(EventType event) {
|
| - event_manager_->Notify(event);
|
| - }
|
| -
|
| - const scoped_refptr<EventManager> event_manager_;
|
| - scoped_ptr<StreamListenSocket> connection_;
|
| - base::Lock mutex_;
|
| - string data_;
|
| -};
|
| -
|
| -bool UserCanConnectCallback(
|
| - bool allow_user, const scoped_refptr<EventManager>& event_manager,
|
| - uid_t, gid_t) {
|
| - event_manager->Notify(
|
| - allow_user ? EVENT_AUTH_GRANTED : EVENT_AUTH_DENIED);
|
| - return allow_user;
|
| -}
|
| -
|
| -class UnixDomainSocketTestHelper : public testing::Test {
|
| - public:
|
| - void CreateAndListen() {
|
| - socket_ = UnixDomainSocket::CreateAndListen(
|
| - file_path_.value(), socket_delegate_.get(), MakeAuthCallback());
|
| - socket_delegate_->OnListenCompleted();
|
| - }
|
| -
|
| - protected:
|
| - UnixDomainSocketTestHelper(const string& path, bool allow_user)
|
| - : file_path_(path),
|
| - allow_user_(allow_user) {}
|
| -
|
| - virtual void SetUp() OVERRIDE {
|
| - event_manager_ = new EventManager();
|
| - socket_delegate_.reset(new TestListenSocketDelegate(event_manager_));
|
| - DeleteSocketFile();
|
| - }
|
| -
|
| - virtual void TearDown() OVERRIDE {
|
| - DeleteSocketFile();
|
| - socket_.reset();
|
| - socket_delegate_.reset();
|
| - event_manager_ = NULL;
|
| - }
|
| -
|
| - UnixDomainSocket::AuthCallback MakeAuthCallback() {
|
| - return base::Bind(&UserCanConnectCallback, allow_user_, event_manager_);
|
| - }
|
| -
|
| - void DeleteSocketFile() {
|
| - ASSERT_FALSE(file_path_.empty());
|
| - base::DeleteFile(file_path_, false /* not recursive */);
|
| - }
|
| -
|
| - SocketDescriptor CreateClientSocket() {
|
| - const SocketDescriptor sock = CreatePlatformSocket(PF_UNIX, SOCK_STREAM, 0);
|
| - if (sock < 0) {
|
| - LOG(ERROR) << "socket() error";
|
| - return kInvalidSocket;
|
| - }
|
| - sockaddr_un addr;
|
| - memset(&addr, 0, sizeof(addr));
|
| - addr.sun_family = AF_UNIX;
|
| - socklen_t addr_len;
|
| - strncpy(addr.sun_path, file_path_.value().c_str(), sizeof(addr.sun_path));
|
| - addr_len = sizeof(sockaddr_un);
|
| - if (connect(sock, reinterpret_cast<sockaddr*>(&addr), addr_len) != 0) {
|
| - LOG(ERROR) << "connect() error";
|
| - return kInvalidSocket;
|
| - }
|
| - return sock;
|
| - }
|
| -
|
| - scoped_ptr<base::Thread> CreateAndRunServerThread() {
|
| - base::Thread::Options options;
|
| - options.message_loop_type = base::MessageLoop::TYPE_IO;
|
| - scoped_ptr<base::Thread> thread(new base::Thread("socketio_test"));
|
| - thread->StartWithOptions(options);
|
| - thread->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&UnixDomainSocketTestHelper::CreateAndListen,
|
| - base::Unretained(this)));
|
| - return thread.Pass();
|
| - }
|
| -
|
| - const base::FilePath file_path_;
|
| - const bool allow_user_;
|
| - scoped_refptr<EventManager> event_manager_;
|
| - scoped_ptr<TestListenSocketDelegate> socket_delegate_;
|
| - scoped_ptr<UnixDomainSocket> socket_;
|
| -};
|
| -
|
| -class UnixDomainSocketTest : public UnixDomainSocketTestHelper {
|
| - protected:
|
| - UnixDomainSocketTest()
|
| - : UnixDomainSocketTestHelper(MakeSocketPath(), true /* allow user */) {}
|
| -};
|
| -
|
| -class UnixDomainSocketTestWithInvalidPath : public UnixDomainSocketTestHelper {
|
| - protected:
|
| - UnixDomainSocketTestWithInvalidPath()
|
| - : UnixDomainSocketTestHelper(kInvalidSocketPath, true) {}
|
| -};
|
| -
|
| -class UnixDomainSocketTestWithForbiddenUser
|
| - : public UnixDomainSocketTestHelper {
|
| - protected:
|
| - UnixDomainSocketTestWithForbiddenUser()
|
| - : UnixDomainSocketTestHelper(MakeSocketPath(), false /* forbid user */) {}
|
| -};
|
| -
|
| -TEST_F(UnixDomainSocketTest, CreateAndListen) {
|
| - CreateAndListen();
|
| - EXPECT_FALSE(socket_.get() == NULL);
|
| -}
|
| -
|
| -TEST_F(UnixDomainSocketTestWithInvalidPath, CreateAndListenWithInvalidPath) {
|
| - CreateAndListen();
|
| - EXPECT_TRUE(socket_.get() == NULL);
|
| -}
|
| -
|
| -#ifdef SOCKET_ABSTRACT_NAMESPACE_SUPPORTED
|
| -// Test with an invalid path to make sure that the socket is not backed by a
|
| -// file.
|
| -TEST_F(UnixDomainSocketTestWithInvalidPath,
|
| - CreateAndListenWithAbstractNamespace) {
|
| - socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
|
| - file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
|
| - EXPECT_FALSE(socket_.get() == NULL);
|
| -}
|
| -
|
| -TEST_F(UnixDomainSocketTest, TestFallbackName) {
|
| - scoped_ptr<UnixDomainSocket> existing_socket =
|
| - UnixDomainSocket::CreateAndListenWithAbstractNamespace(
|
| - file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
|
| - EXPECT_FALSE(existing_socket.get() == NULL);
|
| - // First, try to bind socket with the same name with no fallback name.
|
| - socket_ =
|
| - UnixDomainSocket::CreateAndListenWithAbstractNamespace(
|
| - file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
|
| - EXPECT_TRUE(socket_.get() == NULL);
|
| - // Now with a fallback name.
|
| - const char kFallbackSocketName[] = "unix_domain_socket_for_testing_2";
|
| - socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
|
| - file_path_.value(),
|
| - MakeSocketPath(kFallbackSocketName),
|
| - socket_delegate_.get(),
|
| - MakeAuthCallback());
|
| - EXPECT_FALSE(socket_.get() == NULL);
|
| -}
|
| -#endif
|
| -
|
| -TEST_F(UnixDomainSocketTest, TestWithClient) {
|
| - const scoped_ptr<base::Thread> server_thread = CreateAndRunServerThread();
|
| - EventType event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_LISTEN, event);
|
| -
|
| - // Create the client socket.
|
| - const SocketDescriptor sock = CreateClientSocket();
|
| - ASSERT_NE(kInvalidSocket, sock);
|
| - event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_AUTH_GRANTED, event);
|
| - event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_ACCEPT, event);
|
| -
|
| - // Send a message from the client to the server.
|
| - ssize_t ret = HANDLE_EINTR(send(sock, kMsg, sizeof(kMsg), 0));
|
| - ASSERT_NE(-1, ret);
|
| - ASSERT_EQ(sizeof(kMsg), static_cast<size_t>(ret));
|
| - event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_READ, event);
|
| - ASSERT_EQ(kMsg, socket_delegate_->ReceivedData());
|
| -
|
| - // Close the client socket.
|
| - ret = IGNORE_EINTR(close(sock));
|
| - event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_CLOSE, event);
|
| -}
|
| -
|
| -TEST_F(UnixDomainSocketTestWithForbiddenUser, TestWithForbiddenUser) {
|
| - const scoped_ptr<base::Thread> server_thread = CreateAndRunServerThread();
|
| - EventType event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_LISTEN, event);
|
| - const SocketDescriptor sock = CreateClientSocket();
|
| - ASSERT_NE(kInvalidSocket, sock);
|
| -
|
| - event = event_manager_->WaitForEvent();
|
| - ASSERT_EQ(EVENT_AUTH_DENIED, event);
|
| -
|
| - // Wait until the file descriptor is closed by the server.
|
| - struct pollfd poll_fd;
|
| - poll_fd.fd = sock;
|
| - poll_fd.events = POLLIN;
|
| - poll(&poll_fd, 1, -1 /* rely on GTest for timeout handling */);
|
| -
|
| - // Send() must fail.
|
| - ssize_t ret = HANDLE_EINTR(send(sock, kMsg, sizeof(kMsg), 0));
|
| - ASSERT_EQ(-1, ret);
|
| - ASSERT_EQ(EPIPE, errno);
|
| - ASSERT_FALSE(event_manager_->HasPendingEvent());
|
| -}
|
| -
|
| -} // namespace
|
| -} // namespace net
|
|
|