1 // Copyright 2014 The Chromium Authors
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/check.h"
8 #include "base/run_loop.h"
9 #include "base/time/time.h"
10 #include "net/base/ip_address.h"
11 #include "net/base/net_errors.h"
12 #include "net/log/net_log_with_source.h"
13 #include "net/socket/next_proto.h"
14 #include "net/socket/socket_test_util.h"
15 #include "net/test/gtest_util.h"
16 #include "net/test/test_with_task_environment.h"
17 #include "net/traffic_annotation/network_traffic_annotation.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 using net::test::IsOk;
22
23 namespace net {
24
25 namespace {
26
27 class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
28 public:
29 FakeWaiter() = default;
30
GotEndpointLock()31 void GotEndpointLock() override {
32 CHECK(!called_);
33 called_ = true;
34 }
35
called() const36 bool called() const { return called_; }
37
38 private:
39 bool called_ = false;
40 };
41
42 class BlockingWaiter : public FakeWaiter {
43 public:
WaitForLock()44 void WaitForLock() {
45 while (!called()) {
46 run_loop_.Run();
47 }
48 }
49
GotEndpointLock()50 void GotEndpointLock() override {
51 FakeWaiter::GotEndpointLock();
52 run_loop_.Quit();
53 }
54
55 private:
56 base::RunLoop run_loop_;
57 };
58
59 class WebSocketEndpointLockManagerTest : public TestWithTaskEnvironment {
60 protected:
WebSocketEndpointLockManagerTest()61 WebSocketEndpointLockManagerTest() {
62 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(
63 base::TimeDelta());
64 }
65
~WebSocketEndpointLockManagerTest()66 ~WebSocketEndpointLockManagerTest() override {
67 // Permit any pending asynchronous unlock operations to complete.
68 RunUntilIdle();
69 // If this check fails then subsequent tests may fail.
70 CHECK(websocket_endpoint_lock_manager_.IsEmpty());
71 }
72
DummyEndpoint()73 IPEndPoint DummyEndpoint() {
74 return IPEndPoint(IPAddress::IPv4Localhost(), 80);
75 }
76
UnlockDummyEndpoint(int times)77 void UnlockDummyEndpoint(int times) {
78 for (int i = 0; i < times; ++i) {
79 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
80 RunUntilIdle();
81 }
82 }
83
RunUntilIdle()84 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
85
86 WebSocketEndpointLockManager websocket_endpoint_lock_manager_;
87 };
88
TEST_F(WebSocketEndpointLockManagerTest,LockEndpointReturnsOkOnce)89 TEST_F(WebSocketEndpointLockManagerTest, LockEndpointReturnsOkOnce) {
90 FakeWaiter waiters[2];
91 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]));
96
97 UnlockDummyEndpoint(2);
98 }
99
TEST_F(WebSocketEndpointLockManagerTest,GotEndpointLockNotCalledOnOk)100 TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) {
101 FakeWaiter waiter;
102 EXPECT_THAT(
103 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
104 IsOk());
105 RunUntilIdle();
106 EXPECT_FALSE(waiter.called());
107
108 UnlockDummyEndpoint(1);
109 }
110
TEST_F(WebSocketEndpointLockManagerTest,GotEndpointLockNotCalledImmediately)111 TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledImmediately) {
112 FakeWaiter waiters[2];
113 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]));
118 RunUntilIdle();
119 EXPECT_FALSE(waiters[1].called());
120
121 UnlockDummyEndpoint(2);
122 }
123
TEST_F(WebSocketEndpointLockManagerTest,GotEndpointLockCalledWhenUnlocked)124 TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockCalledWhenUnlocked) {
125 FakeWaiter waiters[2];
126 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());
132 RunUntilIdle();
133 EXPECT_TRUE(waiters[1].called());
134
135 UnlockDummyEndpoint(1);
136 }
137
TEST_F(WebSocketEndpointLockManagerTest,EndpointUnlockedIfWaiterAlreadyDeleted)138 TEST_F(WebSocketEndpointLockManagerTest,
139 EndpointUnlockedIfWaiterAlreadyDeleted) {
140 FakeWaiter first_lock_holder;
141 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(),
142 &first_lock_holder),
143 IsOk());
144
145 {
146 FakeWaiter short_lived_waiter;
147 EXPECT_EQ(ERR_IO_PENDING, websocket_endpoint_lock_manager_.LockEndpoint(
148 DummyEndpoint(), &short_lived_waiter));
149 }
150
151 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
152 RunUntilIdle();
153
154 FakeWaiter second_lock_holder;
155 EXPECT_THAT(websocket_endpoint_lock_manager_.LockEndpoint(
156 DummyEndpoint(), &second_lock_holder),
157 IsOk());
158
159 UnlockDummyEndpoint(1);
160 }
161
TEST_F(WebSocketEndpointLockManagerTest,LockReleaserWorks)162 TEST_F(WebSocketEndpointLockManagerTest, LockReleaserWorks) {
163 FakeWaiter waiters[2];
164 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]));
169
170 {
171 WebSocketEndpointLockManager::LockReleaser releaser(
172 &websocket_endpoint_lock_manager_, DummyEndpoint());
173 }
174 RunUntilIdle();
175 EXPECT_TRUE(waiters[1].called());
176
177 UnlockDummyEndpoint(1);
178 }
179
180 // UnlockEndpoint() should cause any LockReleasers for this endpoint to be
181 // unregistered.
TEST_F(WebSocketEndpointLockManagerTest,LockReleaserForgottenOnUnlock)182 TEST_F(WebSocketEndpointLockManagerTest, LockReleaserForgottenOnUnlock) {
183 FakeWaiter waiter;
184
185 EXPECT_THAT(
186 websocket_endpoint_lock_manager_.LockEndpoint(DummyEndpoint(), &waiter),
187 IsOk());
188 WebSocketEndpointLockManager::LockReleaser releaser(
189 &websocket_endpoint_lock_manager_, DummyEndpoint());
190 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
191 RunUntilIdle();
192 EXPECT_TRUE(websocket_endpoint_lock_manager_.IsEmpty());
193 }
194
195 // When ownership of the endpoint is passed to a new waiter, the new waiter can
196 // construct another LockReleaser.
TEST_F(WebSocketEndpointLockManagerTest,NextWaiterCanCreateLockReleaserAgain)197 TEST_F(WebSocketEndpointLockManagerTest, NextWaiterCanCreateLockReleaserAgain) {
198 FakeWaiter waiters[2];
199 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]));
204
205 WebSocketEndpointLockManager::LockReleaser releaser1(
206 &websocket_endpoint_lock_manager_, DummyEndpoint());
207 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
208 RunUntilIdle();
209 EXPECT_TRUE(waiters[1].called());
210 WebSocketEndpointLockManager::LockReleaser releaser2(
211 &websocket_endpoint_lock_manager_, DummyEndpoint());
212
213 UnlockDummyEndpoint(1);
214 }
215
216 // Destroying LockReleaser after UnlockEndpoint() does nothing.
TEST_F(WebSocketEndpointLockManagerTest,DestroyLockReleaserAfterUnlockEndpointDoesNothing)217 TEST_F(WebSocketEndpointLockManagerTest,
218 DestroyLockReleaserAfterUnlockEndpointDoesNothing) {
219 FakeWaiter waiters[3];
220
221 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]));
228 {
229 WebSocketEndpointLockManager::LockReleaser releaser(
230 &websocket_endpoint_lock_manager_, DummyEndpoint());
231 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
232 }
233 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.
TEST_F(WebSocketEndpointLockManagerTest,UnlockEndpointIsAsynchronous)241 TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsAsynchronous) {
242 FakeWaiter waiters[2];
243 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]));
248
249 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
250 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.
TEST_F(WebSocketEndpointLockManagerTest,UnlockEndpointIsDelayed)258 TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsDelayed) {
259 using base::TimeTicks;
260
261 // 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.
268 const base::TimeDelta unlock_delay = base::Milliseconds(1);
269 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(unlock_delay);
270 FakeWaiter fake_waiter;
271 BlockingWaiter blocking_waiter;
272 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));
277
278 TimeTicks before_unlock = TimeTicks::Now();
279 websocket_endpoint_lock_manager_.UnlockEndpoint(DummyEndpoint());
280 blocking_waiter.WaitForLock();
281 TimeTicks after_unlock = TimeTicks::Now();
282 EXPECT_GE(after_unlock - before_unlock, unlock_delay);
283 websocket_endpoint_lock_manager_.SetUnlockDelayForTesting(base::TimeDelta());
284 UnlockDummyEndpoint(1);
285 }
286
287 } // namespace
288
289 } // namespace net
290