15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <poll.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/un.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstring>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/unix_domain_socket_posix.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::queue;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSocketFilename[] = "unix_domain_socket_for_testing";
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kFallbackSocketName[] = "unix_domain_socket_for_testing_2";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidSocketPath[] = "/invalid/path";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMsg[] = "hello";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum EventType {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_ACCEPT,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_AUTH_DENIED,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_AUTH_GRANTED,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_CLOSE,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_LISTEN,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_READ,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)string MakeSocketPath(const string& socket_file_name) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath temp_dir;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::GetTempDir(&temp_dir);
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return temp_dir.Append(socket_file_name).value();
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)string MakeSocketPath() {
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return MakeSocketPath(kSocketFilename);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EventManager : public base::RefCounted<EventManager> {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventManager() : condition_(&mutex_) {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasPendingEvent() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(mutex_);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !events_.empty();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Notify(EventType event) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(mutex_);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push(event);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    condition_.Broadcast();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventType WaitForEvent() {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(mutex_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (events_.empty())
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      condition_.Wait();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventType event = events_.front();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.pop();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return event;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<EventManager>;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~EventManager() {}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue<EventType> events_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock mutex_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ConditionVariable condition_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestListenSocketDelegate : public StreamListenSocket::Delegate {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestListenSocketDelegate(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<EventManager>& event_manager)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : event_manager_(event_manager) {}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidAccept(StreamListenSocket* server,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         StreamListenSocket* connection) OVERRIDE {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << __PRETTY_FUNCTION__;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_ = connection;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Notify(EVENT_ACCEPT);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidRead(StreamListenSocket* connection,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* data,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int len) OVERRIDE {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(mutex_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(len);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_.assign(data, len - 1);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Notify(EVENT_READ);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidClose(StreamListenSocket* sock) OVERRIDE {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Notify(EVENT_CLOSE);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnListenCompleted() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Notify(EVENT_LISTEN);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string ReceivedData() {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(mutex_);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Notify(EventType event) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_manager_->Notify(event);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<EventManager> event_manager_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<StreamListenSocket> connection_;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock mutex_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string data_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UserCanConnectCallback(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allow_user, const scoped_refptr<EventManager>& event_manager,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uid_t, gid_t) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_manager->Notify(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_user ? EVENT_AUTH_GRANTED : EVENT_AUTH_DENIED);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return allow_user;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnixDomainSocketTestHelper : public testing::Test {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateAndListen() {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_ = UnixDomainSocket::CreateAndListen(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_path_.value(), socket_delegate_.get(), MakeAuthCallback());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_delegate_->OnListenCompleted();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixDomainSocketTestHelper(const string& path, bool allow_user)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : file_path_(path),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        allow_user_(allow_user) {}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_manager_ = new EventManager();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_delegate_.reset(new TestListenSocketDelegate(event_manager_));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteSocketFile();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteSocketFile();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_ = NULL;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_delegate_.reset();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_manager_ = NULL;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixDomainSocket::AuthCallback MakeAuthCallback() {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Bind(&UserCanConnectCallback, allow_user_, event_manager_);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteSocketFile() {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(file_path_.empty());
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DeleteFile(file_path_, false /* not recursive */);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SocketDescriptor CreateClientSocket() {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SocketDescriptor sock = socket(PF_UNIX, SOCK_STREAM, 0);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sock < 0) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "socket() error";
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return StreamListenSocket::kInvalidSocket;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sockaddr_un addr;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&addr, 0, sizeof(addr));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addr.sun_family = AF_UNIX;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socklen_t addr_len;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strncpy(addr.sun_path, file_path_.value().c_str(), sizeof(addr.sun_path));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addr_len = sizeof(sockaddr_un);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (connect(sock, reinterpret_cast<sockaddr*>(&addr), addr_len) != 0) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "connect() error";
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return StreamListenSocket::kInvalidSocket;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sock;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Thread> CreateAndRunServerThread() {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Thread::Options options;
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    options.message_loop_type = base::MessageLoop::TYPE_IO;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::Thread> thread(new base::Thread("socketio_test"));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thread->StartWithOptions(options);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    thread->message_loop()->PostTask(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&UnixDomainSocketTestHelper::CreateAndListen,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return thread.Pass();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath file_path_;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool allow_user_;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<EventManager> event_manager_;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestListenSocketDelegate> socket_delegate_;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<UnixDomainSocket> socket_;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnixDomainSocketTest : public UnixDomainSocketTestHelper {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixDomainSocketTest()
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : UnixDomainSocketTestHelper(MakeSocketPath(), true /* allow user */) {}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnixDomainSocketTestWithInvalidPath : public UnixDomainSocketTestHelper {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixDomainSocketTestWithInvalidPath()
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : UnixDomainSocketTestHelper(kInvalidSocketPath, true) {}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnixDomainSocketTestWithForbiddenUser
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public UnixDomainSocketTestHelper {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixDomainSocketTestWithForbiddenUser()
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : UnixDomainSocketTestHelper(MakeSocketPath(), false /* forbid user */) {}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(UnixDomainSocketTest, CreateAndListen) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAndListen();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(socket_.get() == NULL);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(UnixDomainSocketTestWithInvalidPath, CreateAndListenWithInvalidPath) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAndListen();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(socket_.get() == NULL);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SOCKET_ABSTRACT_NAMESPACE_SUPPORTED
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test with an invalid path to make sure that the socket is not backed by a
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(UnixDomainSocketTestWithInvalidPath,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       CreateAndListenWithAbstractNamespace) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(socket_.get() == NULL);
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(UnixDomainSocketTest, TestFallbackName) {
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<UnixDomainSocket> existing_socket =
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UnixDomainSocket::CreateAndListenWithAbstractNamespace(
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(existing_socket.get() == NULL);
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // First, try to bind socket with the same name with no fallback name.
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_ =
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UnixDomainSocket::CreateAndListenWithAbstractNamespace(
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(socket_.get() == NULL);
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Now with a fallback name.
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_path_.value(),
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      MakeSocketPath(kFallbackSocketName),
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      socket_delegate_.get(),
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      MakeAuthCallback());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(socket_.get() == NULL);
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  existing_socket = NULL;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(UnixDomainSocketTest, TestWithClient) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_ptr<base::Thread> server_thread = CreateAndRunServerThread();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventType event = event_manager_->WaitForEvent();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_LISTEN, event);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the client socket.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SocketDescriptor sock = CreateClientSocket();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(StreamListenSocket::kInvalidSocket, sock);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event = event_manager_->WaitForEvent();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_AUTH_GRANTED, event);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event = event_manager_->WaitForEvent();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_ACCEPT, event);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a message from the client to the server.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t ret = HANDLE_EINTR(send(sock, kMsg, sizeof(kMsg), 0));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(-1, ret);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(sizeof(kMsg), static_cast<size_t>(ret));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event = event_manager_->WaitForEvent();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_READ, event);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kMsg, socket_delegate_->ReceivedData());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close the client socket.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ret = HANDLE_EINTR(close(sock));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event = event_manager_->WaitForEvent();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_CLOSE, event);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(UnixDomainSocketTestWithForbiddenUser, TestWithForbiddenUser) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_ptr<base::Thread> server_thread = CreateAndRunServerThread();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventType event = event_manager_->WaitForEvent();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_LISTEN, event);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SocketDescriptor sock = CreateClientSocket();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(StreamListenSocket::kInvalidSocket, sock);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event = event_manager_->WaitForEvent();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EVENT_AUTH_DENIED, event);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the file descriptor is closed by the server.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct pollfd poll_fd;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  poll_fd.fd = sock;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  poll_fd.events = POLLIN;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  poll(&poll_fd, 1, -1 /* rely on GTest for timeout handling */);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send() must fail.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t ret = HANDLE_EINTR(send(sock, kMsg, sizeof(kMsg), 0));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(-1, ret);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(EPIPE, errno);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(event_manager_->HasPendingEvent());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
339