• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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