1 // Copyright 2013 The Chromium Authors
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 "base/sync_socket.h"
6
7 #include "base/containers/span.h"
8 #include "base/memory/raw_ptr.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/threading/platform_thread.h"
11 #include "base/threading/simple_thread.h"
12 #include "base/time/time.h"
13 #include "build/build_config.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17
18 namespace {
19
20 constexpr TimeDelta kReceiveTimeout = base::Milliseconds(750);
21
22 class HangingReceiveThread : public DelegateSimpleThread::Delegate {
23 public:
HangingReceiveThread(SyncSocket * socket,bool with_timeout)24 explicit HangingReceiveThread(SyncSocket* socket, bool with_timeout)
25 : socket_(socket),
26 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) {
32 thread_.Start();
33 }
34
35 HangingReceiveThread(const HangingReceiveThread&) = delete;
36 HangingReceiveThread& operator=(const HangingReceiveThread&) = delete;
37 ~HangingReceiveThread() override = default;
38
Run()39 void Run() override {
40 int data = 0;
41 ASSERT_EQ(socket_->Peek(), 0u);
42
43 started_event_.Signal();
44
45 if (with_timeout_) {
46 ASSERT_EQ(0u, socket_->ReceiveWithTimeout(byte_span_from_ref(data),
47 kReceiveTimeout));
48 } else {
49 ASSERT_EQ(0u, socket_->Receive(byte_span_from_ref(data)));
50 }
51
52 done_event_.Signal();
53 }
54
Stop()55 void Stop() {
56 thread_.Join();
57 }
58
started_event()59 WaitableEvent* started_event() { return &started_event_; }
done_event()60 WaitableEvent* done_event() { return &done_event_; }
61
62 private:
63 raw_ptr<SyncSocket> socket_;
64 DelegateSimpleThread thread_;
65 bool with_timeout_;
66 WaitableEvent started_event_;
67 WaitableEvent done_event_;
68 };
69
70 // Tests sending data between two SyncSockets. Uses ASSERT() and thus will exit
71 // early upon failure. Callers should use ASSERT_NO_FATAL_FAILURE() if testing
72 // continues after return.
SendReceivePeek(SyncSocket * socket_a,SyncSocket * socket_b)73 void SendReceivePeek(SyncSocket* socket_a, SyncSocket* socket_b) {
74 int received = 0;
75 const int kSending = 123;
76 static_assert(sizeof(kSending) == sizeof(received), "invalid data size");
77
78 ASSERT_EQ(0u, socket_a->Peek());
79 ASSERT_EQ(0u, socket_b->Peek());
80
81 // Verify |socket_a| can send to |socket_a| and |socket_a| can Receive from
82 // |socket_a|.
83 ASSERT_EQ(sizeof(kSending), socket_a->Send(byte_span_from_ref(kSending)));
84 ASSERT_EQ(sizeof(kSending), socket_b->Peek());
85 ASSERT_EQ(sizeof(kSending), socket_b->Receive(byte_span_from_ref(received)));
86 ASSERT_EQ(kSending, received);
87
88 ASSERT_EQ(0u, socket_a->Peek());
89 ASSERT_EQ(0u, socket_b->Peek());
90
91 // Now verify the reverse.
92 received = 0;
93 ASSERT_EQ(sizeof(kSending), socket_b->Send(byte_span_from_ref(kSending)));
94 ASSERT_EQ(sizeof(kSending), socket_a->Peek());
95 ASSERT_EQ(sizeof(kSending), socket_a->Receive(byte_span_from_ref(received)));
96 ASSERT_EQ(kSending, received);
97
98 ASSERT_EQ(0u, socket_a->Peek());
99 ASSERT_EQ(0u, socket_b->Peek());
100
101 socket_a->Close();
102 socket_b->Close();
103 }
104
105 } // namespace
106
107 class SyncSocketTest : public testing::Test {
108 public:
SetUp()109 void SetUp() override {
110 ASSERT_TRUE(SyncSocket::CreatePair(&socket_a_, &socket_b_));
111 }
112
113 protected:
114 SyncSocket socket_a_;
115 SyncSocket socket_b_;
116 };
117
TEST_F(SyncSocketTest,NormalSendReceivePeek)118 TEST_F(SyncSocketTest, NormalSendReceivePeek) {
119 SendReceivePeek(&socket_a_, &socket_b_);
120 }
121
TEST_F(SyncSocketTest,ClonedSendReceivePeek)122 TEST_F(SyncSocketTest, ClonedSendReceivePeek) {
123 SyncSocket socket_c(socket_a_.Release());
124 SyncSocket socket_d(socket_b_.Release());
125 SendReceivePeek(&socket_c, &socket_d);
126 }
127
128 class CancelableSyncSocketTest : public testing::Test {
129 public:
SetUp()130 void SetUp() override {
131 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&socket_a_, &socket_b_));
132 }
133
134 protected:
135 CancelableSyncSocket socket_a_;
136 CancelableSyncSocket socket_b_;
137 };
138
TEST_F(CancelableSyncSocketTest,NormalSendReceivePeek)139 TEST_F(CancelableSyncSocketTest, NormalSendReceivePeek) {
140 SendReceivePeek(&socket_a_, &socket_b_);
141 }
142
TEST_F(CancelableSyncSocketTest,ClonedSendReceivePeek)143 TEST_F(CancelableSyncSocketTest, ClonedSendReceivePeek) {
144 CancelableSyncSocket socket_c(socket_a_.Release());
145 CancelableSyncSocket socket_d(socket_b_.Release());
146 SendReceivePeek(&socket_c, &socket_d);
147 }
148
149 // TODO(https://crbug.com/361250560): Flaky on mac.
150 #if BUILDFLAG(IS_MAC)
151 #define MAYBE_ShutdownCancelsReceive DISABLED_ShutdownCancelsReceive
152 #else
153 #define MAYBE_ShutdownCancelsReceive ShutdownCancelsReceive
154 #endif
TEST_F(CancelableSyncSocketTest,MAYBE_ShutdownCancelsReceive)155 TEST_F(CancelableSyncSocketTest, MAYBE_ShutdownCancelsReceive) {
156 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ false);
157
158 // Wait for the thread to be started. Note that this doesn't guarantee that
159 // Receive() is called before Shutdown().
160 thread.started_event()->Wait();
161
162 EXPECT_TRUE(socket_b_.Shutdown());
163 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
164
165 thread.Stop();
166 }
167
TEST_F(CancelableSyncSocketTest,ShutdownCancelsReceiveWithTimeout)168 TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceiveWithTimeout) {
169 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ true);
170
171 // Wait for the thread to be started. Note that this doesn't guarantee that
172 // Receive() is called before Shutdown().
173 thread.started_event()->Wait();
174
175 EXPECT_TRUE(socket_b_.Shutdown());
176 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
177
178 thread.Stop();
179 }
180
TEST_F(CancelableSyncSocketTest,ReceiveAfterShutdown)181 TEST_F(CancelableSyncSocketTest, ReceiveAfterShutdown) {
182 socket_a_.Shutdown();
183 int data = 0;
184 EXPECT_EQ(0u, socket_a_.Receive(byte_span_from_ref(data)));
185 }
186
TEST_F(CancelableSyncSocketTest,ReceiveWithTimeoutAfterShutdown)187 TEST_F(CancelableSyncSocketTest, ReceiveWithTimeoutAfterShutdown) {
188 socket_a_.Shutdown();
189 TimeTicks start = TimeTicks::Now();
190 int data = 0;
191 EXPECT_EQ(0u, socket_a_.ReceiveWithTimeout(byte_span_from_ref(data),
192 kReceiveTimeout));
193
194 // Ensure the receive didn't just timeout.
195 EXPECT_LT(TimeTicks::Now() - start, kReceiveTimeout);
196 }
197
198 } // namespace base
199