blob: a3a673924a721c75a59713b4bd940ccbb0ed603d [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2013 The Chromium Authors
dalecurtis@chromium.org62558f12013-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
danakj51d26a42024-04-25 14:23:565#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7#pragma allow_unsafe_buffers
8#endif
9
dalecurtis@chromium.org62558f12013-10-19 22:13:1910#include "base/sync_socket.h"
Sergey Ulanove9631752017-08-03 19:24:2911
Keishi Hattori0e45c022021-11-27 09:25:5212#include "base/memory/raw_ptr.h"
Sergey Ulanove9631752017-08-03 19:24:2913#include "base/synchronization/waitable_event.h"
14#include "base/threading/platform_thread.h"
dalecurtis@chromium.org62558f12013-10-19 22:13:1915#include "base/threading/simple_thread.h"
16#include "base/time/time.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
Sergey Ulanove9631752017-08-03 19:24:2919namespace base {
20
dalecurtis@chromium.org62558f12013-10-19 22:13:1921namespace {
22
Peter Kastinge5a38ed2021-10-02 03:06:3523constexpr TimeDelta kReceiveTimeout = base::Milliseconds(750);
dalecurtis@chromium.org62558f12013-10-19 22:13:1924
Sergey Ulanove9631752017-08-03 19:24:2925class HangingReceiveThread : public DelegateSimpleThread::Delegate {
dalecurtis@chromium.org62558f12013-10-19 22:13:1926 public:
Sergey Ulanove9631752017-08-03 19:24:2927 explicit HangingReceiveThread(SyncSocket* socket, bool with_timeout)
dalecurtis@chromium.org62558f12013-10-19 22:13:1928 : socket_(socket),
Sergey Ulanove9631752017-08-03 19:24:2929 thread_(this, "HangingReceiveThread"),
30 with_timeout_(with_timeout),
31 started_event_(WaitableEvent::ResetPolicy::MANUAL,
32 WaitableEvent::InitialState::NOT_SIGNALED),
33 done_event_(WaitableEvent::ResetPolicy::MANUAL,
34 WaitableEvent::InitialState::NOT_SIGNALED) {
dalecurtis@chromium.org62558f12013-10-19 22:13:1935 thread_.Start();
36 }
37
David Bienvenu5f4d4f02020-09-27 16:55:0338 HangingReceiveThread(const HangingReceiveThread&) = delete;
39 HangingReceiveThread& operator=(const HangingReceiveThread&) = delete;
Chris Watkinsbb7211c2017-11-29 07:16:3840 ~HangingReceiveThread() override = default;
dalecurtis@chromium.org62558f12013-10-19 22:13:1941
dcheng56488182014-10-21 10:54:5142 void Run() override {
dalecurtis@chromium.org62558f12013-10-19 22:13:1943 int data = 0;
44 ASSERT_EQ(socket_->Peek(), 0u);
45
Sergey Ulanove9631752017-08-03 19:24:2946 started_event_.Signal();
47
48 if (with_timeout_) {
49 ASSERT_EQ(0u, socket_->ReceiveWithTimeout(&data, sizeof(data),
50 kReceiveTimeout));
51 } else {
52 ASSERT_EQ(0u, socket_->Receive(&data, sizeof(data)));
53 }
54
55 done_event_.Signal();
dalecurtis@chromium.org62558f12013-10-19 22:13:1956 }
57
58 void Stop() {
59 thread_.Join();
60 }
61
Sergey Ulanove9631752017-08-03 19:24:2962 WaitableEvent* started_event() { return &started_event_; }
63 WaitableEvent* done_event() { return &done_event_; }
64
dalecurtis@chromium.org62558f12013-10-19 22:13:1965 private:
Keishi Hattori0e45c022021-11-27 09:25:5266 raw_ptr<SyncSocket> socket_;
Sergey Ulanove9631752017-08-03 19:24:2967 DelegateSimpleThread thread_;
68 bool with_timeout_;
69 WaitableEvent started_event_;
70 WaitableEvent done_event_;
dalecurtis@chromium.org62558f12013-10-19 22:13:1971};
72
Sergey Ulanove9631752017-08-03 19:24:2973// Tests sending data between two SyncSockets. Uses ASSERT() and thus will exit
dalecurtis@chromium.org62558f12013-10-19 22:13:1974// early upon failure. Callers should use ASSERT_NO_FATAL_FAILURE() if testing
75// continues after return.
Sergey Ulanove9631752017-08-03 19:24:2976void SendReceivePeek(SyncSocket* socket_a, SyncSocket* socket_b) {
dalecurtis@chromium.org62558f12013-10-19 22:13:1977 int received = 0;
78 const int kSending = 123;
avi4ec0dff2015-11-24 14:26:2479 static_assert(sizeof(kSending) == sizeof(received), "invalid data size");
dalecurtis@chromium.org62558f12013-10-19 22:13:1980
81 ASSERT_EQ(0u, socket_a->Peek());
82 ASSERT_EQ(0u, socket_b->Peek());
83
84 // Verify |socket_a| can send to |socket_a| and |socket_a| can Receive from
85 // |socket_a|.
Austin Sullivanedf168fd2024-01-17 21:37:2086 ASSERT_EQ(sizeof(kSending),
87 socket_a->Send(as_bytes(make_span(&kSending, 1u))));
dalecurtis@chromium.org62558f12013-10-19 22:13:1988 ASSERT_EQ(sizeof(kSending), socket_b->Peek());
Austin Sullivanedf168fd2024-01-17 21:37:2089 ASSERT_EQ(sizeof(kSending),
90 socket_b->Receive(as_writable_bytes(make_span(&received, 1u))));
dalecurtis@chromium.org62558f12013-10-19 22:13:1991 ASSERT_EQ(kSending, received);
92
93 ASSERT_EQ(0u, socket_a->Peek());
94 ASSERT_EQ(0u, socket_b->Peek());
95
96 // Now verify the reverse.
97 received = 0;
Austin Sullivanedf168fd2024-01-17 21:37:2098 ASSERT_EQ(sizeof(kSending),
99 socket_b->Send(as_bytes(make_span(&kSending, 1u))));
dalecurtis@chromium.org62558f12013-10-19 22:13:19100 ASSERT_EQ(sizeof(kSending), socket_a->Peek());
Austin Sullivanedf168fd2024-01-17 21:37:20101 ASSERT_EQ(sizeof(kSending),
102 socket_a->Receive(as_writable_bytes(make_span(&received, 1u))));
dalecurtis@chromium.org62558f12013-10-19 22:13:19103 ASSERT_EQ(kSending, received);
104
105 ASSERT_EQ(0u, socket_a->Peek());
106 ASSERT_EQ(0u, socket_b->Peek());
107
Robert Sesek6ab73b022020-02-13 16:42:39108 socket_a->Close();
109 socket_b->Close();
dalecurtis@chromium.org62558f12013-10-19 22:13:19110}
111
Sergey Ulanove9631752017-08-03 19:24:29112} // namespace
113
114class SyncSocketTest : public testing::Test {
115 public:
116 void SetUp() override {
117 ASSERT_TRUE(SyncSocket::CreatePair(&socket_a_, &socket_b_));
118 }
119
120 protected:
121 SyncSocket socket_a_;
122 SyncSocket socket_b_;
123};
124
125TEST_F(SyncSocketTest, NormalSendReceivePeek) {
126 SendReceivePeek(&socket_a_, &socket_b_);
dalecurtis@chromium.org62558f12013-10-19 22:13:19127}
128
Sergey Ulanove9631752017-08-03 19:24:29129TEST_F(SyncSocketTest, ClonedSendReceivePeek) {
130 SyncSocket socket_c(socket_a_.Release());
131 SyncSocket socket_d(socket_b_.Release());
132 SendReceivePeek(&socket_c, &socket_d);
Nico Weberca5f9592019-01-31 14:35:41133}
brucedawsond3509432015-09-18 18:28:13134
Sergey Ulanove9631752017-08-03 19:24:29135class CancelableSyncSocketTest : public testing::Test {
136 public:
137 void SetUp() override {
138 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&socket_a_, &socket_b_));
139 }
140
141 protected:
142 CancelableSyncSocket socket_a_;
143 CancelableSyncSocket socket_b_;
144};
145
146TEST_F(CancelableSyncSocketTest, NormalSendReceivePeek) {
147 SendReceivePeek(&socket_a_, &socket_b_);
148}
149
150TEST_F(CancelableSyncSocketTest, ClonedSendReceivePeek) {
151 CancelableSyncSocket socket_c(socket_a_.Release());
152 CancelableSyncSocket socket_d(socket_b_.Release());
brucedawsond3509432015-09-18 18:28:13153 SendReceivePeek(&socket_c, &socket_d);
154}
155
Sergey Ulanove9631752017-08-03 19:24:29156TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceive) {
157 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ false);
dalecurtis@chromium.org62558f12013-10-19 22:13:19158
Sergey Ulanove9631752017-08-03 19:24:29159 // Wait for the thread to be started. Note that this doesn't guarantee that
160 // Receive() is called before Shutdown().
161 thread.started_event()->Wait();
dalecurtis@chromium.org62558f12013-10-19 22:13:19162
Sergey Ulanove9631752017-08-03 19:24:29163 EXPECT_TRUE(socket_b_.Shutdown());
164 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
brucedawsond3509432015-09-18 18:28:13165
dalecurtis@chromium.org62558f12013-10-19 22:13:19166 thread.Stop();
Sergey Ulanove9631752017-08-03 19:24:29167}
168
169TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceiveWithTimeout) {
170 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ true);
171
172 // Wait for the thread to be started. Note that this doesn't guarantee that
173 // Receive() is called before Shutdown().
174 thread.started_event()->Wait();
175
176 EXPECT_TRUE(socket_b_.Shutdown());
177 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
178
179 thread.Stop();
180}
181
182TEST_F(CancelableSyncSocketTest, ReceiveAfterShutdown) {
183 socket_a_.Shutdown();
184 int data = 0;
Austin Sullivanedf168fd2024-01-17 21:37:20185 EXPECT_EQ(0u, socket_a_.Receive(as_writable_bytes(make_span(&data, 1u))));
Sergey Ulanove9631752017-08-03 19:24:29186}
187
188TEST_F(CancelableSyncSocketTest, ReceiveWithTimeoutAfterShutdown) {
189 socket_a_.Shutdown();
190 TimeTicks start = TimeTicks::Now();
191 int data = 0;
192 EXPECT_EQ(0u,
193 socket_a_.ReceiveWithTimeout(&data, sizeof(data), kReceiveTimeout));
dalecurtis@chromium.org62558f12013-10-19 22:13:19194
195 // Ensure the receive didn't just timeout.
Sergey Ulanove9631752017-08-03 19:24:29196 EXPECT_LT(TimeTicks::Now() - start, kReceiveTimeout);
dalecurtis@chromium.org62558f12013-10-19 22:13:19197}
Sergey Ulanove9631752017-08-03 19:24:29198
199} // namespace base