blob: 202aa2c764a79f0bddb5a55047949b641f8a1812 [file] [log] [blame]
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +09001// 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
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +09005#include "base/sync_socket.h"
Sergey Ulanova6832682017-08-04 04:24:29 +09006
7#include "base/macros.h"
8#include "base/synchronization/waitable_event.h"
9#include "base/threading/platform_thread.h"
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090010#include "base/threading/simple_thread.h"
11#include "base/time/time.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
Sergey Ulanova6832682017-08-04 04:24:29 +090014namespace base {
15
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090016namespace {
17
Sergey Ulanova6832682017-08-04 04:24:29 +090018constexpr TimeDelta kReceiveTimeout = base::TimeDelta::FromMilliseconds(750);
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090019
Sergey Ulanova6832682017-08-04 04:24:29 +090020class HangingReceiveThread : public DelegateSimpleThread::Delegate {
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090021 public:
Sergey Ulanova6832682017-08-04 04:24:29 +090022 explicit HangingReceiveThread(SyncSocket* socket, bool with_timeout)
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090023 : socket_(socket),
Sergey Ulanova6832682017-08-04 04:24:29 +090024 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) {
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090030 thread_.Start();
31 }
32
dcheng7dc8df52014-10-21 19:54:51 +090033 ~HangingReceiveThread() override {}
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090034
dcheng7dc8df52014-10-21 19:54:51 +090035 void Run() override {
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090036 int data = 0;
37 ASSERT_EQ(socket_->Peek(), 0u);
38
Sergey Ulanova6832682017-08-04 04:24:29 +090039 started_event_.Signal();
40
41 if (with_timeout_) {
42 ASSERT_EQ(0u, socket_->ReceiveWithTimeout(&data, sizeof(data),
43 kReceiveTimeout));
44 } else {
45 ASSERT_EQ(0u, socket_->Receive(&data, sizeof(data)));
46 }
47
48 done_event_.Signal();
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090049 }
50
51 void Stop() {
52 thread_.Join();
53 }
54
Sergey Ulanova6832682017-08-04 04:24:29 +090055 WaitableEvent* started_event() { return &started_event_; }
56 WaitableEvent* done_event() { return &done_event_; }
57
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090058 private:
Sergey Ulanova6832682017-08-04 04:24:29 +090059 SyncSocket* socket_;
60 DelegateSimpleThread thread_;
61 bool with_timeout_;
62 WaitableEvent started_event_;
63 WaitableEvent done_event_;
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090064
65 DISALLOW_COPY_AND_ASSIGN(HangingReceiveThread);
66};
67
Sergey Ulanova6832682017-08-04 04:24:29 +090068// Tests sending data between two SyncSockets. Uses ASSERT() and thus will exit
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090069// early upon failure. Callers should use ASSERT_NO_FATAL_FAILURE() if testing
70// continues after return.
Sergey Ulanova6832682017-08-04 04:24:29 +090071void SendReceivePeek(SyncSocket* socket_a, SyncSocket* socket_b) {
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090072 int received = 0;
73 const int kSending = 123;
avi486c61f2015-11-24 23:26:24 +090074 static_assert(sizeof(kSending) == sizeof(received), "invalid data size");
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +090075
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), socket_a->Send(&kSending, sizeof(kSending)));
82 ASSERT_EQ(sizeof(kSending), socket_b->Peek());
83 ASSERT_EQ(sizeof(kSending), socket_b->Receive(&received, sizeof(kSending)));
84 ASSERT_EQ(kSending, received);
85
86 ASSERT_EQ(0u, socket_a->Peek());
87 ASSERT_EQ(0u, socket_b->Peek());
88
89 // Now verify the reverse.
90 received = 0;
91 ASSERT_EQ(sizeof(kSending), socket_b->Send(&kSending, sizeof(kSending)));
92 ASSERT_EQ(sizeof(kSending), socket_a->Peek());
93 ASSERT_EQ(sizeof(kSending), socket_a->Receive(&received, sizeof(kSending)));
94 ASSERT_EQ(kSending, received);
95
96 ASSERT_EQ(0u, socket_a->Peek());
97 ASSERT_EQ(0u, socket_b->Peek());
98
99 ASSERT_TRUE(socket_a->Close());
100 ASSERT_TRUE(socket_b->Close());
101}
102
Sergey Ulanova6832682017-08-04 04:24:29 +0900103} // namespace
104
105class SyncSocketTest : public testing::Test {
106 public:
107 void SetUp() override {
108 ASSERT_TRUE(SyncSocket::CreatePair(&socket_a_, &socket_b_));
109 }
110
111 protected:
112 SyncSocket socket_a_;
113 SyncSocket socket_b_;
114};
115
116TEST_F(SyncSocketTest, NormalSendReceivePeek) {
117 SendReceivePeek(&socket_a_, &socket_b_);
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +0900118}
119
Sergey Ulanova6832682017-08-04 04:24:29 +0900120TEST_F(SyncSocketTest, ClonedSendReceivePeek) {
121 SyncSocket socket_c(socket_a_.Release());
122 SyncSocket socket_d(socket_b_.Release());
123 SendReceivePeek(&socket_c, &socket_d);
124};
brucedawsona75f6882015-09-19 03:28:13 +0900125
Sergey Ulanova6832682017-08-04 04:24:29 +0900126class CancelableSyncSocketTest : public testing::Test {
127 public:
128 void SetUp() override {
129 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&socket_a_, &socket_b_));
130 }
131
132 protected:
133 CancelableSyncSocket socket_a_;
134 CancelableSyncSocket socket_b_;
135};
136
137TEST_F(CancelableSyncSocketTest, NormalSendReceivePeek) {
138 SendReceivePeek(&socket_a_, &socket_b_);
139}
140
141TEST_F(CancelableSyncSocketTest, ClonedSendReceivePeek) {
142 CancelableSyncSocket socket_c(socket_a_.Release());
143 CancelableSyncSocket socket_d(socket_b_.Release());
brucedawsona75f6882015-09-19 03:28:13 +0900144 SendReceivePeek(&socket_c, &socket_d);
145}
146
Sergey Ulanova6832682017-08-04 04:24:29 +0900147TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceive) {
148 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ false);
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +0900149
Sergey Ulanova6832682017-08-04 04:24:29 +0900150 // Wait for the thread to be started. Note that this doesn't guarantee that
151 // Receive() is called before Shutdown().
152 thread.started_event()->Wait();
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +0900153
Sergey Ulanova6832682017-08-04 04:24:29 +0900154 EXPECT_TRUE(socket_b_.Shutdown());
155 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
brucedawsona75f6882015-09-19 03:28:13 +0900156
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +0900157 thread.Stop();
Sergey Ulanova6832682017-08-04 04:24:29 +0900158}
159
160TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceiveWithTimeout) {
161 HangingReceiveThread thread(&socket_b_, /* with_timeout = */ true);
162
163 // Wait for the thread to be started. Note that this doesn't guarantee that
164 // Receive() is called before Shutdown().
165 thread.started_event()->Wait();
166
167 EXPECT_TRUE(socket_b_.Shutdown());
168 EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
169
170 thread.Stop();
171}
172
173TEST_F(CancelableSyncSocketTest, ReceiveAfterShutdown) {
174 socket_a_.Shutdown();
175 int data = 0;
176 EXPECT_EQ(0u, socket_a_.Receive(&data, sizeof(data)));
177}
178
179TEST_F(CancelableSyncSocketTest, ReceiveWithTimeoutAfterShutdown) {
180 socket_a_.Shutdown();
181 TimeTicks start = TimeTicks::Now();
182 int data = 0;
183 EXPECT_EQ(0u,
184 socket_a_.ReceiveWithTimeout(&data, sizeof(data), kReceiveTimeout));
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +0900185
186 // Ensure the receive didn't just timeout.
Sergey Ulanova6832682017-08-04 04:24:29 +0900187 EXPECT_LT(TimeTicks::Now() - start, kReceiveTimeout);
dalecurtis@chromium.org96b19df2013-10-20 07:13:19 +0900188}
Sergey Ulanova6832682017-08-04 04:24:29 +0900189
190} // namespace base