blob: ef27bee6c0612180495d8b0fb6f183320f776b44 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2013 The Chromium Authors
[email protected]62558f12013-10-19 22:13:192// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]62558f12013-10-19 22:13:195#include "base/sync_socket.h"
Sergey Ulanove9631752017-08-03 19:24:296
Jan Keitel351a86c62024-08-03 08:25:317#include "base/containers/span.h"
Keishi Hattori0e45c022021-11-27 09:25:528#include "base/memory/raw_ptr.h"
Sergey Ulanove9631752017-08-03 19:24:299#include "base/synchronization/waitable_event.h"
10#include "base/threading/platform_thread.h"
[email protected]62558f12013-10-19 22:13:1911#include "base/threading/simple_thread.h"
12#include "base/time/time.h"
Kevin McNeeea3573ff2024-08-21 16:38:2213#include "build/build_config.h"
[email protected]62558f12013-10-19 22:13:1914#include "testing/gtest/include/gtest/gtest.h"
15
Sergey Ulanove9631752017-08-03 19:24:2916namespace base {
17
[email protected]62558f12013-10-19 22:13:1918namespace {
19
Peter Kastinge5a38ed2021-10-02 03:06:3520constexpr TimeDelta kReceiveTimeout = base::Milliseconds(750);
[email protected]62558f12013-10-19 22:13:1921
Sergey Ulanove9631752017-08-03 19:24:2922class HangingReceiveThread : public DelegateSimpleThread::Delegate {
[email protected]62558f12013-10-19 22:13:1923 public:
Sergey Ulanove9631752017-08-03 19:24:2924 explicit HangingReceiveThread(SyncSocket* socket, bool with_timeout)
[email protected]62558f12013-10-19 22:13:1925 : socket_(socket),
Sergey Ulanove9631752017-08-03 19:24:2926 thread_(this, "HangingReceiveThread"),
27 with_timeout_(with_timeout),
28 started_event_(WaitableEvent::ResetPolicy::MANUAL,
29 WaitableEvent::InitialState::NOT_SIGNALED),
30 done_event_(WaitableEvent::ResetPolicy::MANUAL,
31 WaitableEvent::InitialState::NOT_SIGNALED) {
[email protected]62558f12013-10-19 22:13:1932 thread_.Start();
33 }
34
David Bienvenu5f4d4f02020-09-27 16:55:0335 HangingReceiveThread(const HangingReceiveThread&) = delete;
36 HangingReceiveThread& operator=(const HangingReceiveThread&) = delete;
Chris Watkinsbb7211c2017-11-29 07:16:3837 ~HangingReceiveThread() override = default;
[email protected]62558f12013-10-19 22:13:1938
dcheng56488182014-10-21 10:54:5139 void Run() override {
[email protected]62558f12013-10-19 22:13:1940 int data = 0;
41 ASSERT_EQ(socket_->Peek(), 0u);
42
Sergey Ulanove9631752017-08-03 19:24:2943 started_event_.Signal();
44
45 if (with_timeout_) {
Jan Keitel351a86c62024-08-03 08:25:3146 ASSERT_EQ(0u, socket_->ReceiveWithTimeout(byte_span_from_ref(data),
Sergey Ulanove9631752017-08-03 19:24:2947 kReceiveTimeout));
48 } else {
Jan Keitel351a86c62024-08-03 08:25:3149 ASSERT_EQ(0u, socket_->Receive(byte_span_from_ref(data)));
Sergey Ulanove9631752017-08-03 19:24:2950 }
51
52 done_event_.Signal();
[email protected]62558f12013-10-19 22:13:1953 }
54
Peter Kasting134ef9af2024-12-28 02:30:0955 void Stop() { thread_.Join(); }
[email protected]62558f12013-10-19 22:13:1956
Sergey Ulanove9631752017-08-03 19:24:2957 WaitableEvent* started_event() { return &started_event_; }
58 WaitableEvent* done_event() { return &done_event_; }
59
[email protected]62558f12013-10-19 22:13:1960 private:
Keishi Hattori0e45c022021-11-27 09:25:5261 raw_ptr<SyncSocket> socket_;
Sergey Ulanove9631752017-08-03 19:24:2962 DelegateSimpleThread thread_;
63 bool with_timeout_;
64 WaitableEvent started_event_;
65 WaitableEvent done_event_;
[email protected]62558f12013-10-19 22:13:1966};
67
Sergey Ulanove9631752017-08-03 19:24:2968// Tests sending data between two SyncSockets. Uses ASSERT() and thus will exit
[email protected]62558f12013-10-19 22:13:1969// early upon failure. Callers should use ASSERT_NO_FATAL_FAILURE() if testing
70// continues after return.
Sergey Ulanove9631752017-08-03 19:24:2971void SendReceivePeek(SyncSocket* socket_a, SyncSocket* socket_b) {
[email protected]62558f12013-10-19 22:13:1972 int received = 0;
73 const int kSending = 123;
avi4ec0dff2015-11-24 14:26:2474 static_assert(sizeof(kSending) == sizeof(received), "invalid data size");
[email protected]62558f12013-10-19 22:13:1975
76 ASSERT_EQ(0u, socket_a->Peek());
77 ASSERT_EQ(0u, socket_b->Peek());
78
79 // Verify |socket_a| can send to |socket_a| and |socket_a| can Receive from
80 // |socket_a|.
Jan Keitel351a86c62024-08-03 08:25:3181 ASSERT_EQ(sizeof(kSending), socket_a->Send(byte_span_from_ref(kSending)));
[email protected]62558f12013-10-19 22:13:1982 ASSERT_EQ(sizeof(kSending), socket_b->Peek());
Jan Keitel351a86c62024-08-03 08:25:3183 ASSERT_EQ(sizeof(kSending), socket_b->Receive(byte_span_from_ref(received)));
[email protected]62558f12013-10-19 22:13:1984 ASSERT_EQ(kSending, received);
85
86 ASSERT_EQ(0u, socket_a->Peek());
87 ASSERT_EQ(0u, socket_b->Peek());
88
89 // Now verify the reverse.
90 received = 0;
Jan Keitel351a86c62024-08-03 08:25:3191 ASSERT_EQ(sizeof(kSending), socket_b->Send(byte_span_from_ref(kSending)));
[email protected]62558f12013-10-19 22:13:1992 ASSERT_EQ(sizeof(kSending), socket_a->Peek());
Jan Keitel351a86c62024-08-03 08:25:3193 ASSERT_EQ(sizeof(kSending), socket_a->Receive(byte_span_from_ref(received)));
[email protected]62558f12013-10-19 22:13:1994 ASSERT_EQ(kSending, received);
95
96 ASSERT_EQ(0u, socket_a->Peek());
97 ASSERT_EQ(0u, socket_b->Peek());
98
Robert Sesek6ab73b022020-02-13 16:42:3999 socket_a->Close();
100 socket_b->Close();
[email protected]62558f12013-10-19 22:13:19101}
102
Sergey Ulanove9631752017-08-03 19:24:29103} // namespace
104
105class SyncSocketTest : public testing::Test {
106 public:
107 void SetUp() override {
108 ASSERT_TRUE(SyncSocket::CreatePair(&socket_a_, &socket_b_));
109 }
110
111 protected:
112 SyncSocket socket_a_;
113 SyncSocket socket_b_;
114};
115
116TEST_F(SyncSocketTest, NormalSendReceivePeek) {
117 SendReceivePeek(&socket_a_, &socket_b_);
[email protected]62558f12013-10-19 22:13:19118}
119
Sergey Ulanove9631752017-08-03 19:24:29120TEST_F(SyncSocketTest, ClonedSendReceivePeek) {
121 SyncSocket socket_c(socket_a_.Release());
122 SyncSocket socket_d(socket_b_.Release());
123 SendReceivePeek(&socket_c, &socket_d);
Nico Weberca5f9592019-01-31 14:35:41124}
brucedawsond3509432015-09-18 18:28:13125
Sergey Ulanove9631752017-08-03 19:24:29126class CancelableSyncSocketTest : public testing::Test {
127 public:
128 void SetUp() override {
129 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&socket_a_, &socket_b_));
130 }
131
132 protected:
133 CancelableSyncSocket socket_a_;
134 CancelableSyncSocket socket_b_;
135};
136
137TEST_F(CancelableSyncSocketTest, NormalSendReceivePeek) {
138 SendReceivePeek(&socket_a_, &socket_b_);
139}
140
141TEST_F(CancelableSyncSocketTest, ClonedSendReceivePeek) {
142 CancelableSyncSocket socket_c(socket_a_.Release());
143 CancelableSyncSocket socket_d(socket_b_.Release());
brucedawsond3509432015-09-18 18:28:13144 SendReceivePeek(&socket_c, &socket_d);
145}
146
Kevin McNeeea3573ff2024-08-21 16:38:22147// TODO(https://crbug.com/361250560): Flaky on mac.
148#if BUILDFLAG(IS_MAC)
149#define MAYBE_ShutdownCancelsReceive DISABLED_ShutdownCancelsReceive
150#else
151#define MAYBE_ShutdownCancelsReceive ShutdownCancelsReceive
152#endif
153TEST_F(CancelableSyncSocketTest, MAYBE_ShutdownCancelsReceive) {
Sergey Ulanove9631752017-08-03 19:24:29154 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ false);
[email protected]62558f12013-10-19 22:13:19155
Sergey Ulanove9631752017-08-03 19:24:29156 // Wait for the thread to be started. Note that this doesn't guarantee that
157 // Receive() is called before Shutdown().
158 thread.started_event()->Wait();
[email protected]62558f12013-10-19 22:13:19159
Sergey Ulanove9631752017-08-03 19:24:29160 EXPECT_TRUE(socket_b_.Shutdown());
161 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
brucedawsond3509432015-09-18 18:28:13162
[email protected]62558f12013-10-19 22:13:19163 thread.Stop();
Sergey Ulanove9631752017-08-03 19:24:29164}
165
166TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceiveWithTimeout) {
167 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ true);
168
169 // Wait for the thread to be started. Note that this doesn't guarantee that
170 // Receive() is called before Shutdown().
171 thread.started_event()->Wait();
172
173 EXPECT_TRUE(socket_b_.Shutdown());
174 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
175
176 thread.Stop();
177}
178
179TEST_F(CancelableSyncSocketTest, ReceiveAfterShutdown) {
180 socket_a_.Shutdown();
181 int data = 0;
Jan Keitel351a86c62024-08-03 08:25:31182 EXPECT_EQ(0u, socket_a_.Receive(byte_span_from_ref(data)));
Sergey Ulanove9631752017-08-03 19:24:29183}
184
185TEST_F(CancelableSyncSocketTest, ReceiveWithTimeoutAfterShutdown) {
186 socket_a_.Shutdown();
187 TimeTicks start = TimeTicks::Now();
188 int data = 0;
Jan Keitel351a86c62024-08-03 08:25:31189 EXPECT_EQ(0u, socket_a_.ReceiveWithTimeout(byte_span_from_ref(data),
190 kReceiveTimeout));
[email protected]62558f12013-10-19 22:13:19191
192 // Ensure the receive didn't just timeout.
Sergey Ulanove9631752017-08-03 19:24:29193 EXPECT_LT(TimeTicks::Now() - start, kReceiveTimeout);
[email protected]62558f12013-10-19 22:13:19194}
Sergey Ulanove9631752017-08-03 19:24:29195
196} // namespace base