blob: 8c3fcc1601076ecbdec217b4778e296fea361daf [file] [log] [blame]
[email protected]654866142014-06-24 22:53:311// 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
tbansalf82cc8e2015-10-14 20:05:497#include "base/logging.h"
Avi Drissman13fc8932015-12-20 04:40:468#include "base/macros.h"
riceabafe0f22015-01-23 05:31:259#include "base/run_loop.h"
10#include "base/time/time.h"
martijna2e83bd2016-03-18 13:10:4511#include "net/base/ip_address.h"
[email protected]654866142014-06-24 22:53:3112#include "net/base/net_errors.h"
mikecironef22f9812016-10-04 03:40:1913#include "net/log/net_log_with_source.h"
[email protected]654866142014-06-24 22:53:3114#include "net/socket/next_proto.h"
15#include "net/socket/socket_test_util.h"
robpercival214763f2016-07-01 23:27:0116#include "net/test/gtest_util.h"
Gabriel Charettec7108742019-08-23 03:31:4017#include "net/test/test_with_task_environment.h"
[email protected]a2b2cfc2017-12-06 09:06:0818#include "net/traffic_annotation/network_traffic_annotation.h"
robpercival214763f2016-07-01 23:27:0119#include "testing/gmock/include/gmock/gmock.h"
[email protected]654866142014-06-24 22:53:3120#include "testing/gtest/include/gtest/gtest.h"
21
robpercival214763f2016-07-01 23:27:0122using net::test::IsOk;
23
[email protected]654866142014-06-24 22:53:3124namespace net {
25
26namespace {
27
[email protected]654866142014-06-24 22:53:3128class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
29 public:
30 FakeWaiter() : called_(false) {}
31
dchengb03027d2014-10-21 12:00:2032 void GotEndpointLock() override {
[email protected]654866142014-06-24 22:53:3133 CHECK(!called_);
34 called_ = true;
35 }
36
37 bool called() const { return called_; }
38
39 private:
40 bool called_;
41};
42
ricea6da0ff62015-01-27 08:15:1943class BlockingWaiter : public FakeWaiter {
44 public:
45 void WaitForLock() {
46 while (!called()) {
47 run_loop_.Run();
48 }
49 }
50
51 void GotEndpointLock() override {
52 FakeWaiter::GotEndpointLock();
53 run_loop_.Quit();
54 }
55
56 private:
57 base::RunLoop run_loop_;
58};
59
Gabriel Charette694c3c332019-08-19 14:53:0560class WebSocketEndpointLockManagerTest : public TestWithTaskEnvironment {
[email protected]654866142014-06-24 22:53:3161 protected:
Bence Békyda280c62018-04-12 15:08:3762 WebSocketEndpointLockManagerTest() {
63 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(
64 base::TimeDelta());
65 }
66
dcheng67be2b1f2014-10-27 21:47:2967 ~WebSocketEndpointLockManagerTest() override {
riceabafe0f22015-01-23 05:31:2568 // Permit any pending asynchronous unlock operations to complete.
69 RunUntilIdle();
[email protected]654866142014-06-24 22:53:3170 // If this check fails then subsequent tests may fail.
Bence Békyda280c62018-04-12 15:08:3771 CHECK(websocket_endpoint_lock_manager_.IsEmpty());
[email protected]654866142014-06-24 22:53:3172 }
73
[email protected]654866142014-06-24 22:53:3174 IPEndPoint DummyEndpoint() {
martijna2e83bd2016-03-18 13:10:4575 return IPEndPoint(IPAddress::IPv4Localhost(), 80);
[email protected]654866142014-06-24 22:53:3176 }
77
78 void UnlockDummyEndpoint(int times) {
79 for (int i = 0; i < times; ++i) {
Bence Békyda280c62018-04-12 15:08:3780 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:2581 RunUntilIdle();
[email protected]654866142014-06-24 22:53:3182 }
83 }
84
riceabafe0f22015-01-23 05:31:2585 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
86
Bence Békyda280c62018-04-12 15:08:3787 WebSocketEndpointLockManager websocket_endpoint_lock_manager_;
[email protected]654866142014-06-24 22:53:3188};
89
[email protected]654866142014-06-24 22:53:3190TEST_F(WebSocketEndpointLockManagerTest, LockEndpointReturnsOkOnce) {
91 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:3792 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
93 &waiters[0]),
94 IsOk());
95 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
96 DummyEndpoint(), &waiters[1]));
[email protected]654866142014-06-24 22:53:3197
98 UnlockDummyEndpoint(2);
99}
100
101TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) {
102 FakeWaiter waiter;
Bence Békyda280c62018-04-12 15:08:37103 EXPECT_THAT(
104 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
105 IsOk());
riceabafe0f22015-01-23 05:31:25106 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31107 EXPECT_FALSE(waiter.called());
108
109 UnlockDummyEndpoint(1);
110}
111
112TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledImmediately) {
113 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37114 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
115 &waiters[0]),
116 IsOk());
117 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
118 DummyEndpoint(), &waiters[1]));
riceabafe0f22015-01-23 05:31:25119 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31120 EXPECT_FALSE(waiters[1].called());
121
122 UnlockDummyEndpoint(2);
123}
124
125TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockCalledWhenUnlocked) {
126 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37127 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
128 &waiters[0]),
129 IsOk());
130 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
131 DummyEndpoint(), &waiters[1]));
132 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25133 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31134 EXPECT_TRUE(waiters[1].called());
135
136 UnlockDummyEndpoint(1);
137}
138
139TEST_F(WebSocketEndpointLockManagerTest,
140 EndpointUnlockedIfWaiterAlreadyDeleted) {
141 FakeWaiter first_lock_holder;
Bence Békyda280c62018-04-12 15:08:37142 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
143 &first_lock_holder),
robpercival214763f2016-07-01 23:27:01144 IsOk());
[email protected]654866142014-06-24 22:53:31145
146 {
147 FakeWaiter short_lived_waiter;
Bence Békyda280c62018-04-12 15:08:37148 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
149 DummyEndpoint(), &short_lived_waiter));
[email protected]654866142014-06-24 22:53:31150 }
151
Bence Békyda280c62018-04-12 15:08:37152 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25153 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31154
155 FakeWaiter second_lock_holder;
Bence Békyda280c62018-04-12 15:08:37156 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(
157 DummyEndpoint(), &second_lock_holder),
robpercival214763f2016-07-01 23:27:01158 IsOk());
[email protected]654866142014-06-24 22:53:31159
160 UnlockDummyEndpoint(1);
161}
162
Adam Ricea0e71392019-02-14 13:29:41163TEST_F(WebSocketEndpointLockManagerTest, LockReleaserWorks) {
[email protected]654866142014-06-24 22:53:31164 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37165 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
166 &waiters[0]),
167 IsOk());
168 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
169 DummyEndpoint(), &waiters[1]));
[email protected]654866142014-06-24 22:53:31170
Adam Ricea0e71392019-02-14 13:29:41171 {
172 WebSocketEndpointLockManager::LockReleaser releaser(
173 &websocket_endpoint_lock_manager_, DummyEndpoint());
174 }
riceabafe0f22015-01-23 05:31:25175 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31176 EXPECT_TRUE(waiters[1].called());
177
178 UnlockDummyEndpoint(1);
179}
180
Adam Ricea0e71392019-02-14 13:29:41181// UnlockEndpoint() should cause any LockReleasers for this endpoint to be
182// unregistered.
183TEST_F(WebSocketEndpointLockManagerTest, LockReleaserForgottenOnUnlock) {
[email protected]654866142014-06-24 22:53:31184 FakeWaiter waiter;
[email protected]6bcd67d2014-08-05 16:31:24185
Bence Békyda280c62018-04-12 15:08:37186 EXPECT_THAT(
187 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
188 IsOk());
Adam Ricea0e71392019-02-14 13:29:41189 WebSocketEndpointLockManager::LockReleaser releaser(
190 &websocket_endpoint_lock_manager_, DummyEndpoint());
Bence Békyda280c62018-04-12 15:08:37191 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25192 RunUntilIdle();
Bence Békyda280c62018-04-12 15:08:37193 EXPECT_TRUE(websocket_endpoint_lock_manager_.IsEmpty());
[email protected]6bcd67d2014-08-05 16:31:24194}
195
196// When ownership of the endpoint is passed to a new waiter, the new waiter can
Adam Ricea0e71392019-02-14 13:29:41197// construct another LockReleaser.
198TEST_F(WebSocketEndpointLockManagerTest, NextWaiterCanCreateLockReleaserAgain) {
[email protected]6bcd67d2014-08-05 16:31:24199 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37200 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
201 &waiters[0]),
202 IsOk());
203 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
204 DummyEndpoint(), &waiters[1]));
[email protected]6bcd67d2014-08-05 16:31:24205
Adam Ricea0e71392019-02-14 13:29:41206 WebSocketEndpointLockManager::LockReleaser releaser1(
207 &websocket_endpoint_lock_manager_, DummyEndpoint());
Bence Békyda280c62018-04-12 15:08:37208 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25209 RunUntilIdle();
[email protected]6bcd67d2014-08-05 16:31:24210 EXPECT_TRUE(waiters[1].called());
Adam Ricea0e71392019-02-14 13:29:41211 WebSocketEndpointLockManager::LockReleaser releaser2(
212 &websocket_endpoint_lock_manager_, DummyEndpoint());
[email protected]6bcd67d2014-08-05 16:31:24213
214 UnlockDummyEndpoint(1);
[email protected]654866142014-06-24 22:53:31215}
216
Adam Ricea0e71392019-02-14 13:29:41217// Destroying LockReleaser after UnlockEndpoint() does nothing.
riceabafe0f22015-01-23 05:31:25218TEST_F(WebSocketEndpointLockManagerTest,
Adam Ricea0e71392019-02-14 13:29:41219 DestroyLockReleaserAfterUnlockEndpointDoesNothing) {
riceabafe0f22015-01-23 05:31:25220 FakeWaiter waiters[3];
riceabafe0f22015-01-23 05:31:25221
Bence Békyda280c62018-04-12 15:08:37222 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
223 &waiters[0]),
224 IsOk());
225 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
226 DummyEndpoint(), &waiters[1]));
227 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
228 DummyEndpoint(), &waiters[2]));
Adam Ricea0e71392019-02-14 13:29:41229 {
230 WebSocketEndpointLockManager::LockReleaser releaser(
231 &websocket_endpoint_lock_manager_, DummyEndpoint());
232 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
233 }
riceabafe0f22015-01-23 05:31:25234 RunUntilIdle();
235 EXPECT_TRUE(waiters[1].called());
236 EXPECT_FALSE(waiters[2].called());
237
238 UnlockDummyEndpoint(2);
239}
240
241// UnlockEndpoint() should always be asynchronous.
242TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsAsynchronous) {
243 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37244 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
245 &waiters[0]),
246 IsOk());
247 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
248 DummyEndpoint(), &waiters[1]));
riceabafe0f22015-01-23 05:31:25249
Bence Békyda280c62018-04-12 15:08:37250 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25251 EXPECT_FALSE(waiters[1].called());
252 RunUntilIdle();
253 EXPECT_TRUE(waiters[1].called());
254
255 UnlockDummyEndpoint(1);
256}
257
258// UnlockEndpoint() should normally have a delay.
259TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsDelayed) {
ricea6da0ff62015-01-27 08:15:19260 using base::TimeTicks;
riceabafe0f22015-01-23 05:31:25261
riceaba683622015-02-01 18:16:53262 // This 1ms delay is too short for very slow environments (usually those
263 // running memory checkers). In those environments, the code takes >1ms to run
264 // and no delay is needed. Rather than increase the delay and slow down the
265 // test everywhere, the test doesn't explicitly verify that a delay has been
266 // applied. Instead it just verifies that the whole thing took >=1ms. 1ms is
267 // easily enough for normal compiles even on Android, so the fact that there
268 // is a delay is still checked on every platform.
ricea6da0ff62015-01-27 08:15:19269 const base::TimeDelta unlock_delay = base::TimeDelta::FromMilliseconds(1);
Bence Békyda280c62018-04-12 15:08:37270 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(unlock_delay);
ricea6da0ff62015-01-27 08:15:19271 FakeWaiter fake_waiter;
272 BlockingWaiter blocking_waiter;
Bence Békyda280c62018-04-12 15:08:37273 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
274 &fake_waiter),
275 IsOk());
276 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
277 DummyEndpoint(), &blocking_waiter));
ricea6da0ff62015-01-27 08:15:19278
279 TimeTicks before_unlock = TimeTicks::Now();
Bence Békyda280c62018-04-12 15:08:37280 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
ricea6da0ff62015-01-27 08:15:19281 blocking_waiter.WaitForLock();
282 TimeTicks after_unlock = TimeTicks::Now();
283 EXPECT_GE(after_unlock - before_unlock, unlock_delay);
Bence Békyda280c62018-04-12 15:08:37284 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(base::TimeDelta());
riceabafe0f22015-01-23 05:31:25285 UnlockDummyEndpoint(1);
286}
287
[email protected]654866142014-06-24 22:53:31288} // namespace
289
290} // namespace net