move SK_DISABLE_DITHER_32BIT_GRADIENT from SkUserConfig.h to skia.gyp, so we can...
[chromium-blink-merge.git] / net / socket / socks_client_socket_unittest.cc
blob2677b5b4f4fa585e833dde045edd3fd2eb926782
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.
5 #include "net/socket/socks_client_socket.h"
7 #include "net/base/address_list.h"
8 #include "net/base/net_log.h"
9 #include "net/base/net_log_unittest.h"
10 #include "net/base/mock_host_resolver.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/base/winsock_init.h"
13 #include "net/socket/client_socket_factory.h"
14 #include "net/socket/tcp_client_socket.h"
15 #include "net/socket/socket_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
19 //-----------------------------------------------------------------------------
21 namespace net {
23 const char kSOCKSOkRequest[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
24 const char kSOCKSOkReply[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
26 class SOCKSClientSocketTest : public PlatformTest {
27 public:
28 SOCKSClientSocketTest();
29 // Create a SOCKSClientSocket on top of a MockSocket.
30 SOCKSClientSocket* BuildMockSocket(MockRead reads[], size_t reads_count,
31 MockWrite writes[], size_t writes_count,
32 HostResolver* host_resolver,
33 const std::string& hostname, int port,
34 NetLog* net_log);
35 virtual void SetUp();
37 protected:
38 scoped_ptr<SOCKSClientSocket> user_sock_;
39 AddressList address_list_;
40 StreamSocket* tcp_sock_;
41 TestCompletionCallback callback_;
42 scoped_ptr<MockHostResolver> host_resolver_;
43 scoped_ptr<SocketDataProvider> data_;
46 SOCKSClientSocketTest::SOCKSClientSocketTest()
47 : host_resolver_(new MockHostResolver) {
50 // Set up platform before every test case
51 void SOCKSClientSocketTest::SetUp() {
52 PlatformTest::SetUp();
55 SOCKSClientSocket* SOCKSClientSocketTest::BuildMockSocket(
56 MockRead reads[],
57 size_t reads_count,
58 MockWrite writes[],
59 size_t writes_count,
60 HostResolver* host_resolver,
61 const std::string& hostname,
62 int port,
63 NetLog* net_log) {
65 TestCompletionCallback callback;
66 data_.reset(new StaticSocketDataProvider(reads, reads_count,
67 writes, writes_count));
68 tcp_sock_ = new MockTCPClientSocket(address_list_, net_log, data_.get());
70 int rv = tcp_sock_->Connect(callback.callback());
71 EXPECT_EQ(ERR_IO_PENDING, rv);
72 rv = callback.WaitForResult();
73 EXPECT_EQ(OK, rv);
74 EXPECT_TRUE(tcp_sock_->IsConnected());
76 return new SOCKSClientSocket(tcp_sock_,
77 HostResolver::RequestInfo(HostPortPair(hostname, port)),
78 host_resolver);
81 // Implementation of HostResolver that never completes its resolve request.
82 // We use this in the test "DisconnectWhileHostResolveInProgress" to make
83 // sure that the outstanding resolve request gets cancelled.
84 class HangingHostResolverWithCancel : public HostResolver {
85 public:
86 HangingHostResolverWithCancel() : outstanding_request_(NULL) {}
88 virtual int Resolve(const RequestInfo& info,
89 AddressList* addresses,
90 const CompletionCallback& callback,
91 RequestHandle* out_req,
92 const BoundNetLog& net_log) OVERRIDE {
93 DCHECK(addresses);
94 DCHECK_EQ(false, callback.is_null());
95 EXPECT_FALSE(HasOutstandingRequest());
96 outstanding_request_ = reinterpret_cast<RequestHandle>(1);
97 *out_req = outstanding_request_;
98 return ERR_IO_PENDING;
101 virtual int ResolveFromCache(const RequestInfo& info,
102 AddressList* addresses,
103 const BoundNetLog& net_log) OVERRIDE {
104 NOTIMPLEMENTED();
105 return ERR_UNEXPECTED;
108 virtual void CancelRequest(RequestHandle req) OVERRIDE {
109 EXPECT_TRUE(HasOutstandingRequest());
110 EXPECT_EQ(outstanding_request_, req);
111 outstanding_request_ = NULL;
114 bool HasOutstandingRequest() {
115 return outstanding_request_ != NULL;
118 private:
119 RequestHandle outstanding_request_;
121 DISALLOW_COPY_AND_ASSIGN(HangingHostResolverWithCancel);
124 // Tests a complete handshake and the disconnection.
125 TEST_F(SOCKSClientSocketTest, CompleteHandshake) {
126 const std::string payload_write = "random data";
127 const std::string payload_read = "moar random data";
129 MockWrite data_writes[] = {
130 MockWrite(ASYNC, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)),
131 MockWrite(ASYNC, payload_write.data(), payload_write.size()) };
132 MockRead data_reads[] = {
133 MockRead(ASYNC, kSOCKSOkReply, arraysize(kSOCKSOkReply)),
134 MockRead(ASYNC, payload_read.data(), payload_read.size()) };
135 CapturingNetLog log;
137 user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
138 data_writes, arraysize(data_writes),
139 host_resolver_.get(),
140 "localhost", 80,
141 &log));
143 // At this state the TCP connection is completed but not the SOCKS handshake.
144 EXPECT_TRUE(tcp_sock_->IsConnected());
145 EXPECT_FALSE(user_sock_->IsConnected());
147 int rv = user_sock_->Connect(callback_.callback());
148 EXPECT_EQ(ERR_IO_PENDING, rv);
150 CapturingNetLog::CapturedEntryList entries;
151 log.GetEntries(&entries);
152 EXPECT_TRUE(
153 LogContainsBeginEvent(entries, 0, NetLog::TYPE_SOCKS_CONNECT));
154 EXPECT_FALSE(user_sock_->IsConnected());
156 rv = callback_.WaitForResult();
157 EXPECT_EQ(OK, rv);
158 EXPECT_TRUE(user_sock_->IsConnected());
159 log.GetEntries(&entries);
160 EXPECT_TRUE(LogContainsEndEvent(
161 entries, -1, NetLog::TYPE_SOCKS_CONNECT));
163 scoped_refptr<IOBuffer> buffer(new IOBuffer(payload_write.size()));
164 memcpy(buffer->data(), payload_write.data(), payload_write.size());
165 rv = user_sock_->Write(buffer, payload_write.size(), callback_.callback());
166 EXPECT_EQ(ERR_IO_PENDING, rv);
167 rv = callback_.WaitForResult();
168 EXPECT_EQ(static_cast<int>(payload_write.size()), rv);
170 buffer = new IOBuffer(payload_read.size());
171 rv = user_sock_->Read(buffer, payload_read.size(), callback_.callback());
172 EXPECT_EQ(ERR_IO_PENDING, rv);
173 rv = callback_.WaitForResult();
174 EXPECT_EQ(static_cast<int>(payload_read.size()), rv);
175 EXPECT_EQ(payload_read, std::string(buffer->data(), payload_read.size()));
177 user_sock_->Disconnect();
178 EXPECT_FALSE(tcp_sock_->IsConnected());
179 EXPECT_FALSE(user_sock_->IsConnected());
182 // List of responses from the socks server and the errors they should
183 // throw up are tested here.
184 TEST_F(SOCKSClientSocketTest, HandshakeFailures) {
185 const struct {
186 const char fail_reply[8];
187 Error fail_code;
188 } tests[] = {
189 // Failure of the server response code
191 { 0x01, 0x5A, 0x00, 0x00, 0, 0, 0, 0 },
192 ERR_SOCKS_CONNECTION_FAILED,
194 // Failure of the null byte
196 { 0x00, 0x5B, 0x00, 0x00, 0, 0, 0, 0 },
197 ERR_SOCKS_CONNECTION_FAILED,
201 //---------------------------------------
203 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
204 MockWrite data_writes[] = {
205 MockWrite(SYNCHRONOUS, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)) };
206 MockRead data_reads[] = {
207 MockRead(SYNCHRONOUS, tests[i].fail_reply,
208 arraysize(tests[i].fail_reply)) };
209 CapturingNetLog log;
211 user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
212 data_writes, arraysize(data_writes),
213 host_resolver_.get(),
214 "localhost", 80,
215 &log));
217 int rv = user_sock_->Connect(callback_.callback());
218 EXPECT_EQ(ERR_IO_PENDING, rv);
220 CapturingNetLog::CapturedEntryList entries;
221 log.GetEntries(&entries);
222 EXPECT_TRUE(LogContainsBeginEvent(
223 entries, 0, NetLog::TYPE_SOCKS_CONNECT));
225 rv = callback_.WaitForResult();
226 EXPECT_EQ(tests[i].fail_code, rv);
227 EXPECT_FALSE(user_sock_->IsConnected());
228 EXPECT_TRUE(tcp_sock_->IsConnected());
229 log.GetEntries(&entries);
230 EXPECT_TRUE(LogContainsEndEvent(
231 entries, -1, NetLog::TYPE_SOCKS_CONNECT));
235 // Tests scenario when the server sends the handshake response in
236 // more than one packet.
237 TEST_F(SOCKSClientSocketTest, PartialServerReads) {
238 const char kSOCKSPartialReply1[] = { 0x00 };
239 const char kSOCKSPartialReply2[] = { 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
241 MockWrite data_writes[] = {
242 MockWrite(ASYNC, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)) };
243 MockRead data_reads[] = {
244 MockRead(ASYNC, kSOCKSPartialReply1, arraysize(kSOCKSPartialReply1)),
245 MockRead(ASYNC, kSOCKSPartialReply2, arraysize(kSOCKSPartialReply2)) };
246 CapturingNetLog log;
248 user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
249 data_writes, arraysize(data_writes),
250 host_resolver_.get(),
251 "localhost", 80,
252 &log));
254 int rv = user_sock_->Connect(callback_.callback());
255 EXPECT_EQ(ERR_IO_PENDING, rv);
256 CapturingNetLog::CapturedEntryList entries;
257 log.GetEntries(&entries);
258 EXPECT_TRUE(LogContainsBeginEvent(
259 entries, 0, NetLog::TYPE_SOCKS_CONNECT));
261 rv = callback_.WaitForResult();
262 EXPECT_EQ(OK, rv);
263 EXPECT_TRUE(user_sock_->IsConnected());
264 log.GetEntries(&entries);
265 EXPECT_TRUE(LogContainsEndEvent(
266 entries, -1, NetLog::TYPE_SOCKS_CONNECT));
269 // Tests scenario when the client sends the handshake request in
270 // more than one packet.
271 TEST_F(SOCKSClientSocketTest, PartialClientWrites) {
272 const char kSOCKSPartialRequest1[] = { 0x04, 0x01 };
273 const char kSOCKSPartialRequest2[] = { 0x00, 0x50, 127, 0, 0, 1, 0 };
275 MockWrite data_writes[] = {
276 MockWrite(ASYNC, arraysize(kSOCKSPartialRequest1)),
277 // simulate some empty writes
278 MockWrite(ASYNC, 0),
279 MockWrite(ASYNC, 0),
280 MockWrite(ASYNC, kSOCKSPartialRequest2,
281 arraysize(kSOCKSPartialRequest2)) };
282 MockRead data_reads[] = {
283 MockRead(ASYNC, kSOCKSOkReply, arraysize(kSOCKSOkReply)) };
284 CapturingNetLog log;
286 user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
287 data_writes, arraysize(data_writes),
288 host_resolver_.get(),
289 "localhost", 80,
290 &log));
292 int rv = user_sock_->Connect(callback_.callback());
293 EXPECT_EQ(ERR_IO_PENDING, rv);
294 CapturingNetLog::CapturedEntryList entries;
295 log.GetEntries(&entries);
296 EXPECT_TRUE(LogContainsBeginEvent(
297 entries, 0, NetLog::TYPE_SOCKS_CONNECT));
299 rv = callback_.WaitForResult();
300 EXPECT_EQ(OK, rv);
301 EXPECT_TRUE(user_sock_->IsConnected());
302 log.GetEntries(&entries);
303 EXPECT_TRUE(LogContainsEndEvent(
304 entries, -1, NetLog::TYPE_SOCKS_CONNECT));
307 // Tests the case when the server sends a smaller sized handshake data
308 // and closes the connection.
309 TEST_F(SOCKSClientSocketTest, FailedSocketRead) {
310 MockWrite data_writes[] = {
311 MockWrite(ASYNC, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)) };
312 MockRead data_reads[] = {
313 MockRead(ASYNC, kSOCKSOkReply, arraysize(kSOCKSOkReply) - 2),
314 // close connection unexpectedly
315 MockRead(SYNCHRONOUS, 0) };
316 CapturingNetLog log;
318 user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
319 data_writes, arraysize(data_writes),
320 host_resolver_.get(),
321 "localhost", 80,
322 &log));
324 int rv = user_sock_->Connect(callback_.callback());
325 EXPECT_EQ(ERR_IO_PENDING, rv);
326 CapturingNetLog::CapturedEntryList entries;
327 log.GetEntries(&entries);
328 EXPECT_TRUE(LogContainsBeginEvent(
329 entries, 0, NetLog::TYPE_SOCKS_CONNECT));
331 rv = callback_.WaitForResult();
332 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
333 EXPECT_FALSE(user_sock_->IsConnected());
334 log.GetEntries(&entries);
335 EXPECT_TRUE(LogContainsEndEvent(
336 entries, -1, NetLog::TYPE_SOCKS_CONNECT));
339 // Tries to connect to an unknown hostname. Should fail rather than
340 // falling back to SOCKS4a.
341 TEST_F(SOCKSClientSocketTest, FailedDNS) {
342 const char hostname[] = "unresolved.ipv4.address";
344 host_resolver_->rules()->AddSimulatedFailure(hostname);
346 CapturingNetLog log;
348 user_sock_.reset(BuildMockSocket(NULL, 0,
349 NULL, 0,
350 host_resolver_.get(),
351 hostname, 80,
352 &log));
354 int rv = user_sock_->Connect(callback_.callback());
355 EXPECT_EQ(ERR_IO_PENDING, rv);
356 CapturingNetLog::CapturedEntryList entries;
357 log.GetEntries(&entries);
358 EXPECT_TRUE(LogContainsBeginEvent(
359 entries, 0, NetLog::TYPE_SOCKS_CONNECT));
361 rv = callback_.WaitForResult();
362 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
363 EXPECT_FALSE(user_sock_->IsConnected());
364 log.GetEntries(&entries);
365 EXPECT_TRUE(LogContainsEndEvent(
366 entries, -1, NetLog::TYPE_SOCKS_CONNECT));
369 // Calls Disconnect() while a host resolve is in progress. The outstanding host
370 // resolve should be cancelled.
371 TEST_F(SOCKSClientSocketTest, DisconnectWhileHostResolveInProgress) {
372 scoped_ptr<HangingHostResolverWithCancel> hanging_resolver(
373 new HangingHostResolverWithCancel());
375 // Doesn't matter what the socket data is, we will never use it -- garbage.
376 MockWrite data_writes[] = { MockWrite(SYNCHRONOUS, "", 0) };
377 MockRead data_reads[] = { MockRead(SYNCHRONOUS, "", 0) };
379 user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
380 data_writes, arraysize(data_writes),
381 hanging_resolver.get(),
382 "foo", 80,
383 NULL));
385 // Start connecting (will get stuck waiting for the host to resolve).
386 int rv = user_sock_->Connect(callback_.callback());
387 EXPECT_EQ(ERR_IO_PENDING, rv);
389 EXPECT_FALSE(user_sock_->IsConnected());
390 EXPECT_FALSE(user_sock_->IsConnectedAndIdle());
392 // The host resolver should have received the resolve request.
393 EXPECT_TRUE(hanging_resolver->HasOutstandingRequest());
395 // Disconnect the SOCKS socket -- this should cancel the outstanding resolve.
396 user_sock_->Disconnect();
398 EXPECT_FALSE(hanging_resolver->HasOutstandingRequest());
400 EXPECT_FALSE(user_sock_->IsConnected());
401 EXPECT_FALSE(user_sock_->IsConnectedAndIdle());
404 } // namespace net