1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/unix_domain_server_socket_posix.h"
6
7#include <vector>
8
9#include "base/bind.h"
10#include "base/files/file_path.h"
11#include "base/files/scoped_temp_dir.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/run_loop.h"
14#include "base/stl_util.h"
15#include "net/base/io_buffer.h"
16#include "net/base/net_errors.h"
17#include "net/base/test_completion_callback.h"
18#include "net/socket/unix_domain_client_socket_posix.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21namespace net {
22namespace {
23
24const char kSocketFilename[] = "socket_for_testing";
25const char kInvalidSocketPath[] = "/invalid/path";
26
27bool UserCanConnectCallback(bool allow_user,
28    const UnixDomainServerSocket::Credentials& credentials) {
29  // Here peers are running in same process.
30#if defined(OS_LINUX) || defined(OS_ANDROID)
31  EXPECT_EQ(getpid(), credentials.process_id);
32#endif
33  EXPECT_EQ(getuid(), credentials.user_id);
34  EXPECT_EQ(getgid(), credentials.group_id);
35  return allow_user;
36}
37
38UnixDomainServerSocket::AuthCallback CreateAuthCallback(bool allow_user) {
39  return base::Bind(&UserCanConnectCallback, allow_user);
40}
41
42class UnixDomainServerSocketTest : public testing::Test {
43 protected:
44  UnixDomainServerSocketTest() {
45    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
46    socket_path_ = temp_dir_.path().Append(kSocketFilename).value();
47  }
48
49  base::ScopedTempDir temp_dir_;
50  std::string socket_path_;
51};
52
53TEST_F(UnixDomainServerSocketTest, ListenWithInvalidPath) {
54  const bool kUseAbstractNamespace = false;
55  UnixDomainServerSocket server_socket(CreateAuthCallback(true),
56                                       kUseAbstractNamespace);
57  EXPECT_EQ(ERR_FILE_NOT_FOUND,
58            server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
59}
60
61TEST_F(UnixDomainServerSocketTest, ListenWithInvalidPathWithAbstractNamespace) {
62  const bool kUseAbstractNamespace = true;
63  UnixDomainServerSocket server_socket(CreateAuthCallback(true),
64                                       kUseAbstractNamespace);
65#if defined(OS_ANDROID) || defined(OS_LINUX)
66  EXPECT_EQ(OK,
67            server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
68#else
69  EXPECT_EQ(ERR_ADDRESS_INVALID,
70            server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
71#endif
72}
73
74TEST_F(UnixDomainServerSocketTest, ListenAgainAfterFailureWithInvalidPath) {
75  const bool kUseAbstractNamespace = false;
76  UnixDomainServerSocket server_socket(CreateAuthCallback(true),
77                                       kUseAbstractNamespace);
78  EXPECT_EQ(ERR_FILE_NOT_FOUND,
79            server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
80  EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
81}
82
83TEST_F(UnixDomainServerSocketTest, AcceptWithForbiddenUser) {
84  const bool kUseAbstractNamespace = false;
85
86  UnixDomainServerSocket server_socket(CreateAuthCallback(false),
87                                       kUseAbstractNamespace);
88  EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
89
90  scoped_ptr<StreamSocket> accepted_socket;
91  TestCompletionCallback accept_callback;
92  EXPECT_EQ(ERR_IO_PENDING,
93            server_socket.Accept(&accepted_socket, accept_callback.callback()));
94  EXPECT_FALSE(accepted_socket);
95
96  UnixDomainClientSocket client_socket(socket_path_, kUseAbstractNamespace);
97  EXPECT_FALSE(client_socket.IsConnected());
98
99  // Connect() will return OK before the server rejects the connection.
100  TestCompletionCallback connect_callback;
101  int rv = connect_callback.GetResult(
102      client_socket.Connect(connect_callback.callback()));
103  ASSERT_EQ(OK, rv);
104
105  // Try to read from the socket.
106  const int read_buffer_size = 10;
107  scoped_refptr<IOBuffer> read_buffer(new IOBuffer(read_buffer_size));
108  TestCompletionCallback read_callback;
109  rv = read_callback.GetResult(client_socket.Read(
110      read_buffer.get(), read_buffer_size, read_callback.callback()));
111
112  // The server should have disconnected gracefully, without sending any data.
113  ASSERT_EQ(0, rv);
114  EXPECT_FALSE(client_socket.IsConnected());
115
116  // The server socket should not have called |accept_callback| or modified
117  // |accepted_socket|.
118  EXPECT_FALSE(accept_callback.have_result());
119  EXPECT_FALSE(accepted_socket);
120}
121
122// Normal cases including read/write are tested by UnixDomainClientSocketTest.
123
124}  // namespace
125}  // namespace net
126