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. 4 5#include "net/socket/websocket_endpoint_lock_manager.h" 6 7#include "net/base/net_errors.h" 8#include "net/socket/next_proto.h" 9#include "net/socket/socket_test_util.h" 10#include "net/socket/stream_socket.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13namespace net { 14 15namespace { 16 17// A StreamSocket implementation with no functionality at all. 18// TODO(ricea): If you need to use this in another file, please move it to 19// socket_test_util.h. 20class FakeStreamSocket : public StreamSocket { 21 public: 22 FakeStreamSocket() {} 23 24 // StreamSocket implementation 25 virtual int Connect(const CompletionCallback& callback) OVERRIDE { 26 return ERR_FAILED; 27 } 28 29 virtual void Disconnect() OVERRIDE { return; } 30 31 virtual bool IsConnected() const OVERRIDE { return false; } 32 33 virtual bool IsConnectedAndIdle() const OVERRIDE { return false; } 34 35 virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE { 36 return ERR_FAILED; 37 } 38 39 virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE { 40 return ERR_FAILED; 41 } 42 43 virtual const BoundNetLog& NetLog() const OVERRIDE { return bound_net_log_; } 44 45 virtual void SetSubresourceSpeculation() OVERRIDE { return; } 46 virtual void SetOmniboxSpeculation() OVERRIDE { return; } 47 48 virtual bool WasEverUsed() const OVERRIDE { return false; } 49 50 virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } 51 52 virtual bool WasNpnNegotiated() const OVERRIDE { return false; } 53 54 virtual NextProto GetNegotiatedProtocol() const OVERRIDE { 55 return kProtoUnknown; 56 } 57 58 virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { return false; } 59 60 // Socket implementation 61 virtual int Read(IOBuffer* buf, 62 int buf_len, 63 const CompletionCallback& callback) OVERRIDE { 64 return ERR_FAILED; 65 } 66 67 virtual int Write(IOBuffer* buf, 68 int buf_len, 69 const CompletionCallback& callback) OVERRIDE { 70 return ERR_FAILED; 71 } 72 73 virtual int SetReceiveBufferSize(int32 size) OVERRIDE { return ERR_FAILED; } 74 75 virtual int SetSendBufferSize(int32 size) OVERRIDE { return ERR_FAILED; } 76 77 private: 78 BoundNetLog bound_net_log_; 79 80 DISALLOW_COPY_AND_ASSIGN(FakeStreamSocket); 81}; 82 83class FakeWaiter : public WebSocketEndpointLockManager::Waiter { 84 public: 85 FakeWaiter() : called_(false) {} 86 87 virtual void GotEndpointLock() OVERRIDE { 88 CHECK(!called_); 89 called_ = true; 90 } 91 92 bool called() const { return called_; } 93 94 private: 95 bool called_; 96}; 97 98class WebSocketEndpointLockManagerTest : public ::testing::Test { 99 protected: 100 WebSocketEndpointLockManagerTest() 101 : instance_(WebSocketEndpointLockManager::GetInstance()) {} 102 virtual ~WebSocketEndpointLockManagerTest() { 103 // If this check fails then subsequent tests may fail. 104 CHECK(instance_->IsEmpty()); 105 } 106 107 WebSocketEndpointLockManager* instance() const { return instance_; } 108 109 IPEndPoint DummyEndpoint() { 110 IPAddressNumber ip_address_number; 111 CHECK(ParseIPLiteralToNumber("127.0.0.1", &ip_address_number)); 112 return IPEndPoint(ip_address_number, 80); 113 } 114 115 void UnlockDummyEndpoint(int times) { 116 for (int i = 0; i < times; ++i) { 117 instance()->UnlockEndpoint(DummyEndpoint()); 118 } 119 } 120 121 WebSocketEndpointLockManager* const instance_; 122}; 123 124TEST_F(WebSocketEndpointLockManagerTest, GetInstanceWorks) { 125 // All the work is done by the test framework. 126} 127 128TEST_F(WebSocketEndpointLockManagerTest, LockEndpointReturnsOkOnce) { 129 FakeWaiter waiters[2]; 130 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); 131 EXPECT_EQ(ERR_IO_PENDING, 132 instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); 133 134 UnlockDummyEndpoint(2); 135} 136 137TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) { 138 FakeWaiter waiter; 139 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter)); 140 EXPECT_FALSE(waiter.called()); 141 142 UnlockDummyEndpoint(1); 143} 144 145TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledImmediately) { 146 FakeWaiter waiters[2]; 147 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); 148 EXPECT_EQ(ERR_IO_PENDING, 149 instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); 150 EXPECT_FALSE(waiters[1].called()); 151 152 UnlockDummyEndpoint(2); 153} 154 155TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockCalledWhenUnlocked) { 156 FakeWaiter waiters[2]; 157 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); 158 EXPECT_EQ(ERR_IO_PENDING, 159 instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); 160 instance()->UnlockEndpoint(DummyEndpoint()); 161 EXPECT_TRUE(waiters[1].called()); 162 163 UnlockDummyEndpoint(1); 164} 165 166TEST_F(WebSocketEndpointLockManagerTest, 167 EndpointUnlockedIfWaiterAlreadyDeleted) { 168 FakeWaiter first_lock_holder; 169 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &first_lock_holder)); 170 171 { 172 FakeWaiter short_lived_waiter; 173 EXPECT_EQ(ERR_IO_PENDING, 174 instance()->LockEndpoint(DummyEndpoint(), &short_lived_waiter)); 175 } 176 177 instance()->UnlockEndpoint(DummyEndpoint()); 178 179 FakeWaiter second_lock_holder; 180 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &second_lock_holder)); 181 182 UnlockDummyEndpoint(1); 183} 184 185TEST_F(WebSocketEndpointLockManagerTest, RememberSocketWorks) { 186 FakeWaiter waiters[2]; 187 FakeStreamSocket dummy_socket; 188 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); 189 EXPECT_EQ(ERR_IO_PENDING, 190 instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); 191 192 instance()->RememberSocket(&dummy_socket, DummyEndpoint()); 193 instance()->UnlockSocket(&dummy_socket); 194 EXPECT_TRUE(waiters[1].called()); 195 196 UnlockDummyEndpoint(1); 197} 198 199// UnlockEndpoint() should cause any sockets remembered for this endpoint 200// to be forgotten. 201TEST_F(WebSocketEndpointLockManagerTest, SocketAssociationForgottenOnUnlock) { 202 FakeWaiter waiter; 203 FakeStreamSocket dummy_socket; 204 205 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter)); 206 instance()->RememberSocket(&dummy_socket, DummyEndpoint()); 207 instance()->UnlockEndpoint(DummyEndpoint()); 208 EXPECT_TRUE(instance()->IsEmpty()); 209} 210 211// When ownership of the endpoint is passed to a new waiter, the new waiter can 212// call RememberSocket() again. 213TEST_F(WebSocketEndpointLockManagerTest, NextWaiterCanCallRememberSocketAgain) { 214 FakeWaiter waiters[2]; 215 FakeStreamSocket dummy_sockets[2]; 216 EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); 217 EXPECT_EQ(ERR_IO_PENDING, 218 instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); 219 220 instance()->RememberSocket(&dummy_sockets[0], DummyEndpoint()); 221 instance()->UnlockEndpoint(DummyEndpoint()); 222 EXPECT_TRUE(waiters[1].called()); 223 instance()->RememberSocket(&dummy_sockets[1], DummyEndpoint()); 224 225 UnlockDummyEndpoint(1); 226} 227 228} // namespace 229 230} // namespace net 231