Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / net / socket / websocket_endpoint_lock_manager_unittest.cc
blob29fc067b73344f926dab94df7a4f88dbb31c346e
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"
16 namespace net {
18 namespace {
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 {
24 public:
25 FakeStreamSocket() {}
27 // StreamSocket implementation
28 int Connect(const CompletionCallback& callback) override {
29 return ERR_FAILED;
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 {
58 out->clear();
61 void ClearConnectionAttempts() override {}
63 void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
65 // Socket implementation
66 int Read(IOBuffer* buf,
67 int buf_len,
68 const CompletionCallback& callback) override {
69 return ERR_FAILED;
72 int Write(IOBuffer* buf,
73 int buf_len,
74 const CompletionCallback& callback) override {
75 return ERR_FAILED;
78 int SetReceiveBufferSize(int32 size) override { return ERR_FAILED; }
80 int SetSendBufferSize(int32 size) override { return ERR_FAILED; }
82 private:
83 BoundNetLog bound_net_log_;
85 DISALLOW_COPY_AND_ASSIGN(FakeStreamSocket);
88 class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
89 public:
90 FakeWaiter() : called_(false) {}
92 void GotEndpointLock() override {
93 CHECK(!called_);
94 called_ = true;
97 bool called() const { return called_; }
99 private:
100 bool called_;
103 class BlockingWaiter : public FakeWaiter {
104 public:
105 void WaitForLock() {
106 while (!called()) {
107 run_loop_.Run();
111 void GotEndpointLock() override {
112 FakeWaiter::GotEndpointLock();
113 run_loop_.Quit();
116 private:
117 base::RunLoop run_loop_;
120 class WebSocketEndpointLockManagerTest : public ::testing::Test {
121 protected:
122 WebSocketEndpointLockManagerTest()
123 : instance_(WebSocketEndpointLockManager::GetInstance()) {}
124 ~WebSocketEndpointLockManagerTest() override {
125 // Permit any pending asynchronous unlock operations to complete.
126 RunUntilIdle();
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());
142 RunUntilIdle();
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) {
166 FakeWaiter waiter;
167 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter));
168 RunUntilIdle();
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]));
179 RunUntilIdle();
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());
191 RunUntilIdle();
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());
209 RunUntilIdle();
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);
226 RunUntilIdle();
227 EXPECT_TRUE(waiters[1].called());
229 UnlockDummyEndpoint(1);
232 // UnlockEndpoint() should cause any sockets remembered for this endpoint
233 // to be forgotten.
234 TEST_F(WebSocketEndpointLockManagerTest, SocketAssociationForgottenOnUnlock) {
235 FakeWaiter waiter;
236 FakeStreamSocket dummy_socket;
238 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter));
239 instance()->RememberSocket(&dummy_socket, DummyEndpoint());
240 instance()->UnlockEndpoint(DummyEndpoint());
241 RunUntilIdle();
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());
256 RunUntilIdle();
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);
277 RunUntilIdle();
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());
293 RunUntilIdle();
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);
327 } // namespace
329 } // namespace net