blob: 44e6e920268908850bf107231b6414e47334ef39 [file] [log] [blame]
Andrew Top0d1858f2019-05-15 22:01:47 -07001// 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.
4
5#include "net/socket/websocket_endpoint_lock_manager.h"
6
7#include "base/logging.h"
8#include "base/macros.h"
9#include "base/run_loop.h"
10#include "base/time/time.h"
11#include "net/base/ip_address.h"
12#include "net/base/net_errors.h"
13#include "net/log/net_log_with_source.h"
14#include "net/socket/next_proto.h"
15#include "net/socket/socket_test_util.h"
16#include "net/socket/stream_socket.h"
17#include "net/test/gtest_util.h"
18#include "net/test/test_with_scoped_task_environment.h"
19#include "net/traffic_annotation/network_traffic_annotation.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23using net::test::IsOk;
24
25namespace net {
26
27namespace {
28
29// A StreamSocket implementation with no functionality at all.
30// TODO(ricea): If you need to use this in another file, please move it to
31// socket_test_util.h.
32class FakeStreamSocket : public StreamSocket {
33 public:
34 FakeStreamSocket() = default;
35
36 // StreamSocket implementation
37 int Connect(CompletionOnceCallback callback) override { return ERR_FAILED; }
38
39 void Disconnect() override { return; }
40
41 bool IsConnected() const override { return false; }
42
43 bool IsConnectedAndIdle() const override { return false; }
44
45 int GetPeerAddress(IPEndPoint* address) const override { return ERR_FAILED; }
46
47 int GetLocalAddress(IPEndPoint* address) const override { return ERR_FAILED; }
48
49 const NetLogWithSource& NetLog() const override { return net_log_; }
50
51 bool WasEverUsed() const override { return false; }
52
53 bool WasAlpnNegotiated() const override { return false; }
54
55 NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
56
57 bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
58
59 void GetConnectionAttempts(ConnectionAttempts* out) const override {
60 out->clear();
61 }
62
63 void ClearConnectionAttempts() override {}
64
65 void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
66
67 int64_t GetTotalReceivedBytes() const override {
68 NOTIMPLEMENTED();
69 return 0;
70 }
71
72 void ApplySocketTag(const SocketTag& tag) override {}
73
74 // Socket implementation
75 int Read(IOBuffer* buf,
76 int buf_len,
77 CompletionOnceCallback callback) override {
78 return ERR_FAILED;
79 }
80
81 int Write(IOBuffer* buf,
82 int buf_len,
83 CompletionOnceCallback callback,
84 const NetworkTrafficAnnotationTag& traffic_annotation) override {
85 return ERR_FAILED;
86 }
87
88 int SetReceiveBufferSize(int32_t size) override { return ERR_FAILED; }
89
90 int SetSendBufferSize(int32_t size) override { return ERR_FAILED; }
91
92 private:
93 NetLogWithSource net_log_;
94
95 DISALLOW_COPY_AND_ASSIGN(FakeStreamSocket);
96};
97
98class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
99 public:
100 FakeWaiter() : called_(false) {}
101
102 void GotEndpointLock() override {
103 CHECK(!called_);
104 called_ = true;
105 }
106
107 bool called() const { return called_; }
108
109 private:
110 bool called_;
111};
112
113class BlockingWaiter : public FakeWaiter {
114 public:
115 void WaitForLock() {
116 while (!called()) {
117 run_loop_.Run();
118 }
119 }
120
121 void GotEndpointLock() override {
122 FakeWaiter::GotEndpointLock();
123 run_loop_.Quit();
124 }
125
126 private:
127 base::RunLoop run_loop_;
128};
129
130class WebSocketEndpointLockManagerTest : public TestWithScopedTaskEnvironment {
131 protected:
132 WebSocketEndpointLockManagerTest() {
133 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(
134 base::TimeDelta());
135 }
136
137 ~WebSocketEndpointLockManagerTest() override {
138 // Permit any pending asynchronous unlock operations to complete.
139 RunUntilIdle();
140 // If this check fails then subsequent tests may fail.
141 CHECK(websocket_endpoint_lock_manager_.IsEmpty());
142 }
143
144 IPEndPoint DummyEndpoint() {
145 return IPEndPoint(IPAddress::IPv4Localhost(), 80);
146 }
147
148 void UnlockDummyEndpoint(int times) {
149 for (int i = 0; i < times; ++i) {
150 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
151 RunUntilIdle();
152 }
153 }
154
155 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
156
157 WebSocketEndpointLockManager websocket_endpoint_lock_manager_;
158};
159
160TEST_F(WebSocketEndpointLockManagerTest, LockEndpointReturnsOkOnce) {
161 FakeWaiter waiters[2];
162 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
163 &waiters[0]),
164 IsOk());
165 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
166 DummyEndpoint(), &waiters[1]));
167
168 UnlockDummyEndpoint(2);
169}
170
171TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) {
172 FakeWaiter waiter;
173 EXPECT_THAT(
174 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
175 IsOk());
176 RunUntilIdle();
177 EXPECT_FALSE(waiter.called());
178
179 UnlockDummyEndpoint(1);
180}
181
182TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledImmediately) {
183 FakeWaiter waiters[2];
184 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
185 &waiters[0]),
186 IsOk());
187 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
188 DummyEndpoint(), &waiters[1]));
189 RunUntilIdle();
190 EXPECT_FALSE(waiters[1].called());
191
192 UnlockDummyEndpoint(2);
193}
194
195TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockCalledWhenUnlocked) {
196 FakeWaiter waiters[2];
197 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
198 &waiters[0]),
199 IsOk());
200 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
201 DummyEndpoint(), &waiters[1]));
202 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
203 RunUntilIdle();
204 EXPECT_TRUE(waiters[1].called());
205
206 UnlockDummyEndpoint(1);
207}
208
209TEST_F(WebSocketEndpointLockManagerTest,
210 EndpointUnlockedIfWaiterAlreadyDeleted) {
211 FakeWaiter first_lock_holder;
212 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
213 &first_lock_holder),
214 IsOk());
215
216 {
217 FakeWaiter short_lived_waiter;
218 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
219 DummyEndpoint(), &short_lived_waiter));
220 }
221
222 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
223 RunUntilIdle();
224
225 FakeWaiter second_lock_holder;
226 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(
227 DummyEndpoint(), &second_lock_holder),
228 IsOk());
229
230 UnlockDummyEndpoint(1);
231}
232
233TEST_F(WebSocketEndpointLockManagerTest, RememberSocketWorks) {
234 FakeWaiter waiters[2];
235 FakeStreamSocket dummy_socket;
236 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
237 &waiters[0]),
238 IsOk());
239 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
240 DummyEndpoint(), &waiters[1]));
241
242 websocket_endpoint_lock_manager_.RememberSocket(&dummy_socket,
243 DummyEndpoint());
244 websocket_endpoint_lock_manager_.UnlockSocket(&dummy_socket);
245 RunUntilIdle();
246 EXPECT_TRUE(waiters[1].called());
247
248 UnlockDummyEndpoint(1);
249}
250
251// UnlockEndpoint() should cause any sockets remembered for this endpoint
252// to be forgotten.
253TEST_F(WebSocketEndpointLockManagerTest, SocketAssociationForgottenOnUnlock) {
254 FakeWaiter waiter;
255 FakeStreamSocket dummy_socket;
256
257 EXPECT_THAT(
258 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
259 IsOk());
260 websocket_endpoint_lock_manager_.RememberSocket(&dummy_socket,
261 DummyEndpoint());
262 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
263 RunUntilIdle();
264 EXPECT_TRUE(websocket_endpoint_lock_manager_.IsEmpty());
265}
266
267// When ownership of the endpoint is passed to a new waiter, the new waiter can
268// call RememberSocket() again.
269TEST_F(WebSocketEndpointLockManagerTest, NextWaiterCanCallRememberSocketAgain) {
270 FakeWaiter waiters[2];
271 FakeStreamSocket dummy_sockets[2];
272 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
273 &waiters[0]),
274 IsOk());
275 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
276 DummyEndpoint(), &waiters[1]));
277
278 websocket_endpoint_lock_manager_.RememberSocket(&dummy_sockets[0],
279 DummyEndpoint());
280 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
281 RunUntilIdle();
282 EXPECT_TRUE(waiters[1].called());
283 websocket_endpoint_lock_manager_.RememberSocket(&dummy_sockets[1],
284 DummyEndpoint());
285
286 UnlockDummyEndpoint(1);
287}
288
289// Calling UnlockSocket() after UnlockEndpoint() does nothing.
290TEST_F(WebSocketEndpointLockManagerTest,
291 UnlockSocketAfterUnlockEndpointDoesNothing) {
292 FakeWaiter waiters[3];
293 FakeStreamSocket dummy_socket;
294
295 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
296 &waiters[0]),
297 IsOk());
298 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
299 DummyEndpoint(), &waiters[1]));
300 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
301 DummyEndpoint(), &waiters[2]));
302 websocket_endpoint_lock_manager_.RememberSocket(&dummy_socket,
303 DummyEndpoint());
304 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
305 websocket_endpoint_lock_manager_.UnlockSocket(&dummy_socket);
306 RunUntilIdle();
307 EXPECT_TRUE(waiters[1].called());
308 EXPECT_FALSE(waiters[2].called());
309
310 UnlockDummyEndpoint(2);
311}
312
313// UnlockEndpoint() should always be asynchronous.
314TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsAsynchronous) {
315 FakeWaiter waiters[2];
316 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
317 &waiters[0]),
318 IsOk());
319 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
320 DummyEndpoint(), &waiters[1]));
321
322 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
323 EXPECT_FALSE(waiters[1].called());
324 RunUntilIdle();
325 EXPECT_TRUE(waiters[1].called());
326
327 UnlockDummyEndpoint(1);
328}
329
330// UnlockEndpoint() should normally have a delay.
331TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsDelayed) {
332 using base::TimeTicks;
333
334 // This 1ms delay is too short for very slow environments (usually those
335 // running memory checkers). In those environments, the code takes >1ms to run
336 // and no delay is needed. Rather than increase the delay and slow down the
337 // test everywhere, the test doesn't explicitly verify that a delay has been
338 // applied. Instead it just verifies that the whole thing took >=1ms. 1ms is
339 // easily enough for normal compiles even on Android, so the fact that there
340 // is a delay is still checked on every platform.
341 const base::TimeDelta unlock_delay = base::TimeDelta::FromMilliseconds(1);
342 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(unlock_delay);
343 FakeWaiter fake_waiter;
344 BlockingWaiter blocking_waiter;
345 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
346 &fake_waiter),
347 IsOk());
348 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
349 DummyEndpoint(), &blocking_waiter));
350
351 TimeTicks before_unlock = TimeTicks::Now();
352 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
353 blocking_waiter.WaitForLock();
354 TimeTicks after_unlock = TimeTicks::Now();
355 EXPECT_GE(after_unlock - before_unlock, unlock_delay);
356 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(base::TimeDelta());
357 UnlockDummyEndpoint(1);
358}
359
360} // namespace
361
362} // namespace net