blob: ab620213de01ac934279643f73c9d7426f9f4501 [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Primiano Tucci2c5488f2019-06-01 03:27:28 +010017#include "perfetto/ext/base/unix_socket.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000018
Primiano Tucci45b902a2018-10-04 14:57:09 +010019#include <signal.h>
Primiano Tucci43ebf4d2019-01-02 20:04:34 +010020#include <sys/types.h>
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000021#include <list>
Primiano Tucci7a265b62017-12-07 18:37:31 +000022#include <thread>
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000023
Primiano Tuccieb7e3662021-01-07 21:30:40 +010024#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
25#include <sys/mman.h>
26#include <sys/socket.h>
27#include <sys/un.h>
28#endif
29
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000030#include "perfetto/base/build_config.h"
31#include "perfetto/base/logging.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010032#include "perfetto/ext/base/file_utils.h"
Primiano Tucci3d086422021-11-24 00:07:06 +000033#include "perfetto/ext/base/periodic_task.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010034#include "perfetto/ext/base/pipe.h"
Primiano Tucci94e94bb2022-07-26 20:19:30 +010035#include "perfetto/ext/base/string_utils.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010036#include "perfetto/ext/base/temp_file.h"
37#include "perfetto/ext/base/utils.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000038#include "src/base/test/test_task_runner.h"
Primiano Tuccib03ba362017-12-06 09:47:41 +000039#include "src/ipc/test/test_socket.h"
Primiano Tucci919ca1e2019-08-21 20:26:58 +020040#include "test/gtest_and_gmock.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000041
Primiano Tucci4ff32df2023-07-27 16:33:34 +010042#define SKIP_IF_VSOCK_LOOPBACK_NOT_SUPPORTED() \
43 do { \
44 if (!UnixSocketRaw::CreateMayFail(SockFamily::kVsock, SockType::kStream) \
45 .Bind("vsock://1:10000")) { \
46 GTEST_SKIP() << "vsock testing skipped: loopback address unsupported.\n" \
47 << "Please run sudo modprobe vsock-loopback"; \
48 } \
49 } while (0)
50
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000051namespace perfetto {
Florian Mayerf7f0def2018-09-27 13:59:24 +010052namespace base {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000053namespace {
54
55using ::testing::_;
Primiano Tucci9b5d3362017-12-21 21:42:17 +010056using ::testing::AtLeast;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000057using ::testing::Invoke;
Primiano Tucci9b5d3362017-12-21 21:42:17 +010058using ::testing::InvokeWithoutArgs;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000059using ::testing::Mock;
60
Primiano Tuccie6edb062021-02-23 23:26:22 +010061ipc::TestSocket kTestSocket{"unix_socket_unittest"};
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000062
63class MockEventListener : public UnixSocket::EventListener {
64 public:
Daniele Di Proietto0023c082023-04-03 10:58:11 +000065 MOCK_METHOD(void, OnNewIncomingConnection, (UnixSocket*, UnixSocket*));
66 MOCK_METHOD(void, OnConnect, (UnixSocket*, bool), (override));
67 MOCK_METHOD(void, OnDisconnect, (UnixSocket*), (override));
68 MOCK_METHOD(void, OnDataAvailable, (UnixSocket*), (override));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000069
70 // GMock doesn't support mocking methods with non-copiable args.
71 void OnNewIncomingConnection(
72 UnixSocket* self,
73 std::unique_ptr<UnixSocket> new_connection) override {
74 incoming_connections_.emplace_back(std::move(new_connection));
75 OnNewIncomingConnection(self, incoming_connections_.back().get());
76 }
77
78 std::unique_ptr<UnixSocket> GetIncomingConnection() {
79 if (incoming_connections_.empty())
80 return nullptr;
81 std::unique_ptr<UnixSocket> sock = std::move(incoming_connections_.front());
82 incoming_connections_.pop_front();
83 return sock;
84 }
85
86 private:
87 std::list<std::unique_ptr<UnixSocket>> incoming_connections_;
88};
89
90class UnixSocketTest : public ::testing::Test {
91 protected:
Primiano Tuccie6edb062021-02-23 23:26:22 +010092 void SetUp() override { kTestSocket.Destroy(); }
93 void TearDown() override { kTestSocket.Destroy(); }
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000094
Florian Mayerf7f0def2018-09-27 13:59:24 +010095 TestTaskRunner task_runner_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000096 MockEventListener event_listener_;
97};
98
99TEST_F(UnixSocketTest, ConnectionFailureIfUnreachable) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100100 auto cli =
101 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
102 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000103 ASSERT_FALSE(cli->is_connected());
104 auto checkpoint = task_runner_.CreateCheckpoint("failure");
105 EXPECT_CALL(event_listener_, OnConnect(cli.get(), false))
Primiano Tucci9b5d3362017-12-21 21:42:17 +0100106 .WillOnce(InvokeWithoutArgs(checkpoint));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000107 task_runner_.RunUntilCheckpoint("failure");
108}
109
110// Both server and client should see an OnDisconnect() if the server drops
111// incoming connections immediately as they are created.
112TEST_F(UnixSocketTest, ConnectionImmediatelyDroppedByServer) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100113 auto srv =
114 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
115 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000116 ASSERT_TRUE(srv->is_listening());
117
118 // The server will immediately shutdown the connection upon
119 // OnNewIncomingConnection().
120 auto srv_did_shutdown = task_runner_.CreateCheckpoint("srv_did_shutdown");
121 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
122 .WillOnce(
123 Invoke([this, srv_did_shutdown](UnixSocket*, UnixSocket* new_conn) {
124 EXPECT_CALL(event_listener_, OnDisconnect(new_conn));
Florian Mayer48c139c2018-03-12 14:07:57 +0000125 new_conn->Shutdown(true);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000126 srv_did_shutdown();
127 }));
128
129 auto checkpoint = task_runner_.CreateCheckpoint("cli_connected");
Primiano Tuccie6edb062021-02-23 23:26:22 +0100130 auto cli =
131 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
132 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000133 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
Primiano Tucci9b5d3362017-12-21 21:42:17 +0100134 .WillOnce(InvokeWithoutArgs(checkpoint));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000135 task_runner_.RunUntilCheckpoint("cli_connected");
136 task_runner_.RunUntilCheckpoint("srv_did_shutdown");
137
138 // Trying to send something will trigger the disconnection notification.
139 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
140 EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
Primiano Tucci9b5d3362017-12-21 21:42:17 +0100141 .WillOnce(InvokeWithoutArgs(cli_disconnected));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100142
143 // On Windows the first send immediately after the disconnection succeeds, the
144 // kernel will detect the disconnection only later.
Primiano Tucci082503e2021-11-05 13:57:56 +0000145 cli->SendStr(".");
146 EXPECT_FALSE(cli->SendStr("should_fail_both_on_win_and_unix"));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000147 task_runner_.RunUntilCheckpoint("cli_disconnected");
148}
149
150TEST_F(UnixSocketTest, ClientAndServerExchangeData) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100151 auto srv =
152 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
153 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000154 ASSERT_TRUE(srv->is_listening());
155
Primiano Tuccie6edb062021-02-23 23:26:22 +0100156 auto cli =
157 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
158 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000159 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100160 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
161 .WillOnce(InvokeWithoutArgs(cli_connected));
162 auto srv_conn_seen = task_runner_.CreateCheckpoint("srv_conn_seen");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000163 auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
164 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100165 .WillOnce(Invoke([this, srv_conn_seen, srv_disconnected](
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000166 UnixSocket*, UnixSocket* srv_conn) {
167 EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
Primiano Tucci9b5d3362017-12-21 21:42:17 +0100168 .WillOnce(InvokeWithoutArgs(srv_disconnected));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100169 srv_conn_seen();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000170 }));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100171 task_runner_.RunUntilCheckpoint("srv_conn_seen");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000172 task_runner_.RunUntilCheckpoint("cli_connected");
173
174 auto srv_conn = event_listener_.GetIncomingConnection();
175 ASSERT_TRUE(srv_conn);
176 ASSERT_TRUE(cli->is_connected());
177
178 auto cli_did_recv = task_runner_.CreateCheckpoint("cli_did_recv");
179 EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
180 .WillOnce(Invoke([cli_did_recv](UnixSocket* s) {
181 ASSERT_EQ("srv>cli", s->ReceiveString());
182 cli_did_recv();
183 }));
184
185 auto srv_did_recv = task_runner_.CreateCheckpoint("srv_did_recv");
186 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn.get()))
187 .WillOnce(Invoke([srv_did_recv](UnixSocket* s) {
188 ASSERT_EQ("cli>srv", s->ReceiveString());
189 srv_did_recv();
190 }));
Primiano Tucci082503e2021-11-05 13:57:56 +0000191 ASSERT_TRUE(cli->SendStr("cli>srv"));
192 ASSERT_TRUE(srv_conn->SendStr("srv>cli"));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000193 task_runner_.RunUntilCheckpoint("cli_did_recv");
194 task_runner_.RunUntilCheckpoint("srv_did_recv");
195
196 // Check that Send/Receive() fails gracefully once the socket is closed.
197 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
198 EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
Primiano Tucci9b5d3362017-12-21 21:42:17 +0100199 .WillOnce(InvokeWithoutArgs(cli_disconnected));
Florian Mayer48c139c2018-03-12 14:07:57 +0000200 cli->Shutdown(true);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000201 char msg[4];
202 ASSERT_EQ(0u, cli->Receive(&msg, sizeof(msg)));
203 ASSERT_EQ("", cli->ReceiveString());
204 ASSERT_EQ(0u, srv_conn->Receive(&msg, sizeof(msg)));
205 ASSERT_EQ("", srv_conn->ReceiveString());
Primiano Tucci082503e2021-11-05 13:57:56 +0000206 ASSERT_FALSE(cli->SendStr("foo"));
207 ASSERT_FALSE(srv_conn->SendStr("bar"));
Florian Mayer48c139c2018-03-12 14:07:57 +0000208 srv->Shutdown(true);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000209 task_runner_.RunUntilCheckpoint("cli_disconnected");
210 task_runner_.RunUntilCheckpoint("srv_disconnected");
211}
212
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100213TEST_F(UnixSocketTest, ListenWithPassedSocketHandle) {
214 auto sock_raw =
Primiano Tuccie6edb062021-02-23 23:26:22 +0100215 UnixSocketRaw::CreateMayFail(kTestSocket.family(), SockType::kStream);
216 ASSERT_TRUE(sock_raw.Bind(kTestSocket.name()));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100217 auto fd = sock_raw.ReleaseFd();
218 auto srv = UnixSocket::Listen(std::move(fd), &event_listener_, &task_runner_,
Primiano Tuccie6edb062021-02-23 23:26:22 +0100219 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100220 ASSERT_TRUE(srv->is_listening());
221
222 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
Primiano Tuccie6edb062021-02-23 23:26:22 +0100223 auto cli =
224 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
225 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100226 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
227 .WillOnce(InvokeWithoutArgs(cli_connected));
228 auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
229 auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
230 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
231 .WillOnce(Invoke([this, srv_connected, srv_disconnected](
232 UnixSocket*, UnixSocket* srv_conn) {
233 // An empty OnDataAvailable might be raised to signal the EOF state.
234 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
235 .WillRepeatedly(
236 InvokeWithoutArgs([srv_conn] { srv_conn->ReceiveString(); }));
237 EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
238 .WillOnce(InvokeWithoutArgs(srv_disconnected));
239 srv_connected();
240 }));
241 task_runner_.RunUntilCheckpoint("srv_connected");
242 task_runner_.RunUntilCheckpoint("cli_connected");
243 ASSERT_TRUE(cli->is_connected());
244 cli.reset();
245 task_runner_.RunUntilCheckpoint("srv_disconnected");
246}
247
248// Mostly a stress tests. Connects kNumClients clients to the same server and
249// tests that all can exchange data and can see the expected sequence of events.
250TEST_F(UnixSocketTest, SeveralClients) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100251 auto srv =
252 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
253 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100254 ASSERT_TRUE(srv->is_listening());
255 constexpr size_t kNumClients = 32;
256 std::unique_ptr<UnixSocket> cli[kNumClients];
257
258 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
259 .Times(kNumClients)
260 .WillRepeatedly(Invoke([this](UnixSocket*, UnixSocket* s) {
261 EXPECT_CALL(event_listener_, OnDataAvailable(s))
262 .WillOnce(Invoke([](UnixSocket* t) {
263 ASSERT_EQ("PING", t->ReceiveString());
Primiano Tucci082503e2021-11-05 13:57:56 +0000264 ASSERT_TRUE(t->SendStr("PONG"));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100265 }));
266 }));
267
268 for (size_t i = 0; i < kNumClients; i++) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100269 cli[i] =
270 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
271 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100272 EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true))
273 .WillOnce(Invoke([](UnixSocket* s, bool success) {
274 ASSERT_TRUE(success);
Primiano Tucci082503e2021-11-05 13:57:56 +0000275 ASSERT_TRUE(s->SendStr("PING"));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100276 }));
277
278 auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
279 EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
280 .WillOnce(Invoke([checkpoint](UnixSocket* s) {
281 ASSERT_EQ("PONG", s->ReceiveString());
282 checkpoint();
283 }));
284 }
285
286 for (size_t i = 0; i < kNumClients; i++) {
287 task_runner_.RunUntilCheckpoint(std::to_string(i));
288 ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
289 }
290}
291
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100292TEST_F(UnixSocketTest, BlockingSend) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100293 auto srv =
294 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
295 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100296 ASSERT_TRUE(srv->is_listening());
297
298 auto all_frames_done = task_runner_.CreateCheckpoint("all_frames_done");
299 size_t total_bytes_received = 0;
300 static constexpr size_t kTotalBytes = 1024 * 1024 * 4;
301 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
302 .WillOnce(Invoke([this, &total_bytes_received, all_frames_done](
303 UnixSocket*, UnixSocket* srv_conn) {
304 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
305 .WillRepeatedly(
306 Invoke([&total_bytes_received, all_frames_done](UnixSocket* s) {
307 char buf[1024];
308 size_t res = s->Receive(buf, sizeof(buf));
309 total_bytes_received += res;
310 if (total_bytes_received == kTotalBytes)
311 all_frames_done();
312 }));
313 }));
314
315 // Override default timeout as this test can take time on the emulator.
316 static constexpr int kTimeoutMs = 60000 * 3;
317
318 // Perform the blocking send form another thread.
319 std::thread tx_thread([] {
320 TestTaskRunner tx_task_runner;
321 MockEventListener tx_events;
Primiano Tuccie6edb062021-02-23 23:26:22 +0100322 auto cli =
323 UnixSocket::Connect(kTestSocket.name(), &tx_events, &tx_task_runner,
324 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100325
326 auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
327 EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
328 .WillOnce(InvokeWithoutArgs(cli_connected));
329 tx_task_runner.RunUntilCheckpoint("cli_connected");
330
331 auto all_sent = tx_task_runner.CreateCheckpoint("all_sent");
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100332 std::string buf(1024 * 32, '\0');
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100333 tx_task_runner.PostTask([&cli, &buf, all_sent] {
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100334 for (size_t i = 0; i < kTotalBytes / buf.size(); i++)
335 cli->Send(buf.data(), buf.size());
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100336 all_sent();
337 });
338 tx_task_runner.RunUntilCheckpoint("all_sent", kTimeoutMs);
339 });
340
341 task_runner_.RunUntilCheckpoint("all_frames_done", kTimeoutMs);
342 tx_thread.join();
343}
344
345// Regression test for b/76155349 . If the receiver end disconnects while the
346// sender is in the middle of a large send(), the socket should gracefully give
347// up (i.e. Shutdown()) but not crash.
348TEST_F(UnixSocketTest, ReceiverDisconnectsDuringSend) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100349 auto srv =
350 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
351 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100352 ASSERT_TRUE(srv->is_listening());
353 static constexpr int kTimeoutMs = 30000;
354
355 auto receive_done = task_runner_.CreateCheckpoint("receive_done");
356 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
357 .WillOnce(Invoke([this, receive_done](UnixSocket*, UnixSocket* srv_conn) {
358 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
359 .WillOnce(Invoke([receive_done](UnixSocket* s) {
360 char buf[1024];
361 size_t res = s->Receive(buf, sizeof(buf));
362 ASSERT_EQ(1024u, res);
363 s->Shutdown(false /*notify*/);
364 receive_done();
365 }));
366 }));
367
368 // Perform the blocking send form another thread.
369 std::thread tx_thread([] {
370 TestTaskRunner tx_task_runner;
371 MockEventListener tx_events;
Primiano Tuccie6edb062021-02-23 23:26:22 +0100372 auto cli =
373 UnixSocket::Connect(kTestSocket.name(), &tx_events, &tx_task_runner,
374 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100375
376 auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
377 EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
378 .WillOnce(InvokeWithoutArgs(cli_connected));
379 tx_task_runner.RunUntilCheckpoint("cli_connected");
380
381 auto send_done = tx_task_runner.CreateCheckpoint("send_done");
382 static constexpr size_t kBufSize = 32 * 1024 * 1024;
383 std::unique_ptr<char[]> buf(new char[kBufSize]());
384 tx_task_runner.PostTask([&cli, &buf, send_done] {
385 cli->Send(buf.get(), kBufSize);
386 send_done();
387 });
388
389 tx_task_runner.RunUntilCheckpoint("send_done", kTimeoutMs);
390 });
391 task_runner_.RunUntilCheckpoint("receive_done", kTimeoutMs);
392 tx_thread.join();
393}
394
395TEST_F(UnixSocketTest, ReleaseSocket) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100396 auto srv =
397 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
398 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100399 ASSERT_TRUE(srv->is_listening());
400 auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
401 UnixSocket* peer = nullptr;
402 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
403 .WillOnce(
404 Invoke([srv_connected, &peer](UnixSocket*, UnixSocket* new_conn) {
405 peer = new_conn;
406 srv_connected();
407 }));
408
Primiano Tuccie6edb062021-02-23 23:26:22 +0100409 auto cli =
410 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
411 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100412 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
413 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
414 .WillOnce(InvokeWithoutArgs(cli_connected));
415 task_runner_.RunUntilCheckpoint("srv_connected");
416 task_runner_.RunUntilCheckpoint("cli_connected");
417 srv->Shutdown(true);
418
Primiano Tucci082503e2021-11-05 13:57:56 +0000419 cli->SendStr("test");
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100420
421 ASSERT_NE(peer, nullptr);
422 auto raw_sock = peer->ReleaseSocket();
423
424 EXPECT_CALL(event_listener_, OnDataAvailable(_)).Times(0);
425 task_runner_.RunUntilIdle();
426
Primiano Tucci082503e2021-11-05 13:57:56 +0000427 char buf[5];
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100428 ASSERT_TRUE(raw_sock);
Primiano Tucci082503e2021-11-05 13:57:56 +0000429 ASSERT_EQ(raw_sock.Receive(buf, sizeof(buf)), 4);
430 buf[sizeof(buf) - 1] = '\0';
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100431 ASSERT_STREQ(buf, "test");
432}
433
Primiano Tucci4ff32df2023-07-27 16:33:34 +0100434// Tests that the return value of GetSockAddr() returns a well formatted address
435// that can be passed to UnixSocket::Connect().
436TEST_F(UnixSocketTest, GetSockAddrTcp4) {
437 auto srv = UnixSocket::Listen("127.0.0.1:0", &event_listener_, &task_runner_,
438 SockFamily::kInet, SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100439 ASSERT_TRUE(srv->is_listening());
440
Primiano Tucci4ff32df2023-07-27 16:33:34 +0100441 auto cli =
442 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
443 SockFamily::kInet, SockType::kStream);
444 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
445 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
446 task_runner_.RunUntilCheckpoint("connected");
447}
448
449TEST_F(UnixSocketTest, GetSockAddrTcp6) {
450 auto srv = UnixSocket::Listen("[::1]:0", &event_listener_, &task_runner_,
451 SockFamily::kInet6, SockType::kStream);
452 ASSERT_TRUE(srv->is_listening());
453 auto cli =
454 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
455 SockFamily::kInet6, SockType::kStream);
456
457 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
458 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
459 task_runner_.RunUntilCheckpoint("connected");
460}
461
462#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
463 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
464 PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
465TEST_F(UnixSocketTest, GetSockAddrUnixLinked) {
466 TempDir tmp_dir = TempDir::Create();
467 std::string sock_path = tmp_dir.path() + "/test.sock";
468 auto srv = UnixSocket::Listen(sock_path, &event_listener_, &task_runner_,
469 SockFamily::kUnix, SockType::kStream);
470 ASSERT_TRUE(srv->is_listening());
471 EXPECT_EQ(sock_path, srv->GetSockAddr());
472 auto cli =
473 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
474 SockFamily::kUnix, SockType::kStream);
475 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
476 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
477 task_runner_.RunUntilCheckpoint("connected");
478 cli.reset();
479 srv.reset();
480 remove(sock_path.c_str());
481}
482#endif
483
484#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
485 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
486TEST_F(UnixSocketTest, GetSockAddrUnixAbstract) {
487 StackString<128> sock_name("@perfetto_sock_%d_%d", getpid(), rand() % 100000);
488
489 auto srv =
490 UnixSocket::Listen(sock_name.ToStdString(), &event_listener_,
491 &task_runner_, SockFamily::kUnix, SockType::kStream);
492 ASSERT_TRUE(srv->is_listening());
493 EXPECT_EQ(sock_name.ToStdString(), srv->GetSockAddr());
494 auto cli =
495 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
496 SockFamily::kUnix, SockType::kStream);
497 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
498 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
499 task_runner_.RunUntilCheckpoint("connected");
500}
501#endif
502
503#if (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
504 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID))
505TEST_F(UnixSocketTest, GetSockAddrVsock) {
506 SKIP_IF_VSOCK_LOOPBACK_NOT_SUPPORTED();
507
508 auto srv = UnixSocket::Listen("vsock://1:-1", &event_listener_, &task_runner_,
509 SockFamily::kVsock, SockType::kStream);
510 ASSERT_TRUE(srv->is_listening());
511 auto cli =
512 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
513 SockFamily::kVsock, SockType::kStream);
514
515 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
516 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
517 task_runner_.RunUntilCheckpoint("connected");
518}
519#endif
520
521TEST_F(UnixSocketTest, TcpStream) {
522 // Listen on a random port.
523 std::unique_ptr<UnixSocket> srv =
524 UnixSocket::Listen("127.0.0.1:0", &event_listener_, &task_runner_,
525 SockFamily::kInet, SockType::kStream);
526 ASSERT_TRUE(srv->is_listening());
527 std::string host_and_port = srv->GetSockAddr();
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100528 constexpr size_t kNumClients = 3;
529 std::unique_ptr<UnixSocket> cli[kNumClients];
530 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
531 .Times(kNumClients)
532 .WillRepeatedly(Invoke([&](UnixSocket*, UnixSocket* s) {
533 // OnDisconnect() might spuriously happen depending on the dtor order.
534 EXPECT_CALL(event_listener_, OnDisconnect(s)).Times(AtLeast(0));
535 EXPECT_CALL(event_listener_, OnDataAvailable(s))
536 .WillRepeatedly(Invoke([](UnixSocket* cli_sock) {
537 cli_sock->ReceiveString(); // Read connection EOF;
538 }));
Primiano Tucci082503e2021-11-05 13:57:56 +0000539 ASSERT_TRUE(s->SendStr("welcome"));
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100540 }));
541
542 for (size_t i = 0; i < kNumClients; i++) {
543 cli[i] = UnixSocket::Connect(host_and_port, &event_listener_, &task_runner_,
544 SockFamily::kInet, SockType::kStream);
545 auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
546 EXPECT_CALL(event_listener_, OnDisconnect(cli[i].get())).Times(AtLeast(0));
547 EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true));
548 EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
549 .WillRepeatedly(Invoke([checkpoint](UnixSocket* s) {
550 auto str = s->ReceiveString();
551 if (str == "")
552 return; // Connection EOF.
553 ASSERT_EQ("welcome", str);
554 checkpoint();
555 }));
556 }
557
558 for (size_t i = 0; i < kNumClients; i++) {
559 task_runner_.RunUntilCheckpoint(std::to_string(i));
560 ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
561 }
562}
563
564// ---------------------------------
565// Posix-only tests below this point
566// ---------------------------------
567
568#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Primiano Tuccie6edb062021-02-23 23:26:22 +0100569
570// Tests the SockPeerCredMode::kIgnore logic.
571TEST_F(UnixSocketTest, IgnorePeerCredentials) {
572 auto srv =
573 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
574 kTestSocket.family(), SockType::kStream);
575 ASSERT_TRUE(srv->is_listening());
576 auto cli1_connected = task_runner_.CreateCheckpoint("cli1_connected");
577 auto cli1 = UnixSocket::Connect(kTestSocket.name(), &event_listener_,
578 &task_runner_, kTestSocket.family(),
579 SockType::kStream, SockPeerCredMode::kIgnore);
580 EXPECT_CALL(event_listener_, OnConnect(cli1.get(), true))
581 .WillOnce(InvokeWithoutArgs(cli1_connected));
582
583 auto cli2_connected = task_runner_.CreateCheckpoint("cli2_connected");
584 auto cli2 = UnixSocket::Connect(
585 kTestSocket.name(), &event_listener_, &task_runner_, kTestSocket.family(),
586 SockType::kStream, SockPeerCredMode::kReadOnConnect);
587 EXPECT_CALL(event_listener_, OnConnect(cli2.get(), true))
588 .WillOnce(InvokeWithoutArgs(cli2_connected));
589
590 task_runner_.RunUntilCheckpoint("cli1_connected");
591 task_runner_.RunUntilCheckpoint("cli2_connected");
592
593 ASSERT_EQ(cli1->peer_uid_posix(/*skip_check_for_testing=*/true), kInvalidUid);
594 ASSERT_EQ(cli2->peer_uid_posix(), geteuid());
595#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
596 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
597 ASSERT_EQ(cli1->peer_pid_linux(/*skip_check_for_testing=*/true), kInvalidPid);
598 ASSERT_EQ(cli2->peer_pid_linux(), getpid());
599#endif
600}
601
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100602// Checks that the peer_uid() is retained after the client disconnects. The IPC
603// layer needs to rely on this to validate messages received immediately before
604// a client disconnects.
605TEST_F(UnixSocketTest, PeerCredentialsRetainedAfterDisconnect) {
Primiano Tuccie6edb062021-02-23 23:26:22 +0100606 auto srv =
607 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
608 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100609 ASSERT_TRUE(srv->is_listening());
610 UnixSocket* srv_client_conn = nullptr;
611 auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
612 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
613 .WillOnce(Invoke([&srv_client_conn, srv_connected](UnixSocket*,
614 UnixSocket* srv_conn) {
615 srv_client_conn = srv_conn;
616 EXPECT_EQ(geteuid(), static_cast<uint32_t>(srv_conn->peer_uid_posix()));
617#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
618 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
619 EXPECT_EQ(getpid(), static_cast<pid_t>(srv_conn->peer_pid_linux()));
620#endif
621 srv_connected();
622 }));
623 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
Primiano Tuccie6edb062021-02-23 23:26:22 +0100624 auto cli =
625 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
626 kTestSocket.family(), SockType::kStream);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100627 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
628 .WillOnce(InvokeWithoutArgs(cli_connected));
629
630 task_runner_.RunUntilCheckpoint("cli_connected");
631 task_runner_.RunUntilCheckpoint("srv_connected");
632 ASSERT_NE(nullptr, srv_client_conn);
633 ASSERT_TRUE(srv_client_conn->is_connected());
634
635 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
636 EXPECT_CALL(event_listener_, OnDisconnect(srv_client_conn))
637 .WillOnce(InvokeWithoutArgs(cli_disconnected));
638
639 // TODO(primiano): when the a peer disconnects, the other end receives a
640 // spurious OnDataAvailable() that needs to be acked with a Receive() to read
641 // the EOF. See b/69536434.
642 EXPECT_CALL(event_listener_, OnDataAvailable(srv_client_conn))
643 .WillOnce(Invoke([](UnixSocket* sock) { sock->ReceiveString(); }));
644
645 cli.reset();
646 task_runner_.RunUntilCheckpoint("cli_disconnected");
647 ASSERT_FALSE(srv_client_conn->is_connected());
648 EXPECT_EQ(geteuid(),
649 static_cast<uint32_t>(srv_client_conn->peer_uid_posix()));
650#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
651 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
652 EXPECT_EQ(getpid(), static_cast<pid_t>(srv_client_conn->peer_pid_linux()));
653#endif
654}
Florian Mayere1cd07d2018-07-31 11:56:41 +0100655
656TEST_F(UnixSocketTest, ClientAndServerExchangeFDs) {
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100657 static constexpr char cli_str[] = "cli>srv";
658 static constexpr char srv_str[] = "srv>cli";
Primiano Tuccie6edb062021-02-23 23:26:22 +0100659 auto srv =
660 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
661 kTestSocket.family(), SockType::kStream);
Florian Mayere1cd07d2018-07-31 11:56:41 +0100662 ASSERT_TRUE(srv->is_listening());
663
Primiano Tuccie6edb062021-02-23 23:26:22 +0100664 auto cli =
665 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
666 kTestSocket.family(), SockType::kStream);
Florian Mayere1cd07d2018-07-31 11:56:41 +0100667 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
668 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
669 auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
670 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
671 .WillOnce(Invoke([this, cli_connected, srv_disconnected](
672 UnixSocket*, UnixSocket* srv_conn) {
673 EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
674 .WillOnce(InvokeWithoutArgs(srv_disconnected));
675 cli_connected();
676 }));
677 task_runner_.RunUntilCheckpoint("cli_connected");
678
679 auto srv_conn = event_listener_.GetIncomingConnection();
680 ASSERT_TRUE(srv_conn);
681 ASSERT_TRUE(cli->is_connected());
682
Florian Mayerb03fd282018-10-03 16:05:16 +0100683 ScopedFile null_fd(base::OpenFile("/dev/null", O_RDONLY));
684 ScopedFile zero_fd(base::OpenFile("/dev/zero", O_RDONLY));
Florian Mayere1cd07d2018-07-31 11:56:41 +0100685
686 auto cli_did_recv = task_runner_.CreateCheckpoint("cli_did_recv");
687 EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
688 .WillRepeatedly(Invoke([cli_did_recv](UnixSocket* s) {
Florian Mayerf7f0def2018-09-27 13:59:24 +0100689 ScopedFile fd_buf[3];
Florian Mayere1cd07d2018-07-31 11:56:41 +0100690 char buf[sizeof(cli_str)];
Florian Mayerf7f0def2018-09-27 13:59:24 +0100691 if (!s->Receive(buf, sizeof(buf), fd_buf, ArraySize(fd_buf)))
Florian Mayere1cd07d2018-07-31 11:56:41 +0100692 return;
693 ASSERT_STREQ(srv_str, buf);
694 ASSERT_NE(*fd_buf[0], -1);
695 ASSERT_NE(*fd_buf[1], -1);
696 ASSERT_EQ(*fd_buf[2], -1);
697
698 char rd_buf[1];
699 // /dev/null
700 ASSERT_EQ(read(*fd_buf[0], rd_buf, sizeof(rd_buf)), 0);
701 // /dev/zero
702 ASSERT_EQ(read(*fd_buf[1], rd_buf, sizeof(rd_buf)), 1);
703 cli_did_recv();
704 }));
705
706 auto srv_did_recv = task_runner_.CreateCheckpoint("srv_did_recv");
707 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn.get()))
708 .WillRepeatedly(Invoke([srv_did_recv](UnixSocket* s) {
Florian Mayerf7f0def2018-09-27 13:59:24 +0100709 ScopedFile fd_buf[3];
Florian Mayere1cd07d2018-07-31 11:56:41 +0100710 char buf[sizeof(srv_str)];
Florian Mayerf7f0def2018-09-27 13:59:24 +0100711 if (!s->Receive(buf, sizeof(buf), fd_buf, ArraySize(fd_buf)))
Florian Mayere1cd07d2018-07-31 11:56:41 +0100712 return;
713 ASSERT_STREQ(cli_str, buf);
714 ASSERT_NE(*fd_buf[0], -1);
715 ASSERT_NE(*fd_buf[1], -1);
716 ASSERT_EQ(*fd_buf[2], -1);
717
718 char rd_buf[1];
719 // /dev/null
720 ASSERT_EQ(read(*fd_buf[0], rd_buf, sizeof(rd_buf)), 0);
721 // /dev/zero
722 ASSERT_EQ(read(*fd_buf[1], rd_buf, sizeof(rd_buf)), 1);
723 srv_did_recv();
724 }));
725
726 int buf_fd[2] = {null_fd.get(), zero_fd.get()};
727
Florian Mayer74e3fb42020-01-31 09:27:34 +0000728 ASSERT_TRUE(
729 cli->Send(cli_str, sizeof(cli_str), buf_fd, base::ArraySize(buf_fd)));
Florian Mayere1cd07d2018-07-31 11:56:41 +0100730 ASSERT_TRUE(srv_conn->Send(srv_str, sizeof(srv_str), buf_fd,
Florian Mayer74e3fb42020-01-31 09:27:34 +0000731 base::ArraySize(buf_fd)));
Florian Mayere1cd07d2018-07-31 11:56:41 +0100732 task_runner_.RunUntilCheckpoint("srv_did_recv");
733 task_runner_.RunUntilCheckpoint("cli_did_recv");
734
735 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
736 EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
737 .WillOnce(InvokeWithoutArgs(cli_disconnected));
738 cli->Shutdown(true);
739 srv->Shutdown(true);
740 task_runner_.RunUntilCheckpoint("srv_disconnected");
741 task_runner_.RunUntilCheckpoint("cli_disconnected");
742}
743
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000744// Creates two processes. The server process creates a file and passes it over
745// the socket to the client. Both processes mmap the file in shared mode and
746// check that they see the same contents.
747TEST_F(UnixSocketTest, SharedMemory) {
Primiano Tucci76499cd2018-11-21 10:54:04 +0100748 Pipe pipe = Pipe::Create();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000749 pid_t pid = fork();
750 ASSERT_GE(pid, 0);
751 constexpr size_t kTmpSize = 4096;
752
753 if (pid == 0) {
754 // Child process.
Florian Mayerf7f0def2018-09-27 13:59:24 +0100755 TempFile scoped_tmp = TempFile::CreateUnlinked();
Primiano Tucci941b2212018-03-14 22:46:31 +0000756 int tmp_fd = scoped_tmp.fd();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000757 ASSERT_FALSE(ftruncate(tmp_fd, kTmpSize));
758 char* mem = reinterpret_cast<char*>(
759 mmap(nullptr, kTmpSize, PROT_READ | PROT_WRITE, MAP_SHARED, tmp_fd, 0));
760 ASSERT_NE(nullptr, mem);
761 memcpy(mem, "shm rocks", 10);
762
Primiano Tuccie6edb062021-02-23 23:26:22 +0100763 auto srv =
764 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
765 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000766 ASSERT_TRUE(srv->is_listening());
767 // Signal the other process that it can connect.
Primiano Tucci76499cd2018-11-21 10:54:04 +0100768 ASSERT_EQ(1, base::WriteAll(*pipe.wr, ".", 1));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000769 auto checkpoint = task_runner_.CreateCheckpoint("change_seen_by_server");
770 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
771 .WillOnce(Invoke(
772 [this, tmp_fd, checkpoint, mem](UnixSocket*, UnixSocket* new_conn) {
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100773 ASSERT_EQ(geteuid(),
774 static_cast<uint32_t>(new_conn->peer_uid_posix()));
Florian Mayer74e3fb42020-01-31 09:27:34 +0000775 ASSERT_TRUE(new_conn->Send("txfd", 5, tmp_fd));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000776 // Wait for the client to change this again.
777 EXPECT_CALL(event_listener_, OnDataAvailable(new_conn))
778 .WillOnce(Invoke([checkpoint, mem](UnixSocket* s) {
779 ASSERT_EQ("change notify", s->ReceiveString());
780 ASSERT_STREQ("rock more", mem);
781 checkpoint();
782 }));
783 }));
784 task_runner_.RunUntilCheckpoint("change_seen_by_server");
785 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&event_listener_));
786 _exit(0);
787 } else {
788 char sync_cmd = '\0';
Primiano Tucci76499cd2018-11-21 10:54:04 +0100789 ASSERT_EQ(1, PERFETTO_EINTR(read(*pipe.rd, &sync_cmd, 1)));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000790 ASSERT_EQ('.', sync_cmd);
Primiano Tuccie6edb062021-02-23 23:26:22 +0100791 auto cli =
792 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
793 kTestSocket.family(), SockType::kStream);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000794 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
795 auto checkpoint = task_runner_.CreateCheckpoint("change_seen_by_client");
796 EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
797 .WillOnce(Invoke([checkpoint](UnixSocket* s) {
798 char msg[32];
Florian Mayerf7f0def2018-09-27 13:59:24 +0100799 ScopedFile fd;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000800 ASSERT_EQ(5u, s->Receive(msg, sizeof(msg), &fd));
801 ASSERT_STREQ("txfd", msg);
802 ASSERT_TRUE(fd);
803 char* mem = reinterpret_cast<char*>(mmap(
804 nullptr, kTmpSize, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0));
805 ASSERT_NE(nullptr, mem);
806 mem[9] = '\0'; // Just to get a clean error in case of test failure.
807 ASSERT_STREQ("shm rocks", mem);
808
809 // Now change the shared memory and ping the other process.
810 memcpy(mem, "rock more", 10);
Primiano Tucci082503e2021-11-05 13:57:56 +0000811 ASSERT_TRUE(s->SendStr("change notify"));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000812 checkpoint();
813 }));
814 task_runner_.RunUntilCheckpoint("change_seen_by_client");
815 int st = 0;
816 PERFETTO_EINTR(waitpid(pid, &st, 0));
817 ASSERT_FALSE(WIFSIGNALED(st)) << "Server died with signal " << WTERMSIG(st);
818 EXPECT_TRUE(WIFEXITED(st));
819 ASSERT_EQ(0, WEXITSTATUS(st));
820 }
821}
822
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100823TEST_F(UnixSocketTest, ShiftMsgHdrSendPartialFirst) {
824 // Send a part of the first iov, then send the rest.
825 struct iovec iov[2] = {};
826 char hello[] = "hello";
827 char world[] = "world";
828 iov[0].iov_base = &hello[0];
829 iov[0].iov_len = base::ArraySize(hello);
830
831 iov[1].iov_base = &world[0];
832 iov[1].iov_len = base::ArraySize(world);
833
834 struct msghdr hdr = {};
835 hdr.msg_iov = iov;
836 hdr.msg_iovlen = base::ArraySize(iov);
837
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100838 UnixSocketRaw::ShiftMsgHdrPosix(1, &hdr);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100839 EXPECT_NE(hdr.msg_iov, nullptr);
840 EXPECT_EQ(hdr.msg_iov[0].iov_base, &hello[1]);
841 EXPECT_EQ(hdr.msg_iov[1].iov_base, &world[0]);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200842 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 2);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100843 EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "ello");
844 EXPECT_EQ(iov[0].iov_len, base::ArraySize(hello) - 1);
845
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100846 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(hello) - 1, &hdr);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100847 EXPECT_EQ(hdr.msg_iov, &iov[1]);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200848 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 1);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100849 EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), world);
850 EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world));
851
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100852 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(world), &hdr);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100853 EXPECT_EQ(hdr.msg_iov, nullptr);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200854 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100855}
856
857TEST_F(UnixSocketTest, ShiftMsgHdrSendFirstAndPartial) {
858 // Send first iov and part of the second iov, then send the rest.
859 struct iovec iov[2] = {};
860 char hello[] = "hello";
861 char world[] = "world";
862 iov[0].iov_base = &hello[0];
863 iov[0].iov_len = base::ArraySize(hello);
864
865 iov[1].iov_base = &world[0];
866 iov[1].iov_len = base::ArraySize(world);
867
868 struct msghdr hdr = {};
869 hdr.msg_iov = iov;
870 hdr.msg_iovlen = base::ArraySize(iov);
871
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100872 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(hello) + 1, &hdr);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100873 EXPECT_NE(hdr.msg_iov, nullptr);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200874 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 1);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100875 EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "orld");
876 EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world) - 1);
877
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100878 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(world) - 1, &hdr);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100879 EXPECT_EQ(hdr.msg_iov, nullptr);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200880 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100881}
882
883TEST_F(UnixSocketTest, ShiftMsgHdrSendEverything) {
884 // Send everything at once.
885 struct iovec iov[2] = {};
886 char hello[] = "hello";
887 char world[] = "world";
888 iov[0].iov_base = &hello[0];
889 iov[0].iov_len = base::ArraySize(hello);
890
891 iov[1].iov_base = &world[0];
892 iov[1].iov_len = base::ArraySize(world);
893
894 struct msghdr hdr = {};
895 hdr.msg_iov = iov;
896 hdr.msg_iovlen = base::ArraySize(iov);
897
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100898 UnixSocketRaw::ShiftMsgHdrPosix(
899 base::ArraySize(world) + base::ArraySize(hello), &hdr);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100900 EXPECT_EQ(hdr.msg_iov, nullptr);
Primiano Tucci919ca1e2019-08-21 20:26:58 +0200901 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100902}
903
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100904// For use in PartialSendMsgAll template argument. Cannot be a lambda.
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100905int RollbackSigaction(const struct sigaction* act) {
906 return sigaction(SIGWINCH, act, nullptr);
907}
908
909TEST_F(UnixSocketTest, PartialSendMsgAll) {
Primiano Tucci43ebf4d2019-01-02 20:04:34 +0100910 UnixSocketRaw send_sock;
911 UnixSocketRaw recv_sock;
Primiano Tuccid4be9662019-10-22 17:45:13 -0400912 std::tie(send_sock, recv_sock) =
Primiano Tuccie6edb062021-02-23 23:26:22 +0100913 UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
Primiano Tucci43ebf4d2019-01-02 20:04:34 +0100914 ASSERT_TRUE(send_sock);
915 ASSERT_TRUE(recv_sock);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100916
917 // Set bufsize to minimum.
918 int bufsize = 1024;
Primiano Tucci43ebf4d2019-01-02 20:04:34 +0100919 ASSERT_EQ(setsockopt(send_sock.fd(), SOL_SOCKET, SO_SNDBUF, &bufsize,
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100920 sizeof(bufsize)),
921 0);
Primiano Tucci43ebf4d2019-01-02 20:04:34 +0100922 ASSERT_EQ(setsockopt(recv_sock.fd(), SOL_SOCKET, SO_RCVBUF, &bufsize,
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100923 sizeof(bufsize)),
924 0);
925
926 // Send something larger than send + recv kernel buffers combined to make
927 // sendmsg block.
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100928 std::string send_buf(8192, '\0');
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100929 // Make MSAN happy.
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100930 for (size_t i = 0; i < send_buf.size(); ++i)
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100931 send_buf[i] = static_cast<char>(i % 256);
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100932 std::string recv_buf(send_buf.size(), '\0');
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100933
934 // Need to install signal handler to cause the interrupt to happen.
935 // man 3 pthread_kill:
936 // Signal dispositions are process-wide: if a signal handler is
937 // installed, the handler will be invoked in the thread thread, but if
938 // the disposition of the signal is "stop", "continue", or "terminate",
939 // this action will affect the whole process.
940 struct sigaction oldact;
941 struct sigaction newact = {};
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100942 newact.sa_handler = [](int) {};
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100943 ASSERT_EQ(sigaction(SIGWINCH, &newact, &oldact), 0);
944 base::ScopedResource<const struct sigaction*, RollbackSigaction, nullptr>
945 rollback(&oldact);
946
947 auto blocked_thread = pthread_self();
Primiano Tucci43ebf4d2019-01-02 20:04:34 +0100948 std::thread th([blocked_thread, &recv_sock, &recv_buf] {
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100949 ssize_t rd = PERFETTO_EINTR(read(recv_sock.fd(), &recv_buf[0], 1));
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100950 ASSERT_EQ(rd, 1);
951 // We are now sure the other thread is in sendmsg, interrupt send.
952 ASSERT_EQ(pthread_kill(blocked_thread, SIGWINCH), 0);
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100953 // Drain the socket to allow SendMsgAllPosix to succeed.
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100954 size_t offset = 1;
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100955 while (offset < recv_buf.size()) {
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100956 rd = PERFETTO_EINTR(
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100957 read(recv_sock.fd(), &recv_buf[offset], recv_buf.size() - offset));
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100958 ASSERT_GE(rd, 0);
959 offset += static_cast<size_t>(rd);
960 }
961 });
962
963 // Test sending the send_buf in several chunks as an iov to exercise the
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100964 // more complicated code-paths of SendMsgAllPosix.
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100965 struct msghdr hdr = {};
966 struct iovec iov[4];
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100967 ASSERT_EQ(send_buf.size() % base::ArraySize(iov), 0u)
968 << "Cannot split buffer into even pieces.";
969 const size_t kChunkSize = send_buf.size() / base::ArraySize(iov);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100970 for (size_t i = 0; i < base::ArraySize(iov); ++i) {
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100971 iov[i].iov_base = &send_buf[i * kChunkSize];
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100972 iov[i].iov_len = kChunkSize;
973 }
974 hdr.msg_iov = iov;
975 hdr.msg_iovlen = base::ArraySize(iov);
976
Primiano Tuccieb7e3662021-01-07 21:30:40 +0100977 ASSERT_EQ(send_sock.SendMsgAllPosix(&hdr),
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100978 static_cast<ssize_t>(send_buf.size()));
Primiano Tucci43ebf4d2019-01-02 20:04:34 +0100979 send_sock.Shutdown();
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100980 th.join();
981 // Make sure the re-entry logic was actually triggered.
982 ASSERT_EQ(hdr.msg_iov, nullptr);
Primiano Tuccib3deb5e2021-10-19 11:45:30 +0100983 ASSERT_EQ(memcmp(&send_buf[0], &recv_buf[0], send_buf.size()), 0);
Florian Mayerf3c0ac82018-10-02 11:53:55 +0100984}
Primiano Tuccie57ed092021-12-07 14:00:50 +0000985
986// Regression test for b/193234818. SO_SNDTIMEO is unreliable on most systems.
987// It doesn't guarantee that the whole send() call blocks for at most X, as the
988// kernel rearms the timeout if the send buffers frees up and allows a partial
989// send. This test reproduces the issue 100% on Mac. Unfortunately on Linux the
990// repro seem to happen only when a suspend happens in the middle.
991TEST_F(UnixSocketTest, BlockingSendTimeout) {
992 TestTaskRunner ttr;
993 UnixSocketRaw send_sock;
994 UnixSocketRaw recv_sock;
995 std::tie(send_sock, recv_sock) =
996 UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
997
998 auto blocking_send_done = ttr.CreateCheckpoint("blocking_send_done");
999
1000 std::thread tx_thread([&] {
1001 // Fill the tx buffer in non-blocking mode.
1002 send_sock.SetBlocking(false);
1003 char buf[1024 * 16]{};
1004 while (send_sock.Send(buf, sizeof(buf)) > 0) {
1005 }
1006
1007 // Then do a blocking send. It should return a partial value within the tx
1008 // timeout.
1009 send_sock.SetBlocking(true);
1010 send_sock.SetTxTimeout(10);
1011 ASSERT_LT(send_sock.Send(buf, sizeof(buf)),
1012 static_cast<ssize_t>(sizeof(buf)));
1013 ttr.PostTask(blocking_send_done);
1014 });
1015
1016 // This task needs to be slow enough so that doesn't unblock the send, but
1017 // fast enough so that within a blocking cycle, the send re-attempts and
1018 // re-arms the timeout.
1019 PeriodicTask read_slowly_task(&ttr);
1020 PeriodicTask::Args args;
1021 args.period_ms = 1; // Read 1 byte every ms (1 KiB/s).
1022 args.task = [&] {
1023 char rxbuf[1]{};
1024 recv_sock.Receive(rxbuf, sizeof(rxbuf));
1025 };
1026 read_slowly_task.Start(args);
1027
1028 ttr.RunUntilCheckpoint("blocking_send_done");
1029 read_slowly_task.Reset();
1030 tx_thread.join();
1031}
Ryan Savitski8eebce52022-07-25 22:06:39 +01001032
1033#if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
1034TEST_F(UnixSocketTest, SetsCloexec) {
1035 // CLOEXEC set when constructing sockets through helper:
1036 {
1037 auto raw = UnixSocketRaw::CreateMayFail(base::SockFamily::kUnix,
1038 SockType::kStream);
1039 int flags = fcntl(raw.fd(), F_GETFD, 0);
1040 EXPECT_TRUE(flags & FD_CLOEXEC);
1041 }
1042 // CLOEXEC set when creating a UnixSocketRaw out of an existing fd:
1043 {
1044 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
1045 int flags = fcntl(fd, F_GETFD, 0);
1046 EXPECT_FALSE(flags & FD_CLOEXEC);
1047
1048 auto raw = UnixSocketRaw(ScopedSocketHandle(fd), base::SockFamily::kUnix,
1049 SockType::kStream);
1050 flags = fcntl(raw.fd(), F_GETFD, 0);
1051 EXPECT_TRUE(flags & FD_CLOEXEC);
1052 }
1053}
1054#endif // !OS_FUCHSIA
1055
Primiano Tuccieb7e3662021-01-07 21:30:40 +01001056#endif // !OS_WIN
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001057
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001058#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1059 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
1060 PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
1061
1062// Regression test for b/239725760.
1063TEST_F(UnixSocketTest, Sockaddr_FilesystemLinked) {
1064 TempDir tmp_dir = TempDir::Create();
1065 std::string sock_path = tmp_dir.path() + "/test.sock";
1066 auto srv = UnixSocket::Listen(sock_path, &event_listener_, &task_runner_,
1067 SockFamily::kUnix, SockType::kStream);
Primiano Tucci868e4db2022-07-28 19:44:44 +01001068 ASSERT_TRUE(srv && srv->is_listening());
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001069 ASSERT_TRUE(FileExists(sock_path));
1070
1071 // Create a raw socket and manually connect to that (to avoid getting affected
1072 // by accidental future bugs in the logic that populates struct sockaddr_un).
1073 auto cli = UnixSocketRaw::CreateMayFail(SockFamily::kUnix, SockType::kStream);
1074 struct sockaddr_un addr {};
1075 addr.sun_family = AF_UNIX;
1076 StringCopy(addr.sun_path, sock_path.c_str(), sizeof(addr.sun_path));
1077 ASSERT_EQ(0, connect(cli.fd(), reinterpret_cast<struct sockaddr*>(&addr),
1078 sizeof(addr)));
1079 cli.Shutdown();
1080 remove(sock_path.c_str());
1081}
Primiano Tucci868e4db2022-07-28 19:44:44 +01001082#endif // OS_LINUX || OS_ANDROID || OS_MAC
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001083
Primiano Tucci868e4db2022-07-28 19:44:44 +01001084#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1085 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001086// Regression test for b/239725760.
Primiano Tucci868e4db2022-07-28 19:44:44 +01001087// Abstract sockets are not supported on Mac OS.
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001088TEST_F(UnixSocketTest, Sockaddr_AbstractUnix) {
1089 StackString<128> sock_name("@perfetto_test_%d_%d", getpid(), rand() % 100000);
1090 auto srv =
1091 UnixSocket::Listen(sock_name.ToStdString(), &event_listener_,
1092 &task_runner_, SockFamily::kUnix, SockType::kStream);
Primiano Tucci868e4db2022-07-28 19:44:44 +01001093 ASSERT_TRUE(srv && srv->is_listening());
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001094
1095 auto cli = UnixSocketRaw::CreateMayFail(SockFamily::kUnix, SockType::kStream);
1096 struct sockaddr_un addr {};
1097 addr.sun_family = AF_UNIX;
1098 StringCopy(addr.sun_path, sock_name.c_str(), sizeof(addr.sun_path));
1099 addr.sun_path[0] = '\0';
1100 auto addr_len = static_cast<socklen_t>(
1101 __builtin_offsetof(sockaddr_un, sun_path) + sock_name.len());
1102 ASSERT_EQ(0, connect(cli.fd(), reinterpret_cast<struct sockaddr*>(&addr),
1103 addr_len));
1104}
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001105
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001106TEST_F(UnixSocketTest, VSockStream) {
Primiano Tucci4ff32df2023-07-27 16:33:34 +01001107 SKIP_IF_VSOCK_LOOPBACK_NOT_SUPPORTED();
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001108
Primiano Tucci4ff32df2023-07-27 16:33:34 +01001109 // Set up the server. Use the loopback CID (1) and a random port number.
1110 auto srv = UnixSocket::Listen("vsock://1:-1", &event_listener_, &task_runner_,
1111 SockFamily::kVsock, SockType::kStream);
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001112 ASSERT_TRUE(srv && srv->is_listening());
1113
1114 std::unique_ptr<UnixSocket> prod;
1115 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
1116 .WillOnce(Invoke([&](UnixSocket*, UnixSocket* s) {
1117 // OnDisconnect() might spuriously happen depending on the dtor order.
1118 EXPECT_CALL(event_listener_, OnDisconnect(s)).Times(AtLeast(0));
1119 EXPECT_CALL(event_listener_, OnDataAvailable(s))
1120 .WillRepeatedly(Invoke([](UnixSocket* prod_sock) {
1121 prod_sock->ReceiveString(); // Read connection EOF;
1122 }));
1123 ASSERT_TRUE(s->SendStr("welcome"));
1124 }));
1125
1126 // Set up the client.
1127 prod =
Primiano Tucci4ff32df2023-07-27 16:33:34 +01001128 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
1129 SockFamily::kVsock, SockType::kStream);
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001130 auto checkpoint = task_runner_.CreateCheckpoint("prod_connected");
1131 EXPECT_CALL(event_listener_, OnDisconnect(prod.get())).Times(AtLeast(0));
1132 EXPECT_CALL(event_listener_, OnConnect(prod.get(), true));
1133 EXPECT_CALL(event_listener_, OnDataAvailable(prod.get()))
1134 .WillRepeatedly(Invoke([checkpoint](UnixSocket* s) {
1135 auto str = s->ReceiveString();
Primiano Tucci4ff32df2023-07-27 16:33:34 +01001136 if (str.empty())
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001137 return; // Connection EOF.
1138 ASSERT_EQ("welcome", str);
1139 checkpoint();
1140 }));
1141
1142 task_runner_.RunUntilCheckpoint("prod_connected");
1143 ASSERT_TRUE(Mock::VerifyAndClearExpectations(prod.get()));
1144}
Primiano Tucci868e4db2022-07-28 19:44:44 +01001145#endif // OS_LINUX || OS_ANDROID
Primiano Tucci94e94bb2022-07-26 20:19:30 +01001146
Primiano Tuccib0959042023-06-09 17:24:09 +01001147TEST_F(UnixSocketTest, GetSockFamily) {
1148 ASSERT_EQ(GetSockFamily(""), SockFamily::kUnspec);
1149 ASSERT_EQ(GetSockFamily("/path/to/sock"), SockFamily::kUnix);
1150 ASSERT_EQ(GetSockFamily("local_dir_sock"), SockFamily::kUnix);
1151 ASSERT_EQ(GetSockFamily("@abstract"), SockFamily::kUnix);
1152 ASSERT_EQ(GetSockFamily("0.0.0.0:80"), SockFamily::kInet);
1153 ASSERT_EQ(GetSockFamily("127.0.0.1:80"), SockFamily::kInet);
1154 ASSERT_EQ(GetSockFamily("[effe::acca]:1234"), SockFamily::kInet6);
1155 ASSERT_EQ(GetSockFamily("[::1]:123456"), SockFamily::kInet6);
Chinglin Yu6e65ed82023-05-25 09:04:43 +00001156#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1157 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
1158 ASSERT_EQ(GetSockFamily("vsock://-1:10000"), SockFamily::kVsock);
1159#endif
Primiano Tuccib0959042023-06-09 17:24:09 +01001160}
1161
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001162} // namespace
Florian Mayerf7f0def2018-09-27 13:59:24 +01001163} // namespace base
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001164} // namespace perfetto