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