- add sources.
[platform/framework/web/crosswalk.git] / src / net / socket / socks_client_socket_pool_unittest.cc
1 // Copyright (c) 2012 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/socks_client_socket_pool.h"
6
7 #include "base/callback.h"
8 #include "base/compiler_specific.h"
9 #include "base/time/time.h"
10 #include "net/base/load_timing_info.h"
11 #include "net/base/load_timing_info_test_util.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/dns/mock_host_resolver.h"
15 #include "net/socket/client_socket_factory.h"
16 #include "net/socket/client_socket_handle.h"
17 #include "net/socket/client_socket_pool_histograms.h"
18 #include "net/socket/socket_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace net {
22
23 namespace {
24
25 const int kMaxSockets = 32;
26 const int kMaxSocketsPerGroup = 6;
27
28 // Make sure |handle|'s load times are set correctly.  Only connect times should
29 // be set.
30 void TestLoadTimingInfo(const ClientSocketHandle& handle) {
31   LoadTimingInfo load_timing_info;
32   EXPECT_TRUE(handle.GetLoadTimingInfo(false, &load_timing_info));
33
34   // None of these tests use a NetLog.
35   EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
36
37   EXPECT_FALSE(load_timing_info.socket_reused);
38
39   ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
40                               CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
41   ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
42 }
43
44
45 scoped_refptr<TransportSocketParams> CreateProxyHostParams() {
46   return new TransportSocketParams(
47       HostPortPair("proxy", 80), false, false,
48       OnHostResolutionCallback());
49 }
50
51 scoped_refptr<SOCKSSocketParams> CreateSOCKSv4Params() {
52   return new SOCKSSocketParams(
53       CreateProxyHostParams(), false /* socks_v5 */,
54       HostPortPair("host", 80));
55 }
56
57 scoped_refptr<SOCKSSocketParams> CreateSOCKSv5Params() {
58   return new SOCKSSocketParams(
59       CreateProxyHostParams(), true /* socks_v5 */,
60       HostPortPair("host", 80));
61 }
62
63 class SOCKSClientSocketPoolTest : public testing::Test {
64  protected:
65   class SOCKS5MockData {
66    public:
67     explicit SOCKS5MockData(IoMode mode) {
68       writes_.reset(new MockWrite[3]);
69       writes_[0] = MockWrite(mode, kSOCKS5GreetRequest,
70                              kSOCKS5GreetRequestLength);
71       writes_[1] = MockWrite(mode, kSOCKS5OkRequest, kSOCKS5OkRequestLength);
72       writes_[2] = MockWrite(mode, 0);
73
74       reads_.reset(new MockRead[3]);
75       reads_[0] = MockRead(mode, kSOCKS5GreetResponse,
76                            kSOCKS5GreetResponseLength);
77       reads_[1] = MockRead(mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength);
78       reads_[2] = MockRead(mode, 0);
79
80       data_.reset(new StaticSocketDataProvider(reads_.get(), 3,
81                                                writes_.get(), 3));
82     }
83
84     SocketDataProvider* data_provider() { return data_.get(); }
85
86    private:
87     scoped_ptr<StaticSocketDataProvider> data_;
88     scoped_ptr<MockWrite[]> writes_;
89     scoped_ptr<MockRead[]> reads_;
90   };
91
92   SOCKSClientSocketPoolTest()
93       : transport_histograms_("MockTCP"),
94         transport_socket_pool_(
95             kMaxSockets, kMaxSocketsPerGroup,
96             &transport_histograms_,
97             &transport_client_socket_factory_),
98         socks_histograms_("SOCKSUnitTest"),
99         pool_(kMaxSockets, kMaxSocketsPerGroup,
100               &socks_histograms_,
101               &host_resolver_,
102               &transport_socket_pool_,
103               NULL) {
104   }
105
106   virtual ~SOCKSClientSocketPoolTest() {}
107
108   int StartRequestV5(const std::string& group_name, RequestPriority priority) {
109     return test_base_.StartRequestUsingPool(
110         &pool_, group_name, priority, CreateSOCKSv5Params());
111   }
112
113   int GetOrderOfRequest(size_t index) const {
114     return test_base_.GetOrderOfRequest(index);
115   }
116
117   ScopedVector<TestSocketRequest>* requests() { return test_base_.requests(); }
118
119   ClientSocketPoolHistograms transport_histograms_;
120   MockClientSocketFactory transport_client_socket_factory_;
121   MockTransportClientSocketPool transport_socket_pool_;
122
123   ClientSocketPoolHistograms socks_histograms_;
124   MockHostResolver host_resolver_;
125   SOCKSClientSocketPool pool_;
126   ClientSocketPoolTest test_base_;
127 };
128
129 TEST_F(SOCKSClientSocketPoolTest, Simple) {
130   SOCKS5MockData data(SYNCHRONOUS);
131   data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
132   transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
133
134   ClientSocketHandle handle;
135   int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, CompletionCallback(),
136                        &pool_, BoundNetLog());
137   EXPECT_EQ(OK, rv);
138   EXPECT_TRUE(handle.is_initialized());
139   EXPECT_TRUE(handle.socket());
140   TestLoadTimingInfo(handle);
141 }
142
143 // Make sure that SOCKSConnectJob passes on its priority to its
144 // socket request on Init.
145 TEST_F(SOCKSClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
146   for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
147     RequestPriority priority = static_cast<RequestPriority>(i);
148     SOCKS5MockData data(SYNCHRONOUS);
149     data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
150     transport_client_socket_factory_.AddSocketDataProvider(
151         data.data_provider());
152
153     ClientSocketHandle handle;
154     EXPECT_EQ(OK,
155               handle.Init("a", CreateSOCKSv5Params(), priority,
156                           CompletionCallback(), &pool_, BoundNetLog()));
157     EXPECT_EQ(priority, transport_socket_pool_.last_request_priority());
158     handle.socket()->Disconnect();
159   }
160 }
161
162 // Make sure that SOCKSConnectJob passes on its priority to its
163 // HostResolver request (for non-SOCKS5) on Init.
164 TEST_F(SOCKSClientSocketPoolTest, SetResolvePriorityOnInit) {
165   for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
166     RequestPriority priority = static_cast<RequestPriority>(i);
167     SOCKS5MockData data(SYNCHRONOUS);
168     data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
169     transport_client_socket_factory_.AddSocketDataProvider(
170         data.data_provider());
171
172     ClientSocketHandle handle;
173     EXPECT_EQ(ERR_IO_PENDING,
174               handle.Init("a", CreateSOCKSv4Params(), priority,
175                           CompletionCallback(), &pool_, BoundNetLog()));
176     EXPECT_EQ(priority, transport_socket_pool_.last_request_priority());
177     EXPECT_EQ(priority, host_resolver_.last_request_priority());
178     EXPECT_TRUE(handle.socket() == NULL);
179   }
180 }
181
182 TEST_F(SOCKSClientSocketPoolTest, Async) {
183   SOCKS5MockData data(ASYNC);
184   transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
185
186   TestCompletionCallback callback;
187   ClientSocketHandle handle;
188   int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, callback.callback(),
189                        &pool_, BoundNetLog());
190   EXPECT_EQ(ERR_IO_PENDING, rv);
191   EXPECT_FALSE(handle.is_initialized());
192   EXPECT_FALSE(handle.socket());
193
194   EXPECT_EQ(OK, callback.WaitForResult());
195   EXPECT_TRUE(handle.is_initialized());
196   EXPECT_TRUE(handle.socket());
197   TestLoadTimingInfo(handle);
198 }
199
200 TEST_F(SOCKSClientSocketPoolTest, TransportConnectError) {
201   StaticSocketDataProvider socket_data;
202   socket_data.set_connect_data(MockConnect(SYNCHRONOUS,
203                                            ERR_CONNECTION_REFUSED));
204   transport_client_socket_factory_.AddSocketDataProvider(&socket_data);
205
206   ClientSocketHandle handle;
207   int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, CompletionCallback(),
208                        &pool_, BoundNetLog());
209   EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
210   EXPECT_FALSE(handle.is_initialized());
211   EXPECT_FALSE(handle.socket());
212 }
213
214 TEST_F(SOCKSClientSocketPoolTest, AsyncTransportConnectError) {
215   StaticSocketDataProvider socket_data;
216   socket_data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
217   transport_client_socket_factory_.AddSocketDataProvider(&socket_data);
218
219   TestCompletionCallback callback;
220   ClientSocketHandle handle;
221   int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, callback.callback(),
222                        &pool_, BoundNetLog());
223   EXPECT_EQ(ERR_IO_PENDING, rv);
224   EXPECT_FALSE(handle.is_initialized());
225   EXPECT_FALSE(handle.socket());
226
227   EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback.WaitForResult());
228   EXPECT_FALSE(handle.is_initialized());
229   EXPECT_FALSE(handle.socket());
230 }
231
232 TEST_F(SOCKSClientSocketPoolTest, SOCKSConnectError) {
233   MockRead failed_read[] = {
234     MockRead(SYNCHRONOUS, 0),
235   };
236   StaticSocketDataProvider socket_data(
237       failed_read, arraysize(failed_read), NULL, 0);
238   socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
239   transport_client_socket_factory_.AddSocketDataProvider(&socket_data);
240
241   ClientSocketHandle handle;
242   EXPECT_EQ(0, transport_socket_pool_.release_count());
243   int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, CompletionCallback(),
244                        &pool_, BoundNetLog());
245   EXPECT_EQ(ERR_SOCKS_CONNECTION_FAILED, rv);
246   EXPECT_FALSE(handle.is_initialized());
247   EXPECT_FALSE(handle.socket());
248   EXPECT_EQ(1, transport_socket_pool_.release_count());
249 }
250
251 TEST_F(SOCKSClientSocketPoolTest, AsyncSOCKSConnectError) {
252   MockRead failed_read[] = {
253     MockRead(ASYNC, 0),
254   };
255   StaticSocketDataProvider socket_data(
256         failed_read, arraysize(failed_read), NULL, 0);
257   socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
258   transport_client_socket_factory_.AddSocketDataProvider(&socket_data);
259
260   TestCompletionCallback callback;
261   ClientSocketHandle handle;
262   EXPECT_EQ(0, transport_socket_pool_.release_count());
263   int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, callback.callback(),
264                        &pool_, BoundNetLog());
265   EXPECT_EQ(ERR_IO_PENDING, rv);
266   EXPECT_FALSE(handle.is_initialized());
267   EXPECT_FALSE(handle.socket());
268
269   EXPECT_EQ(ERR_SOCKS_CONNECTION_FAILED, callback.WaitForResult());
270   EXPECT_FALSE(handle.is_initialized());
271   EXPECT_FALSE(handle.socket());
272   EXPECT_EQ(1, transport_socket_pool_.release_count());
273 }
274
275 TEST_F(SOCKSClientSocketPoolTest, CancelDuringTransportConnect) {
276   SOCKS5MockData data(SYNCHRONOUS);
277   transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
278   // We need two connections because the pool base lets one cancelled
279   // connect job proceed for potential future use.
280   SOCKS5MockData data2(SYNCHRONOUS);
281   transport_client_socket_factory_.AddSocketDataProvider(data2.data_provider());
282
283   EXPECT_EQ(0, transport_socket_pool_.cancel_count());
284   int rv = StartRequestV5("a", LOW);
285   EXPECT_EQ(ERR_IO_PENDING, rv);
286
287   rv = StartRequestV5("a", LOW);
288   EXPECT_EQ(ERR_IO_PENDING, rv);
289
290   pool_.CancelRequest("a", (*requests())[0]->handle());
291   pool_.CancelRequest("a", (*requests())[1]->handle());
292   // Requests in the connect phase don't actually get cancelled.
293   EXPECT_EQ(0, transport_socket_pool_.cancel_count());
294
295   // Now wait for the TCP sockets to connect.
296   base::MessageLoop::current()->RunUntilIdle();
297
298   EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(1));
299   EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(2));
300   EXPECT_EQ(0, transport_socket_pool_.cancel_count());
301   EXPECT_EQ(2, pool_.IdleSocketCount());
302
303   (*requests())[0]->handle()->Reset();
304   (*requests())[1]->handle()->Reset();
305 }
306
307 TEST_F(SOCKSClientSocketPoolTest, CancelDuringSOCKSConnect) {
308   SOCKS5MockData data(ASYNC);
309   data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
310   transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
311   // We need two connections because the pool base lets one cancelled
312   // connect job proceed for potential future use.
313   SOCKS5MockData data2(ASYNC);
314   data2.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
315   transport_client_socket_factory_.AddSocketDataProvider(data2.data_provider());
316
317   EXPECT_EQ(0, transport_socket_pool_.cancel_count());
318   EXPECT_EQ(0, transport_socket_pool_.release_count());
319   int rv = StartRequestV5("a", LOW);
320   EXPECT_EQ(ERR_IO_PENDING, rv);
321
322   rv = StartRequestV5("a", LOW);
323   EXPECT_EQ(ERR_IO_PENDING, rv);
324
325   pool_.CancelRequest("a", (*requests())[0]->handle());
326   pool_.CancelRequest("a", (*requests())[1]->handle());
327   EXPECT_EQ(0, transport_socket_pool_.cancel_count());
328   // Requests in the connect phase don't actually get cancelled.
329   EXPECT_EQ(0, transport_socket_pool_.release_count());
330
331   // Now wait for the async data to reach the SOCKS connect jobs.
332   base::MessageLoop::current()->RunUntilIdle();
333
334   EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(1));
335   EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(2));
336   EXPECT_EQ(0, transport_socket_pool_.cancel_count());
337   EXPECT_EQ(0, transport_socket_pool_.release_count());
338   EXPECT_EQ(2, pool_.IdleSocketCount());
339
340   (*requests())[0]->handle()->Reset();
341   (*requests())[1]->handle()->Reset();
342 }
343
344 // It would be nice to also test the timeouts in SOCKSClientSocketPool.
345
346 }  // namespace
347
348 }  // namespace net