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 void GetConnectionAttempts(ConnectionAttempts
* out
) const override
{
61 void ClearConnectionAttempts() override
{}
63 void AddConnectionAttempts(const ConnectionAttempts
& attempts
) override
{}
65 // Socket implementation
66 int Read(IOBuffer
* buf
,
68 const CompletionCallback
& callback
) override
{
72 int Write(IOBuffer
* buf
,
74 const CompletionCallback
& callback
) override
{
78 int SetReceiveBufferSize(int32 size
) override
{ return ERR_FAILED
; }
80 int SetSendBufferSize(int32 size
) override
{ return ERR_FAILED
; }
83 BoundNetLog bound_net_log_
;
85 DISALLOW_COPY_AND_ASSIGN(FakeStreamSocket
);
88 class FakeWaiter
: public WebSocketEndpointLockManager::Waiter
{
90 FakeWaiter() : called_(false) {}
92 void GotEndpointLock() override
{
97 bool called() const { return called_
; }
103 class BlockingWaiter
: public FakeWaiter
{
111 void GotEndpointLock() override
{
112 FakeWaiter::GotEndpointLock();
117 base::RunLoop run_loop_
;
120 class WebSocketEndpointLockManagerTest
: public ::testing::Test
{
122 WebSocketEndpointLockManagerTest()
123 : instance_(WebSocketEndpointLockManager::GetInstance()) {}
124 ~WebSocketEndpointLockManagerTest() override
{
125 // Permit any pending asynchronous unlock operations to complete.
127 // If this check fails then subsequent tests may fail.
128 CHECK(instance_
->IsEmpty());
131 WebSocketEndpointLockManager
* instance() const { return instance_
; }
133 IPEndPoint
DummyEndpoint() {
134 IPAddressNumber ip_address_number
;
135 CHECK(ParseIPLiteralToNumber("127.0.0.1", &ip_address_number
));
136 return IPEndPoint(ip_address_number
, 80);
139 void UnlockDummyEndpoint(int times
) {
140 for (int i
= 0; i
< times
; ++i
) {
141 instance()->UnlockEndpoint(DummyEndpoint());
146 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
148 WebSocketEndpointLockManager
* const instance_
;
149 ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_
;
152 TEST_F(WebSocketEndpointLockManagerTest
, GetInstanceWorks
) {
153 // All the work is done by the test framework.
156 TEST_F(WebSocketEndpointLockManagerTest
, LockEndpointReturnsOkOnce
) {
157 FakeWaiter waiters
[2];
158 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
159 EXPECT_EQ(ERR_IO_PENDING
,
160 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
162 UnlockDummyEndpoint(2);
165 TEST_F(WebSocketEndpointLockManagerTest
, GotEndpointLockNotCalledOnOk
) {
167 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiter
));
169 EXPECT_FALSE(waiter
.called());
171 UnlockDummyEndpoint(1);
174 TEST_F(WebSocketEndpointLockManagerTest
, GotEndpointLockNotCalledImmediately
) {
175 FakeWaiter waiters
[2];
176 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
177 EXPECT_EQ(ERR_IO_PENDING
,
178 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
180 EXPECT_FALSE(waiters
[1].called());
182 UnlockDummyEndpoint(2);
185 TEST_F(WebSocketEndpointLockManagerTest
, GotEndpointLockCalledWhenUnlocked
) {
186 FakeWaiter waiters
[2];
187 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
188 EXPECT_EQ(ERR_IO_PENDING
,
189 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
190 instance()->UnlockEndpoint(DummyEndpoint());
192 EXPECT_TRUE(waiters
[1].called());
194 UnlockDummyEndpoint(1);
197 TEST_F(WebSocketEndpointLockManagerTest
,
198 EndpointUnlockedIfWaiterAlreadyDeleted
) {
199 FakeWaiter first_lock_holder
;
200 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &first_lock_holder
));
203 FakeWaiter short_lived_waiter
;
204 EXPECT_EQ(ERR_IO_PENDING
,
205 instance()->LockEndpoint(DummyEndpoint(), &short_lived_waiter
));
208 instance()->UnlockEndpoint(DummyEndpoint());
211 FakeWaiter second_lock_holder
;
212 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &second_lock_holder
));
214 UnlockDummyEndpoint(1);
217 TEST_F(WebSocketEndpointLockManagerTest
, RememberSocketWorks
) {
218 FakeWaiter waiters
[2];
219 FakeStreamSocket dummy_socket
;
220 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
221 EXPECT_EQ(ERR_IO_PENDING
,
222 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
224 instance()->RememberSocket(&dummy_socket
, DummyEndpoint());
225 instance()->UnlockSocket(&dummy_socket
);
227 EXPECT_TRUE(waiters
[1].called());
229 UnlockDummyEndpoint(1);
232 // UnlockEndpoint() should cause any sockets remembered for this endpoint
234 TEST_F(WebSocketEndpointLockManagerTest
, SocketAssociationForgottenOnUnlock
) {
236 FakeStreamSocket dummy_socket
;
238 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiter
));
239 instance()->RememberSocket(&dummy_socket
, DummyEndpoint());
240 instance()->UnlockEndpoint(DummyEndpoint());
242 EXPECT_TRUE(instance()->IsEmpty());
245 // When ownership of the endpoint is passed to a new waiter, the new waiter can
246 // call RememberSocket() again.
247 TEST_F(WebSocketEndpointLockManagerTest
, NextWaiterCanCallRememberSocketAgain
) {
248 FakeWaiter waiters
[2];
249 FakeStreamSocket dummy_sockets
[2];
250 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
251 EXPECT_EQ(ERR_IO_PENDING
,
252 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
254 instance()->RememberSocket(&dummy_sockets
[0], DummyEndpoint());
255 instance()->UnlockEndpoint(DummyEndpoint());
257 EXPECT_TRUE(waiters
[1].called());
258 instance()->RememberSocket(&dummy_sockets
[1], DummyEndpoint());
260 UnlockDummyEndpoint(1);
263 // Calling UnlockSocket() after UnlockEndpoint() does nothing.
264 TEST_F(WebSocketEndpointLockManagerTest
,
265 UnlockSocketAfterUnlockEndpointDoesNothing
) {
266 FakeWaiter waiters
[3];
267 FakeStreamSocket dummy_socket
;
269 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
270 EXPECT_EQ(ERR_IO_PENDING
,
271 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
272 EXPECT_EQ(ERR_IO_PENDING
,
273 instance()->LockEndpoint(DummyEndpoint(), &waiters
[2]));
274 instance()->RememberSocket(&dummy_socket
, DummyEndpoint());
275 instance()->UnlockEndpoint(DummyEndpoint());
276 instance()->UnlockSocket(&dummy_socket
);
278 EXPECT_TRUE(waiters
[1].called());
279 EXPECT_FALSE(waiters
[2].called());
281 UnlockDummyEndpoint(2);
284 // UnlockEndpoint() should always be asynchronous.
285 TEST_F(WebSocketEndpointLockManagerTest
, UnlockEndpointIsAsynchronous
) {
286 FakeWaiter waiters
[2];
287 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &waiters
[0]));
288 EXPECT_EQ(ERR_IO_PENDING
,
289 instance()->LockEndpoint(DummyEndpoint(), &waiters
[1]));
291 instance()->UnlockEndpoint(DummyEndpoint());
292 EXPECT_FALSE(waiters
[1].called());
294 EXPECT_TRUE(waiters
[1].called());
296 UnlockDummyEndpoint(1);
299 // UnlockEndpoint() should normally have a delay.
300 TEST_F(WebSocketEndpointLockManagerTest
, UnlockEndpointIsDelayed
) {
301 using base::TimeTicks
;
303 // This 1ms delay is too short for very slow environments (usually those
304 // running memory checkers). In those environments, the code takes >1ms to run
305 // and no delay is needed. Rather than increase the delay and slow down the
306 // test everywhere, the test doesn't explicitly verify that a delay has been
307 // applied. Instead it just verifies that the whole thing took >=1ms. 1ms is
308 // easily enough for normal compiles even on Android, so the fact that there
309 // is a delay is still checked on every platform.
310 const base::TimeDelta unlock_delay
= base::TimeDelta::FromMilliseconds(1);
311 instance()->SetUnlockDelayForTesting(unlock_delay
);
312 FakeWaiter fake_waiter
;
313 BlockingWaiter blocking_waiter
;
314 EXPECT_EQ(OK
, instance()->LockEndpoint(DummyEndpoint(), &fake_waiter
));
315 EXPECT_EQ(ERR_IO_PENDING
,
316 instance()->LockEndpoint(DummyEndpoint(), &blocking_waiter
));
318 TimeTicks before_unlock
= TimeTicks::Now();
319 instance()->UnlockEndpoint(DummyEndpoint());
320 blocking_waiter
.WaitForLock();
321 TimeTicks after_unlock
= TimeTicks::Now();
322 EXPECT_GE(after_unlock
- before_unlock
, unlock_delay
);
323 instance()->SetUnlockDelayForTesting(base::TimeDelta());
324 UnlockDummyEndpoint(1);