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