1 // Copyright 2014 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.
5 #include "net/socket/websocket_endpoint_lock_manager.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/time/time.h"
10 #include "net/base/net_errors.h"
11 #include "net/socket/next_proto.h"
12 #include "net/socket/socket_test_util.h"
13 #include "net/socket/stream_socket.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 // A StreamSocket implementation with no functionality at all.
21 // TODO(ricea): If you need to use this in another file, please move it to
22 // socket_test_util.h.
23 class FakeStreamSocket
: public StreamSocket
{
27 // StreamSocket implementation
28 int Connect(const CompletionCallback
& callback
) override
{
32 void Disconnect() override
{ return; }
34 bool IsConnected() const override
{ return false; }
36 bool IsConnectedAndIdle() const override
{ return false; }
38 int GetPeerAddress(IPEndPoint
* address
) const override
{ return ERR_FAILED
; }
40 int GetLocalAddress(IPEndPoint
* address
) const override
{ return ERR_FAILED
; }
42 const BoundNetLog
& NetLog() const override
{ return bound_net_log_
; }
44 void SetSubresourceSpeculation() override
{ return; }
45 void SetOmniboxSpeculation() override
{ return; }
47 bool WasEverUsed() const override
{ return false; }
49 bool UsingTCPFastOpen() const override
{ return false; }
51 bool WasNpnNegotiated() const override
{ return false; }
53 NextProto
GetNegotiatedProtocol() const override
{ return kProtoUnknown
; }
55 bool GetSSLInfo(SSLInfo
* ssl_info
) override
{ return false; }
57 // Socket implementation
58 int Read(IOBuffer
* buf
,
60 const CompletionCallback
& callback
) override
{
64 int Write(IOBuffer
* buf
,
66 const CompletionCallback
& callback
) override
{
70 int SetReceiveBufferSize(int32 size
) override
{ return ERR_FAILED
; }
72 int SetSendBufferSize(int32 size
) override
{ return ERR_FAILED
; }
75 BoundNetLog bound_net_log_
;
77 DISALLOW_COPY_AND_ASSIGN(FakeStreamSocket
);
80 class FakeWaiter
: public WebSocketEndpointLockManager::Waiter
{
82 FakeWaiter() : called_(false) {}
84 void GotEndpointLock() override
{
89 bool called() const { return called_
; }
95 class BlockingWaiter
: public FakeWaiter
{
103 void GotEndpointLock() override
{
104 FakeWaiter::GotEndpointLock();
109 base::RunLoop run_loop_
;
112 class WebSocketEndpointLockManagerTest
: public ::testing::Test
{
114 WebSocketEndpointLockManagerTest()
115 : instance_(WebSocketEndpointLockManager::GetInstance()) {}
116 ~WebSocketEndpointLockManagerTest() override
{
117 // Permit any pending asynchronous unlock operations to complete.
119 // If this check fails then subsequent tests may fail.
120 CHECK(instance_
->IsEmpty());
123 WebSocketEndpointLockManager
* instance() const { return instance_
; }
125 IPEndPoint
DummyEndpoint() {
126 IPAddressNumber ip_address_number
;
127 CHECK(ParseIPLiteralToNumber("127.0.0.1", &ip_address_number
));
128 return IPEndPoint(ip_address_number
, 80);
131 void UnlockDummyEndpoint(int times
) {
132 for (int i
= 0; i
< times
; ++i
) {
133 instance()->UnlockEndpoint(DummyEndpoint());
138 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
140 WebSocketEndpointLockManager
* const instance_
;
141 ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_
;
144 TEST_F(WebSocketEndpointLockManagerTest
, GetInstanceWorks
) {
145 // All the work is done by the test framework.
148 TEST_F(WebSocketEndpointLockManagerTest
, LockEndpointReturnsOkOnce
) {
149 FakeWaiter waiters
[2];
150 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
151 EXPECT_EQ(ERR_IO_PENDING
,
152 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
154 UnlockDummyEndpoint(2);
157 TEST_F(WebSocketEndpointLockManagerTest
, GotEndpointLockNotCalledOnOk
) {
159 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiter
));
161 EXPECT_FALSE(waiter
.called());
163 UnlockDummyEndpoint(1);
166 TEST_F(WebSocketEndpointLockManagerTest
, GotEndpointLockNotCalledImmediately
) {
167 FakeWaiter waiters
[2];
168 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
169 EXPECT_EQ(ERR_IO_PENDING
,
170 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
172 EXPECT_FALSE(waiters
[1].called());
174 UnlockDummyEndpoint(2);
177 TEST_F(WebSocketEndpointLockManagerTest
, GotEndpointLockCalledWhenUnlocked
) {
178 FakeWaiter waiters
[2];
179 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
180 EXPECT_EQ(ERR_IO_PENDING
,
181 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
182 instance()->UnlockEndpoint(DummyEndpoint());
184 EXPECT_TRUE(waiters
[1].called());
186 UnlockDummyEndpoint(1);
189 TEST_F(WebSocketEndpointLockManagerTest
,
190 EndpointUnlockedIfWaiterAlreadyDeleted
) {
191 FakeWaiter first_lock_holder
;
192 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &first_lock_holder
));
195 FakeWaiter short_lived_waiter
;
196 EXPECT_EQ(ERR_IO_PENDING
,
197 instance()->LockEndpoint(DummyEndpoint(), &short_lived_waiter
));
200 instance()->UnlockEndpoint(DummyEndpoint());
203 FakeWaiter second_lock_holder
;
204 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &second_lock_holder
));
206 UnlockDummyEndpoint(1);
209 TEST_F(WebSocketEndpointLockManagerTest
, RememberSocketWorks
) {
210 FakeWaiter waiters
[2];
211 FakeStreamSocket dummy_socket
;
212 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
213 EXPECT_EQ(ERR_IO_PENDING
,
214 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
216 instance()->RememberSocket(&dummy_socket
, DummyEndpoint());
217 instance()->UnlockSocket(&dummy_socket
);
219 EXPECT_TRUE(waiters
[1].called());
221 UnlockDummyEndpoint(1);
224 // UnlockEndpoint() should cause any sockets remembered for this endpoint
226 TEST_F(WebSocketEndpointLockManagerTest
, SocketAssociationForgottenOnUnlock
) {
228 FakeStreamSocket dummy_socket
;
230 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiter
));
231 instance()->RememberSocket(&dummy_socket
, DummyEndpoint());
232 instance()->UnlockEndpoint(DummyEndpoint());
234 EXPECT_TRUE(instance()->IsEmpty());
237 // When ownership of the endpoint is passed to a new waiter, the new waiter can
238 // call RememberSocket() again.
239 TEST_F(WebSocketEndpointLockManagerTest
, NextWaiterCanCallRememberSocketAgain
) {
240 FakeWaiter waiters
[2];
241 FakeStreamSocket dummy_sockets
[2];
242 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
243 EXPECT_EQ(ERR_IO_PENDING
,
244 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
246 instance()->RememberSocket(&dummy_sockets
[0], DummyEndpoint());
247 instance()->UnlockEndpoint(DummyEndpoint());
249 EXPECT_TRUE(waiters
[1].called());
250 instance()->RememberSocket(&dummy_sockets
[1], DummyEndpoint());
252 UnlockDummyEndpoint(1);
255 // Calling UnlockSocket() after UnlockEndpoint() does nothing.
256 TEST_F(WebSocketEndpointLockManagerTest
,
257 UnlockSocketAfterUnlockEndpointDoesNothing
) {
258 FakeWaiter waiters
[3];
259 FakeStreamSocket dummy_socket
;
261 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
262 EXPECT_EQ(ERR_IO_PENDING
,
263 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
264 EXPECT_EQ(ERR_IO_PENDING
,
265 instance()->LockEndpoint(DummyEndpoint(), &waiters
[2]));
266 instance()->RememberSocket(&dummy_socket
, DummyEndpoint());
267 instance()->UnlockEndpoint(DummyEndpoint());
268 instance()->UnlockSocket(&dummy_socket
);
270 EXPECT_TRUE(waiters
[1].called());
271 EXPECT_FALSE(waiters
[2].called());
273 UnlockDummyEndpoint(2);
276 // UnlockEndpoint() should always be asynchronous.
277 TEST_F(WebSocketEndpointLockManagerTest
, UnlockEndpointIsAsynchronous
) {
278 FakeWaiter waiters
[2];
279 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
280 EXPECT_EQ(ERR_IO_PENDING
,
281 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
283 instance()->UnlockEndpoint(DummyEndpoint());
284 EXPECT_FALSE(waiters
[1].called());
286 EXPECT_TRUE(waiters
[1].called());
288 UnlockDummyEndpoint(1);
291 // UnlockEndpoint() should normally have a delay.
292 TEST_F(WebSocketEndpointLockManagerTest
, UnlockEndpointIsDelayed
) {
293 using base::TimeTicks
;
295 // This 1ms delay is too short for very slow environments (usually those
296 // running memory checkers). In those environments, the code takes >1ms to run
297 // and no delay is needed. Rather than increase the delay and slow down the
298 // test everywhere, the test doesn't explicitly verify that a delay has been
299 // applied. Instead it just verifies that the whole thing took >=1ms. 1ms is
300 // easily enough for normal compiles even on Android, so the fact that there
301 // is a delay is still checked on every platform.
302 const base::TimeDelta unlock_delay
= base::TimeDelta::FromMilliseconds(1);
303 instance()->SetUnlockDelayForTesting(unlock_delay
);
304 FakeWaiter fake_waiter
;
305 BlockingWaiter blocking_waiter
;
306 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &fake_waiter
));
307 EXPECT_EQ(ERR_IO_PENDING
,
308 instance()->LockEndpoint(DummyEndpoint(), &blocking_waiter
));
310 TimeTicks before_unlock
= TimeTicks::Now();
311 instance()->UnlockEndpoint(DummyEndpoint());
312 blocking_waiter
.WaitForLock();
313 TimeTicks after_unlock
= TimeTicks::Now();
314 EXPECT_GE(after_unlock
- before_unlock
, unlock_delay
);
315 instance()->SetUnlockDelayForTesting(base::TimeDelta());
316 UnlockDummyEndpoint(1);