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