• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 namespace net {
14 
15 namespace {
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.
20 class FakeStreamSocket : public StreamSocket {
21  public:
FakeStreamSocket()22   FakeStreamSocket() {}
23 
24   // StreamSocket implementation
Connect(const CompletionCallback & callback)25   virtual int Connect(const CompletionCallback& callback) OVERRIDE {
26     return ERR_FAILED;
27   }
28 
Disconnect()29   virtual void Disconnect() OVERRIDE { return; }
30 
IsConnected() const31   virtual bool IsConnected() const OVERRIDE { return false; }
32 
IsConnectedAndIdle() const33   virtual bool IsConnectedAndIdle() const OVERRIDE { return false; }
34 
GetPeerAddress(IPEndPoint * address) const35   virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE {
36     return ERR_FAILED;
37   }
38 
GetLocalAddress(IPEndPoint * address) const39   virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE {
40     return ERR_FAILED;
41   }
42 
NetLog() const43   virtual const BoundNetLog& NetLog() const OVERRIDE { return bound_net_log_; }
44 
SetSubresourceSpeculation()45   virtual void SetSubresourceSpeculation() OVERRIDE { return; }
SetOmniboxSpeculation()46   virtual void SetOmniboxSpeculation() OVERRIDE { return; }
47 
WasEverUsed() const48   virtual bool WasEverUsed() const OVERRIDE { return false; }
49 
UsingTCPFastOpen() const50   virtual bool UsingTCPFastOpen() const OVERRIDE { return false; }
51 
WasNpnNegotiated() const52   virtual bool WasNpnNegotiated() const OVERRIDE { return false; }
53 
GetNegotiatedProtocol() const54   virtual NextProto GetNegotiatedProtocol() const OVERRIDE {
55     return kProtoUnknown;
56   }
57 
GetSSLInfo(SSLInfo * ssl_info)58   virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { return false; }
59 
60   // Socket implementation
Read(IOBuffer * buf,int buf_len,const CompletionCallback & callback)61   virtual int Read(IOBuffer* buf,
62                    int buf_len,
63                    const CompletionCallback& callback) OVERRIDE {
64     return ERR_FAILED;
65   }
66 
Write(IOBuffer * buf,int buf_len,const CompletionCallback & callback)67   virtual int Write(IOBuffer* buf,
68                     int buf_len,
69                     const CompletionCallback& callback) OVERRIDE {
70     return ERR_FAILED;
71   }
72 
SetReceiveBufferSize(int32 size)73   virtual int SetReceiveBufferSize(int32 size) OVERRIDE { return ERR_FAILED; }
74 
SetSendBufferSize(int32 size)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 
83 class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
84  public:
FakeWaiter()85   FakeWaiter() : called_(false) {}
86 
GotEndpointLock()87   virtual void GotEndpointLock() OVERRIDE {
88     CHECK(!called_);
89     called_ = true;
90   }
91 
called() const92   bool called() const { return called_; }
93 
94  private:
95   bool called_;
96 };
97 
98 class WebSocketEndpointLockManagerTest : public ::testing::Test {
99  protected:
WebSocketEndpointLockManagerTest()100   WebSocketEndpointLockManagerTest()
101       : instance_(WebSocketEndpointLockManager::GetInstance()) {}
~WebSocketEndpointLockManagerTest()102   virtual ~WebSocketEndpointLockManagerTest() {
103     // If this check fails then subsequent tests may fail.
104     CHECK(instance_->IsEmpty());
105   }
106 
instance() const107   WebSocketEndpointLockManager* instance() const { return instance_; }
108 
DummyEndpoint()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 
UnlockDummyEndpoint(int times)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 
TEST_F(WebSocketEndpointLockManagerTest,GetInstanceWorks)124 TEST_F(WebSocketEndpointLockManagerTest, GetInstanceWorks) {
125   // All the work is done by the test framework.
126 }
127 
TEST_F(WebSocketEndpointLockManagerTest,LockEndpointReturnsOkOnce)128 TEST_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 
TEST_F(WebSocketEndpointLockManagerTest,GotEndpointLockNotCalledOnOk)137 TEST_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 
TEST_F(WebSocketEndpointLockManagerTest,GotEndpointLockNotCalledImmediately)145 TEST_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 
TEST_F(WebSocketEndpointLockManagerTest,GotEndpointLockCalledWhenUnlocked)155 TEST_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 
TEST_F(WebSocketEndpointLockManagerTest,EndpointUnlockedIfWaiterAlreadyDeleted)166 TEST_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 
TEST_F(WebSocketEndpointLockManagerTest,RememberSocketWorks)185 TEST_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.
TEST_F(WebSocketEndpointLockManagerTest,SocketAssociationForgottenOnUnlock)201 TEST_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.
TEST_F(WebSocketEndpointLockManagerTest,NextWaiterCanCallRememberSocketAgain)213 TEST_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