blob: 42b897fca5d9272473e84d39ed882d9006b98ce1 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2014 The Chromium Authors
[email protected]654866142014-06-24 22:53:312// 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
Hans Wennborg0924470b2020-04-27 21:08:057#include "base/check.h"
riceabafe0f22015-01-23 05:31:258#include "base/run_loop.h"
9#include "base/time/time.h"
martijna2e83bd2016-03-18 13:10:4510#include "net/base/ip_address.h"
[email protected]654866142014-06-24 22:53:3111#include "net/base/net_errors.h"
mikecironef22f9812016-10-04 03:40:1912#include "net/log/net_log_with_source.h"
[email protected]654866142014-06-24 22:53:3113#include "net/socket/next_proto.h"
14#include "net/socket/socket_test_util.h"
robpercival214763f2016-07-01 23:27:0115#include "net/test/gtest_util.h"
Gabriel Charettec7108742019-08-23 03:31:4016#include "net/test/test_with_task_environment.h"
[email protected]a2b2cfc2017-12-06 09:06:0817#include "net/traffic_annotation/network_traffic_annotation.h"
robpercival214763f2016-07-01 23:27:0118#include "testing/gmock/include/gmock/gmock.h"
[email protected]654866142014-06-24 22:53:3119#include "testing/gtest/include/gtest/gtest.h"
20
robpercival214763f2016-07-01 23:27:0121using net::test::IsOk;
22
[email protected]654866142014-06-24 22:53:3123namespace net {
24
25namespace {
26
[email protected]654866142014-06-24 22:53:3127class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
28 public:
Tsuyoshi Horo2ec06e002022-06-09 01:38:5929 FakeWaiter() = default;
[email protected]654866142014-06-24 22:53:3130
dchengb03027d2014-10-21 12:00:2031 void GotEndpointLock() override {
[email protected]654866142014-06-24 22:53:3132 CHECK(!called_);
33 called_ = true;
34 }
35
36 bool called() const { return called_; }
37
38 private:
Tsuyoshi Horo2ec06e002022-06-09 01:38:5939 bool called_ = false;
[email protected]654866142014-06-24 22:53:3140};
41
ricea6da0ff62015-01-27 08:15:1942class BlockingWaiter : public FakeWaiter {
43 public:
44 void WaitForLock() {
45 while (!called()) {
46 run_loop_.Run();
47 }
48 }
49
50 void GotEndpointLock() override {
51 FakeWaiter::GotEndpointLock();
52 run_loop_.Quit();
53 }
54
55 private:
56 base::RunLoop run_loop_;
57};
58
Gabriel Charette694c3c332019-08-19 14:53:0559class WebSocketEndpointLockManagerTest : public TestWithTaskEnvironment {
[email protected]654866142014-06-24 22:53:3160 protected:
Bence Békyda280c62018-04-12 15:08:3761 WebSocketEndpointLockManagerTest() {
62 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(
63 base::TimeDelta());
64 }
65
dcheng67be2b1f2014-10-27 21:47:2966 ~WebSocketEndpointLockManagerTest() override {
riceabafe0f22015-01-23 05:31:2567 // Permit any pending asynchronous unlock operations to complete.
68 RunUntilIdle();
[email protected]654866142014-06-24 22:53:3169 // If this check fails then subsequent tests may fail.
Bence Békyda280c62018-04-12 15:08:3770 CHECK(websocket_endpoint_lock_manager_.IsEmpty());
[email protected]654866142014-06-24 22:53:3171 }
72
[email protected]654866142014-06-24 22:53:3173 IPEndPoint DummyEndpoint() {
martijna2e83bd2016-03-18 13:10:4574 return IPEndPoint(IPAddress::IPv4Localhost(), 80);
[email protected]654866142014-06-24 22:53:3175 }
76
77 void UnlockDummyEndpoint(int times) {
78 for (int i = 0; i < times; ++i) {
Bence Békyda280c62018-04-12 15:08:3779 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:2580 RunUntilIdle();
[email protected]654866142014-06-24 22:53:3181 }
82 }
83
riceabafe0f22015-01-23 05:31:2584 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
85
Bence Békyda280c62018-04-12 15:08:3786 WebSocketEndpointLockManager websocket_endpoint_lock_manager_;
[email protected]654866142014-06-24 22:53:3187};
88
[email protected]654866142014-06-24 22:53:3189TEST_F(WebSocketEndpointLockManagerTest, LockEndpointReturnsOkOnce) {
90 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:3791 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
92 &waiters[0]),
93 IsOk());
94 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
95 DummyEndpoint(), &waiters[1]));
[email protected]654866142014-06-24 22:53:3196
97 UnlockDummyEndpoint(2);
98}
99
100TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) {
101 FakeWaiter waiter;
Bence Békyda280c62018-04-12 15:08:37102 EXPECT_THAT(
103 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
104 IsOk());
riceabafe0f22015-01-23 05:31:25105 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31106 EXPECT_FALSE(waiter.called());
107
108 UnlockDummyEndpoint(1);
109}
110
111TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledImmediately) {
112 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37113 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
114 &waiters[0]),
115 IsOk());
116 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
117 DummyEndpoint(), &waiters[1]));
riceabafe0f22015-01-23 05:31:25118 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31119 EXPECT_FALSE(waiters[1].called());
120
121 UnlockDummyEndpoint(2);
122}
123
124TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockCalledWhenUnlocked) {
125 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37126 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
127 &waiters[0]),
128 IsOk());
129 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
130 DummyEndpoint(), &waiters[1]));
131 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25132 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31133 EXPECT_TRUE(waiters[1].called());
134
135 UnlockDummyEndpoint(1);
136}
137
138TEST_F(WebSocketEndpointLockManagerTest,
139 EndpointUnlockedIfWaiterAlreadyDeleted) {
140 FakeWaiter first_lock_holder;
Bence Békyda280c62018-04-12 15:08:37141 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
142 &first_lock_holder),
robpercival214763f2016-07-01 23:27:01143 IsOk());
[email protected]654866142014-06-24 22:53:31144
145 {
146 FakeWaiter short_lived_waiter;
Bence Békyda280c62018-04-12 15:08:37147 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
148 DummyEndpoint(), &short_lived_waiter));
[email protected]654866142014-06-24 22:53:31149 }
150
Bence Békyda280c62018-04-12 15:08:37151 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25152 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31153
154 FakeWaiter second_lock_holder;
Bence Békyda280c62018-04-12 15:08:37155 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(
156 DummyEndpoint(), &second_lock_holder),
robpercival214763f2016-07-01 23:27:01157 IsOk());
[email protected]654866142014-06-24 22:53:31158
159 UnlockDummyEndpoint(1);
160}
161
Adam Ricea0e71392019-02-14 13:29:41162TEST_F(WebSocketEndpointLockManagerTest, LockReleaserWorks) {
[email protected]654866142014-06-24 22:53:31163 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37164 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
165 &waiters[0]),
166 IsOk());
167 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
168 DummyEndpoint(), &waiters[1]));
[email protected]654866142014-06-24 22:53:31169
Adam Ricea0e71392019-02-14 13:29:41170 {
171 WebSocketEndpointLockManager::LockReleaser releaser(
172 &websocket_endpoint_lock_manager_, DummyEndpoint());
173 }
riceabafe0f22015-01-23 05:31:25174 RunUntilIdle();
[email protected]654866142014-06-24 22:53:31175 EXPECT_TRUE(waiters[1].called());
176
177 UnlockDummyEndpoint(1);
178}
179
Adam Ricea0e71392019-02-14 13:29:41180// UnlockEndpoint() should cause any LockReleasers for this endpoint to be
181// unregistered.
182TEST_F(WebSocketEndpointLockManagerTest, LockReleaserForgottenOnUnlock) {
[email protected]654866142014-06-24 22:53:31183 FakeWaiter waiter;
[email protected]6bcd67d2014-08-05 16:31:24184
Bence Békyda280c62018-04-12 15:08:37185 EXPECT_THAT(
186 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
187 IsOk());
Adam Ricea0e71392019-02-14 13:29:41188 WebSocketEndpointLockManager::LockReleaser releaser(
189 &websocket_endpoint_lock_manager_, DummyEndpoint());
Bence Békyda280c62018-04-12 15:08:37190 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25191 RunUntilIdle();
Bence Békyda280c62018-04-12 15:08:37192 EXPECT_TRUE(websocket_endpoint_lock_manager_.IsEmpty());
[email protected]6bcd67d2014-08-05 16:31:24193}
194
195// When ownership of the endpoint is passed to a new waiter, the new waiter can
Adam Ricea0e71392019-02-14 13:29:41196// construct another LockReleaser.
197TEST_F(WebSocketEndpointLockManagerTest, NextWaiterCanCreateLockReleaserAgain) {
[email protected]6bcd67d2014-08-05 16:31:24198 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37199 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
200 &waiters[0]),
201 IsOk());
202 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
203 DummyEndpoint(), &waiters[1]));
[email protected]6bcd67d2014-08-05 16:31:24204
Adam Ricea0e71392019-02-14 13:29:41205 WebSocketEndpointLockManager::LockReleaser releaser1(
206 &websocket_endpoint_lock_manager_, DummyEndpoint());
Bence Békyda280c62018-04-12 15:08:37207 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25208 RunUntilIdle();
[email protected]6bcd67d2014-08-05 16:31:24209 EXPECT_TRUE(waiters[1].called());
Adam Ricea0e71392019-02-14 13:29:41210 WebSocketEndpointLockManager::LockReleaser releaser2(
211 &websocket_endpoint_lock_manager_, DummyEndpoint());
[email protected]6bcd67d2014-08-05 16:31:24212
213 UnlockDummyEndpoint(1);
[email protected]654866142014-06-24 22:53:31214}
215
Adam Ricea0e71392019-02-14 13:29:41216// Destroying LockReleaser after UnlockEndpoint() does nothing.
riceabafe0f22015-01-23 05:31:25217TEST_F(WebSocketEndpointLockManagerTest,
Adam Ricea0e71392019-02-14 13:29:41218 DestroyLockReleaserAfterUnlockEndpointDoesNothing) {
riceabafe0f22015-01-23 05:31:25219 FakeWaiter waiters[3];
riceabafe0f22015-01-23 05:31:25220
Bence Békyda280c62018-04-12 15:08:37221 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
222 &waiters[0]),
223 IsOk());
224 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
225 DummyEndpoint(), &waiters[1]));
226 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
227 DummyEndpoint(), &waiters[2]));
Adam Ricea0e71392019-02-14 13:29:41228 {
229 WebSocketEndpointLockManager::LockReleaser releaser(
230 &websocket_endpoint_lock_manager_, DummyEndpoint());
231 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
232 }
riceabafe0f22015-01-23 05:31:25233 RunUntilIdle();
234 EXPECT_TRUE(waiters[1].called());
235 EXPECT_FALSE(waiters[2].called());
236
237 UnlockDummyEndpoint(2);
238}
239
240// UnlockEndpoint() should always be asynchronous.
241TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsAsynchronous) {
242 FakeWaiter waiters[2];
Bence Békyda280c62018-04-12 15:08:37243 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
244 &waiters[0]),
245 IsOk());
246 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
247 DummyEndpoint(), &waiters[1]));
riceabafe0f22015-01-23 05:31:25248
Bence Békyda280c62018-04-12 15:08:37249 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
riceabafe0f22015-01-23 05:31:25250 EXPECT_FALSE(waiters[1].called());
251 RunUntilIdle();
252 EXPECT_TRUE(waiters[1].called());
253
254 UnlockDummyEndpoint(1);
255}
256
257// UnlockEndpoint() should normally have a delay.
258TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsDelayed) {
ricea6da0ff62015-01-27 08:15:19259 using base::TimeTicks;
riceabafe0f22015-01-23 05:31:25260
riceaba683622015-02-01 18:16:53261 // This 1ms delay is too short for very slow environments (usually those
262 // running memory checkers). In those environments, the code takes >1ms to run
263 // and no delay is needed. Rather than increase the delay and slow down the
264 // test everywhere, the test doesn't explicitly verify that a delay has been
265 // applied. Instead it just verifies that the whole thing took >=1ms. 1ms is
266 // easily enough for normal compiles even on Android, so the fact that there
267 // is a delay is still checked on every platform.
Peter Kastinge5a38ed2021-10-02 03:06:35268 const base::TimeDelta unlock_delay = base::Milliseconds(1);
Bence Békyda280c62018-04-12 15:08:37269 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(unlock_delay);
ricea6da0ff62015-01-27 08:15:19270 FakeWaiter fake_waiter;
271 BlockingWaiter blocking_waiter;
Bence Békyda280c62018-04-12 15:08:37272 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
273 &fake_waiter),
274 IsOk());
275 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
276 DummyEndpoint(), &blocking_waiter));
ricea6da0ff62015-01-27 08:15:19277
278 TimeTicks before_unlock = TimeTicks::Now();
Bence Békyda280c62018-04-12 15:08:37279 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
ricea6da0ff62015-01-27 08:15:19280 blocking_waiter.WaitForLock();
281 TimeTicks after_unlock = TimeTicks::Now();
282 EXPECT_GE(after_unlock - before_unlock, unlock_delay);
Bence Békyda280c62018-04-12 15:08:37283 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(base::TimeDelta());
riceabafe0f22015-01-23 05:31:25284 UnlockDummyEndpoint(1);
285}
286
[email protected]654866142014-06-24 22:53:31287} // namespace
288
289} // namespace net