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_stream/socket_stream.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "net/base/auth.h"
15 #include "net/base/net_log.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/http/http_network_session.h"
20 #include "net/proxy/proxy_service.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/platform_test.h"
30 struct SocketStreamEvent
{
32 EVENT_START_OPEN_CONNECTION
, EVENT_CONNECTED
, EVENT_SENT_DATA
,
33 EVENT_RECEIVED_DATA
, EVENT_CLOSE
, EVENT_AUTH_REQUIRED
, EVENT_ERROR
,
36 SocketStreamEvent(EventType type
,
37 SocketStream
* socket_stream
,
39 const std::string
& str
,
40 AuthChallengeInfo
* auth_challenge_info
,
42 : event_type(type
), socket(socket_stream
), number(num
), data(str
),
43 auth_info(auth_challenge_info
), error_code(error
) {}
49 scoped_refptr
<AuthChallengeInfo
> auth_info
;
53 class SocketStreamEventRecorder
: public SocketStream::Delegate
{
55 // |callback| will be run when the OnClose() or OnError() method is called.
56 // For OnClose(), |callback| is called with OK. For OnError(), it's called
57 // with the error code.
58 explicit SocketStreamEventRecorder(const CompletionCallback
& callback
)
59 : callback_(callback
) {}
60 virtual ~SocketStreamEventRecorder() {}
62 void SetOnStartOpenConnection(
63 const base::Callback
<int(SocketStreamEvent
*)>& callback
) {
64 on_start_open_connection_
= callback
;
67 const base::Callback
<void(SocketStreamEvent
*)>& callback
) {
68 on_connected_
= callback
;
71 const base::Callback
<void(SocketStreamEvent
*)>& callback
) {
72 on_sent_data_
= callback
;
74 void SetOnReceivedData(
75 const base::Callback
<void(SocketStreamEvent
*)>& callback
) {
76 on_received_data_
= callback
;
78 void SetOnClose(const base::Callback
<void(SocketStreamEvent
*)>& callback
) {
81 void SetOnAuthRequired(
82 const base::Callback
<void(SocketStreamEvent
*)>& callback
) {
83 on_auth_required_
= callback
;
85 void SetOnError(const base::Callback
<void(SocketStreamEvent
*)>& callback
) {
89 virtual int OnStartOpenConnection(
91 const CompletionCallback
& callback
) OVERRIDE
{
92 connection_callback_
= callback
;
94 SocketStreamEvent(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
95 socket
, 0, std::string(), NULL
, OK
));
96 if (!on_start_open_connection_
.is_null())
97 return on_start_open_connection_
.Run(&events_
.back());
100 virtual void OnConnected(SocketStream
* socket
,
101 int num_pending_send_allowed
) OVERRIDE
{
103 SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED
,
104 socket
, num_pending_send_allowed
, std::string(),
106 if (!on_connected_
.is_null())
107 on_connected_
.Run(&events_
.back());
109 virtual void OnSentData(SocketStream
* socket
,
110 int amount_sent
) OVERRIDE
{
112 SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA
, socket
,
113 amount_sent
, std::string(), NULL
, OK
));
114 if (!on_sent_data_
.is_null())
115 on_sent_data_
.Run(&events_
.back());
117 virtual void OnReceivedData(SocketStream
* socket
,
118 const char* data
, int len
) OVERRIDE
{
120 SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA
, socket
, len
,
121 std::string(data
, len
), NULL
, OK
));
122 if (!on_received_data_
.is_null())
123 on_received_data_
.Run(&events_
.back());
125 virtual void OnClose(SocketStream
* socket
) OVERRIDE
{
127 SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE
, socket
, 0,
128 std::string(), NULL
, OK
));
129 if (!on_close_
.is_null())
130 on_close_
.Run(&events_
.back());
131 if (!callback_
.is_null())
134 virtual void OnAuthRequired(SocketStream
* socket
,
135 AuthChallengeInfo
* auth_info
) OVERRIDE
{
137 SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED
, socket
, 0,
138 std::string(), auth_info
, OK
));
139 if (!on_auth_required_
.is_null())
140 on_auth_required_
.Run(&events_
.back());
142 virtual void OnError(const SocketStream
* socket
, int error
) OVERRIDE
{
144 SocketStreamEvent(SocketStreamEvent::EVENT_ERROR
, NULL
, 0,
145 std::string(), NULL
, error
));
146 if (!on_error_
.is_null())
147 on_error_
.Run(&events_
.back());
148 if (!callback_
.is_null())
149 callback_
.Run(error
);
152 void DoClose(SocketStreamEvent
* event
) {
153 event
->socket
->Close();
155 void DoRestartWithAuth(SocketStreamEvent
* event
) {
156 VLOG(1) << "RestartWithAuth username=" << credentials_
.username()
157 << " password=" << credentials_
.password();
158 event
->socket
->RestartWithAuth(credentials_
);
160 void SetAuthInfo(const AuthCredentials
& credentials
) {
161 credentials_
= credentials
;
163 void CompleteConnection(int result
) {
164 connection_callback_
.Run(result
);
167 const std::vector
<SocketStreamEvent
>& GetSeenEvents() const {
172 std::vector
<SocketStreamEvent
> events_
;
173 base::Callback
<int(SocketStreamEvent
*)> on_start_open_connection_
;
174 base::Callback
<void(SocketStreamEvent
*)> on_connected_
;
175 base::Callback
<void(SocketStreamEvent
*)> on_sent_data_
;
176 base::Callback
<void(SocketStreamEvent
*)> on_received_data_
;
177 base::Callback
<void(SocketStreamEvent
*)> on_close_
;
178 base::Callback
<void(SocketStreamEvent
*)> on_auth_required_
;
179 base::Callback
<void(SocketStreamEvent
*)> on_error_
;
180 const CompletionCallback callback_
;
181 CompletionCallback connection_callback_
;
182 AuthCredentials credentials_
;
184 DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder
);
187 // This is used for the test OnErrorDetachDelegate.
188 class SelfDeletingDelegate
: public SocketStream::Delegate
{
190 // |callback| must cause the test message loop to exit when called.
191 explicit SelfDeletingDelegate(const CompletionCallback
& callback
)
192 : socket_stream_(), callback_(callback
) {}
194 virtual ~SelfDeletingDelegate() {}
196 // Call DetachDelegate(), delete |this|, then run the callback.
197 virtual void OnError(const SocketStream
* socket
, int error
) OVERRIDE
{
198 // callback_ will be deleted when we delete |this|, so copy it to call it
200 CompletionCallback callback
= callback_
;
201 socket_stream_
->DetachDelegate();
206 // This can't be passed in the constructor because this object needs to be
207 // created before SocketStream.
208 void set_socket_stream(const scoped_refptr
<SocketStream
>& socket_stream
) {
209 socket_stream_
= socket_stream
;
210 EXPECT_EQ(socket_stream_
->delegate(), this);
213 virtual void OnConnected(SocketStream
* socket
, int max_pending_send_allowed
)
215 ADD_FAILURE() << "OnConnected() should not be called";
217 virtual void OnSentData(SocketStream
* socket
, int amount_sent
) OVERRIDE
{
218 ADD_FAILURE() << "OnSentData() should not be called";
220 virtual void OnReceivedData(SocketStream
* socket
, const char* data
, int len
)
222 ADD_FAILURE() << "OnReceivedData() should not be called";
224 virtual void OnClose(SocketStream
* socket
) OVERRIDE
{
225 ADD_FAILURE() << "OnClose() should not be called";
229 scoped_refptr
<SocketStream
> socket_stream_
;
230 const CompletionCallback callback_
;
232 DISALLOW_COPY_AND_ASSIGN(SelfDeletingDelegate
);
235 class TestURLRequestContextWithProxy
: public TestURLRequestContext
{
237 explicit TestURLRequestContextWithProxy(const std::string
& proxy
)
238 : TestURLRequestContext(true) {
239 context_storage_
.set_proxy_service(ProxyService::CreateFixed(proxy
));
242 virtual ~TestURLRequestContextWithProxy() {}
245 class TestSocketStreamNetworkDelegate
: public TestNetworkDelegate
{
247 TestSocketStreamNetworkDelegate()
248 : before_connect_result_(OK
) {}
249 virtual ~TestSocketStreamNetworkDelegate() {}
251 virtual int OnBeforeSocketStreamConnect(
252 SocketStream
* stream
,
253 const CompletionCallback
& callback
) OVERRIDE
{
254 return before_connect_result_
;
257 void SetBeforeConnectResult(int result
) {
258 before_connect_result_
= result
;
262 int before_connect_result_
;
267 class SocketStreamTest
: public PlatformTest
{
269 virtual ~SocketStreamTest() {}
270 virtual void SetUp() {
271 mock_socket_factory_
.reset();
272 handshake_request_
= kWebSocketHandshakeRequest
;
273 handshake_response_
= kWebSocketHandshakeResponse
;
275 virtual void TearDown() {
276 mock_socket_factory_
.reset();
279 virtual void SetWebSocketHandshakeMessage(
280 const char* request
, const char* response
) {
281 handshake_request_
= request
;
282 handshake_response_
= response
;
284 virtual void AddWebSocketMessage(const std::string
& message
) {
285 messages_
.push_back(message
);
288 virtual MockClientSocketFactory
* GetMockClientSocketFactory() {
289 mock_socket_factory_
.reset(new MockClientSocketFactory
);
290 return mock_socket_factory_
.get();
293 virtual void DoSendWebSocketHandshake(SocketStreamEvent
* event
) {
294 event
->socket
->SendData(
295 handshake_request_
.data(), handshake_request_
.size());
298 virtual void DoCloseFlushPendingWriteTest(SocketStreamEvent
* event
) {
299 // handshake response received.
300 for (size_t i
= 0; i
< messages_
.size(); i
++) {
301 std::vector
<char> frame
;
302 frame
.push_back('\0');
303 frame
.insert(frame
.end(), messages_
[i
].begin(), messages_
[i
].end());
304 frame
.push_back('\xff');
305 EXPECT_TRUE(event
->socket
->SendData(&frame
[0], frame
.size()));
307 // Actual StreamSocket close must happen after all frames queued by
308 // SendData above are sent out.
309 event
->socket
->Close();
312 virtual void DoFailByTooBigDataAndClose(SocketStreamEvent
* event
) {
313 std::string
frame(event
->number
+ 1, 0x00);
314 VLOG(1) << event
->number
;
315 EXPECT_FALSE(event
->socket
->SendData(&frame
[0], frame
.size()));
316 event
->socket
->Close();
319 virtual int DoSwitchToSpdyTest(SocketStreamEvent
* event
) {
320 return ERR_PROTOCOL_SWITCHED
;
323 virtual int DoIOPending(SocketStreamEvent
* event
) {
324 io_test_callback_
.callback().Run(OK
);
325 return ERR_IO_PENDING
;
328 static const char kWebSocketHandshakeRequest
[];
329 static const char kWebSocketHandshakeResponse
[];
332 TestCompletionCallback io_test_callback_
;
335 std::string handshake_request_
;
336 std::string handshake_response_
;
337 std::vector
<std::string
> messages_
;
339 scoped_ptr
<MockClientSocketFactory
> mock_socket_factory_
;
342 const char SocketStreamTest::kWebSocketHandshakeRequest
[] =
343 "GET /demo HTTP/1.1\r\n"
344 "Host: example.com\r\n"
345 "Connection: Upgrade\r\n"
346 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
347 "Sec-WebSocket-Protocol: sample\r\n"
348 "Upgrade: WebSocket\r\n"
349 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
350 "Origin: http://example.com\r\n"
354 const char SocketStreamTest::kWebSocketHandshakeResponse
[] =
355 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
356 "Upgrade: WebSocket\r\n"
357 "Connection: Upgrade\r\n"
358 "Sec-WebSocket-Origin: http://example.com\r\n"
359 "Sec-WebSocket-Location: ws://example.com/demo\r\n"
360 "Sec-WebSocket-Protocol: sample\r\n"
364 TEST_F(SocketStreamTest
, CloseFlushPendingWrite
) {
365 TestCompletionCallback test_callback
;
367 scoped_ptr
<SocketStreamEventRecorder
> delegate(
368 new SocketStreamEventRecorder(test_callback
.callback()));
369 delegate
->SetOnConnected(base::Bind(
370 &SocketStreamTest::DoSendWebSocketHandshake
, base::Unretained(this)));
371 delegate
->SetOnReceivedData(base::Bind(
372 &SocketStreamTest::DoCloseFlushPendingWriteTest
,
373 base::Unretained(this)));
375 TestURLRequestContext context
;
377 scoped_refptr
<SocketStream
> socket_stream(
378 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
380 socket_stream
->set_context(&context
);
382 MockWrite data_writes
[] = {
383 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest
),
384 MockWrite(ASYNC
, "\0message1\xff", 10),
385 MockWrite(ASYNC
, "\0message2\xff", 10)
387 MockRead data_reads
[] = {
388 MockRead(SocketStreamTest::kWebSocketHandshakeResponse
),
389 // Server doesn't close the connection after handshake.
390 MockRead(ASYNC
, ERR_IO_PENDING
)
392 AddWebSocketMessage("message1");
393 AddWebSocketMessage("message2");
395 DelayedSocketData
data_provider(
396 1, data_reads
, arraysize(data_reads
),
397 data_writes
, arraysize(data_writes
));
399 MockClientSocketFactory
* mock_socket_factory
=
400 GetMockClientSocketFactory();
401 mock_socket_factory
->AddSocketDataProvider(&data_provider
);
403 socket_stream
->SetClientSocketFactory(mock_socket_factory
);
405 socket_stream
->Connect();
407 test_callback
.WaitForResult();
409 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
410 ASSERT_EQ(7U, events
.size());
412 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
413 events
[0].event_type
);
414 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[1].event_type
);
415 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA
, events
[2].event_type
);
416 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA
, events
[3].event_type
);
417 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA
, events
[4].event_type
);
418 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA
, events
[5].event_type
);
419 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[6].event_type
);
422 TEST_F(SocketStreamTest
, ResolveFailure
) {
423 TestCompletionCallback test_callback
;
425 scoped_ptr
<SocketStreamEventRecorder
> delegate(
426 new SocketStreamEventRecorder(test_callback
.callback()));
428 scoped_refptr
<SocketStream
> socket_stream(
429 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
431 // Make resolver fail.
432 TestURLRequestContext context
;
433 scoped_ptr
<MockHostResolver
> mock_host_resolver(
434 new MockHostResolver());
435 mock_host_resolver
->rules()->AddSimulatedFailure("example.com");
436 context
.set_host_resolver(mock_host_resolver
.get());
437 socket_stream
->set_context(&context
);
439 // No read/write on socket is expected.
440 StaticSocketDataProvider
data_provider(NULL
, 0, NULL
, 0);
441 MockClientSocketFactory
* mock_socket_factory
=
442 GetMockClientSocketFactory();
443 mock_socket_factory
->AddSocketDataProvider(&data_provider
);
444 socket_stream
->SetClientSocketFactory(mock_socket_factory
);
446 socket_stream
->Connect();
448 test_callback
.WaitForResult();
450 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
451 ASSERT_EQ(2U, events
.size());
453 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[0].event_type
);
454 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[1].event_type
);
457 TEST_F(SocketStreamTest
, ExceedMaxPendingSendAllowed
) {
458 TestCompletionCallback test_callback
;
460 scoped_ptr
<SocketStreamEventRecorder
> delegate(
461 new SocketStreamEventRecorder(test_callback
.callback()));
462 delegate
->SetOnConnected(base::Bind(
463 &SocketStreamTest::DoFailByTooBigDataAndClose
, base::Unretained(this)));
465 TestURLRequestContext context
;
467 scoped_refptr
<SocketStream
> socket_stream(
468 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
470 socket_stream
->set_context(&context
);
472 DelayedSocketData
data_provider(1, NULL
, 0, NULL
, 0);
474 MockClientSocketFactory
* mock_socket_factory
=
475 GetMockClientSocketFactory();
476 mock_socket_factory
->AddSocketDataProvider(&data_provider
);
478 socket_stream
->SetClientSocketFactory(mock_socket_factory
);
480 socket_stream
->Connect();
482 test_callback
.WaitForResult();
484 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
485 ASSERT_EQ(4U, events
.size());
487 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
488 events
[0].event_type
);
489 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[1].event_type
);
490 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[2].event_type
);
491 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[3].event_type
);
494 TEST_F(SocketStreamTest
, BasicAuthProxy
) {
495 MockClientSocketFactory mock_socket_factory
;
496 MockWrite data_writes1
[] = {
497 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
498 "Host: example.com\r\n"
499 "Proxy-Connection: keep-alive\r\n\r\n"),
501 MockRead data_reads1
[] = {
502 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
503 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
506 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
507 data_writes1
, arraysize(data_writes1
));
508 mock_socket_factory
.AddSocketDataProvider(&data1
);
510 MockWrite data_writes2
[] = {
511 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
512 "Host: example.com\r\n"
513 "Proxy-Connection: keep-alive\r\n"
514 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
516 MockRead data_reads2
[] = {
517 MockRead("HTTP/1.1 200 Connection Established\r\n"),
518 MockRead("Proxy-agent: Apache/2.2.8\r\n"),
520 // SocketStream::DoClose is run asynchronously. Socket can be read after
521 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate
522 // server doesn't close the connection.
523 MockRead(ASYNC
, ERR_IO_PENDING
)
525 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
526 data_writes2
, arraysize(data_writes2
));
527 mock_socket_factory
.AddSocketDataProvider(&data2
);
529 TestCompletionCallback test_callback
;
531 scoped_ptr
<SocketStreamEventRecorder
> delegate(
532 new SocketStreamEventRecorder(test_callback
.callback()));
533 delegate
->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose
,
534 base::Unretained(delegate
.get())));
535 delegate
->SetAuthInfo(AuthCredentials(ASCIIToUTF16("foo"),
536 ASCIIToUTF16("bar")));
537 delegate
->SetOnAuthRequired(base::Bind(
538 &SocketStreamEventRecorder::DoRestartWithAuth
,
539 base::Unretained(delegate
.get())));
541 scoped_refptr
<SocketStream
> socket_stream(
542 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
544 TestURLRequestContextWithProxy
context("myproxy:70");
546 socket_stream
->set_context(&context
);
547 socket_stream
->SetClientSocketFactory(&mock_socket_factory
);
549 socket_stream
->Connect();
551 test_callback
.WaitForResult();
553 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
554 ASSERT_EQ(5U, events
.size());
556 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
557 events
[0].event_type
);
558 EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED
, events
[1].event_type
);
559 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[2].event_type
);
560 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[3].event_type
);
561 EXPECT_EQ(ERR_ABORTED
, events
[3].error_code
);
562 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[4].event_type
);
564 // TODO(eroman): Add back NetLogTest here...
567 TEST_F(SocketStreamTest
, BasicAuthProxyWithAuthCache
) {
568 MockClientSocketFactory mock_socket_factory
;
569 MockWrite data_writes
[] = {
570 // WebSocket(SocketStream) always uses CONNECT when it is configured to use
571 // proxy so the port may not be 443.
572 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
573 "Host: example.com\r\n"
574 "Proxy-Connection: keep-alive\r\n"
575 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
577 MockRead data_reads
[] = {
578 MockRead("HTTP/1.1 200 Connection Established\r\n"),
579 MockRead("Proxy-agent: Apache/2.2.8\r\n"),
581 MockRead(ASYNC
, ERR_IO_PENDING
)
583 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
584 data_writes
, arraysize(data_writes
));
585 mock_socket_factory
.AddSocketDataProvider(&data
);
587 TestCompletionCallback test_callback
;
588 scoped_ptr
<SocketStreamEventRecorder
> delegate(
589 new SocketStreamEventRecorder(test_callback
.callback()));
590 delegate
->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose
,
591 base::Unretained(delegate
.get())));
593 scoped_refptr
<SocketStream
> socket_stream(
594 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
596 TestURLRequestContextWithProxy
context("myproxy:70");
597 HttpAuthCache
* auth_cache
=
598 context
.http_transaction_factory()->GetSession()->http_auth_cache();
599 auth_cache
->Add(GURL("http://myproxy:70"),
601 HttpAuth::AUTH_SCHEME_BASIC
,
602 "Basic realm=MyRealm1",
603 AuthCredentials(ASCIIToUTF16("foo"),
604 ASCIIToUTF16("bar")),
607 socket_stream
->set_context(&context
);
608 socket_stream
->SetClientSocketFactory(&mock_socket_factory
);
610 socket_stream
->Connect();
612 test_callback
.WaitForResult();
614 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
615 ASSERT_EQ(4U, events
.size());
616 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
617 events
[0].event_type
);
618 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[1].event_type
);
619 EXPECT_EQ(ERR_ABORTED
, events
[2].error_code
);
620 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[3].event_type
);
623 TEST_F(SocketStreamTest
, WSSBasicAuthProxyWithAuthCache
) {
624 MockClientSocketFactory mock_socket_factory
;
625 MockWrite data_writes1
[] = {
626 MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
627 "Host: example.com\r\n"
628 "Proxy-Connection: keep-alive\r\n"
629 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
631 MockRead data_reads1
[] = {
632 MockRead("HTTP/1.1 200 Connection Established\r\n"),
633 MockRead("Proxy-agent: Apache/2.2.8\r\n"),
635 MockRead(ASYNC
, ERR_IO_PENDING
)
637 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
638 data_writes1
, arraysize(data_writes1
));
639 mock_socket_factory
.AddSocketDataProvider(&data1
);
641 SSLSocketDataProvider
data2(ASYNC
, OK
);
642 mock_socket_factory
.AddSSLSocketDataProvider(&data2
);
644 TestCompletionCallback test_callback
;
645 scoped_ptr
<SocketStreamEventRecorder
> delegate(
646 new SocketStreamEventRecorder(test_callback
.callback()));
647 delegate
->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose
,
648 base::Unretained(delegate
.get())));
650 scoped_refptr
<SocketStream
> socket_stream(
651 new SocketStream(GURL("wss://example.com/demo"), delegate
.get()));
653 TestURLRequestContextWithProxy
context("myproxy:70");
654 HttpAuthCache
* auth_cache
=
655 context
.http_transaction_factory()->GetSession()->http_auth_cache();
656 auth_cache
->Add(GURL("http://myproxy:70"),
658 HttpAuth::AUTH_SCHEME_BASIC
,
659 "Basic realm=MyRealm1",
660 AuthCredentials(ASCIIToUTF16("foo"),
661 ASCIIToUTF16("bar")),
664 socket_stream
->set_context(&context
);
665 socket_stream
->SetClientSocketFactory(&mock_socket_factory
);
667 socket_stream
->Connect();
669 test_callback
.WaitForResult();
671 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
672 ASSERT_EQ(4U, events
.size());
673 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
674 events
[0].event_type
);
675 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[1].event_type
);
676 EXPECT_EQ(ERR_ABORTED
, events
[2].error_code
);
677 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[3].event_type
);
680 TEST_F(SocketStreamTest
, IOPending
) {
681 TestCompletionCallback test_callback
;
683 scoped_ptr
<SocketStreamEventRecorder
> delegate(
684 new SocketStreamEventRecorder(test_callback
.callback()));
685 delegate
->SetOnConnected(base::Bind(
686 &SocketStreamTest::DoSendWebSocketHandshake
, base::Unretained(this)));
687 delegate
->SetOnReceivedData(base::Bind(
688 &SocketStreamTest::DoCloseFlushPendingWriteTest
,
689 base::Unretained(this)));
690 delegate
->SetOnStartOpenConnection(base::Bind(
691 &SocketStreamTest::DoIOPending
, base::Unretained(this)));
693 TestURLRequestContext context
;
695 scoped_refptr
<SocketStream
> socket_stream(
696 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
698 socket_stream
->set_context(&context
);
700 MockWrite data_writes
[] = {
701 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest
),
702 MockWrite(ASYNC
, "\0message1\xff", 10),
703 MockWrite(ASYNC
, "\0message2\xff", 10)
705 MockRead data_reads
[] = {
706 MockRead(SocketStreamTest::kWebSocketHandshakeResponse
),
707 // Server doesn't close the connection after handshake.
708 MockRead(ASYNC
, ERR_IO_PENDING
)
710 AddWebSocketMessage("message1");
711 AddWebSocketMessage("message2");
713 DelayedSocketData
data_provider(
714 1, data_reads
, arraysize(data_reads
),
715 data_writes
, arraysize(data_writes
));
717 MockClientSocketFactory
* mock_socket_factory
=
718 GetMockClientSocketFactory();
719 mock_socket_factory
->AddSocketDataProvider(&data_provider
);
721 socket_stream
->SetClientSocketFactory(mock_socket_factory
);
723 socket_stream
->Connect();
724 io_test_callback_
.WaitForResult();
725 EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE
,
726 socket_stream
->next_state_
);
727 delegate
->CompleteConnection(OK
);
729 EXPECT_EQ(OK
, test_callback
.WaitForResult());
731 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
732 ASSERT_EQ(7U, events
.size());
734 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
735 events
[0].event_type
);
736 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[1].event_type
);
737 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA
, events
[2].event_type
);
738 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA
, events
[3].event_type
);
739 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA
, events
[4].event_type
);
740 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA
, events
[5].event_type
);
741 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[6].event_type
);
744 TEST_F(SocketStreamTest
, SwitchToSpdy
) {
745 TestCompletionCallback test_callback
;
747 scoped_ptr
<SocketStreamEventRecorder
> delegate(
748 new SocketStreamEventRecorder(test_callback
.callback()));
749 delegate
->SetOnStartOpenConnection(base::Bind(
750 &SocketStreamTest::DoSwitchToSpdyTest
, base::Unretained(this)));
752 TestURLRequestContext context
;
754 scoped_refptr
<SocketStream
> socket_stream(
755 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
757 socket_stream
->set_context(&context
);
759 socket_stream
->Connect();
761 EXPECT_EQ(ERR_PROTOCOL_SWITCHED
, test_callback
.WaitForResult());
763 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
764 ASSERT_EQ(2U, events
.size());
766 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
767 events
[0].event_type
);
768 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[1].event_type
);
769 EXPECT_EQ(ERR_PROTOCOL_SWITCHED
, events
[1].error_code
);
772 TEST_F(SocketStreamTest
, SwitchAfterPending
) {
773 TestCompletionCallback test_callback
;
775 scoped_ptr
<SocketStreamEventRecorder
> delegate(
776 new SocketStreamEventRecorder(test_callback
.callback()));
777 delegate
->SetOnStartOpenConnection(base::Bind(
778 &SocketStreamTest::DoIOPending
, base::Unretained(this)));
780 TestURLRequestContext context
;
782 scoped_refptr
<SocketStream
> socket_stream(
783 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
785 socket_stream
->set_context(&context
);
787 socket_stream
->Connect();
788 io_test_callback_
.WaitForResult();
789 EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE
,
790 socket_stream
->next_state_
);
791 delegate
->CompleteConnection(ERR_PROTOCOL_SWITCHED
);
793 EXPECT_EQ(ERR_PROTOCOL_SWITCHED
, test_callback
.WaitForResult());
795 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
796 ASSERT_EQ(2U, events
.size());
798 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
799 events
[0].event_type
);
800 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[1].event_type
);
801 EXPECT_EQ(ERR_PROTOCOL_SWITCHED
, events
[1].error_code
);
804 // Test a connection though a secure proxy.
805 TEST_F(SocketStreamTest
, SecureProxyConnectError
) {
806 MockClientSocketFactory mock_socket_factory
;
807 MockWrite data_writes
[] = {
808 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
809 "Host: example.com\r\n"
810 "Proxy-Connection: keep-alive\r\n\r\n")
812 MockRead data_reads
[] = {
813 MockRead("HTTP/1.1 200 Connection Established\r\n"),
814 MockRead("Proxy-agent: Apache/2.2.8\r\n"),
816 // SocketStream::DoClose is run asynchronously. Socket can be read after
817 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate
818 // server doesn't close the connection.
819 MockRead(ASYNC
, ERR_IO_PENDING
)
821 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
822 data_writes
, arraysize(data_writes
));
823 mock_socket_factory
.AddSocketDataProvider(&data
);
824 SSLSocketDataProvider
ssl(SYNCHRONOUS
, ERR_SSL_PROTOCOL_ERROR
);
825 mock_socket_factory
.AddSSLSocketDataProvider(&ssl
);
827 TestCompletionCallback test_callback
;
828 TestURLRequestContextWithProxy
context("https://myproxy:70");
830 scoped_ptr
<SocketStreamEventRecorder
> delegate(
831 new SocketStreamEventRecorder(test_callback
.callback()));
832 delegate
->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose
,
833 base::Unretained(delegate
.get())));
835 scoped_refptr
<SocketStream
> socket_stream(
836 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
838 socket_stream
->set_context(&context
);
839 socket_stream
->SetClientSocketFactory(&mock_socket_factory
);
841 socket_stream
->Connect();
843 test_callback
.WaitForResult();
845 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
846 ASSERT_EQ(3U, events
.size());
848 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
849 events
[0].event_type
);
850 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[1].event_type
);
851 EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR
, events
[1].error_code
);
852 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[2].event_type
);
855 // Test a connection though a secure proxy.
856 TEST_F(SocketStreamTest
, SecureProxyConnect
) {
857 MockClientSocketFactory mock_socket_factory
;
858 MockWrite data_writes
[] = {
859 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
860 "Host: example.com\r\n"
861 "Proxy-Connection: keep-alive\r\n\r\n")
863 MockRead data_reads
[] = {
864 MockRead("HTTP/1.1 200 Connection Established\r\n"),
865 MockRead("Proxy-agent: Apache/2.2.8\r\n"),
867 // SocketStream::DoClose is run asynchronously. Socket can be read after
868 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate
869 // server doesn't close the connection.
870 MockRead(ASYNC
, ERR_IO_PENDING
)
872 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
873 data_writes
, arraysize(data_writes
));
874 mock_socket_factory
.AddSocketDataProvider(&data
);
875 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
876 mock_socket_factory
.AddSSLSocketDataProvider(&ssl
);
878 TestCompletionCallback test_callback
;
879 TestURLRequestContextWithProxy
context("https://myproxy:70");
881 scoped_ptr
<SocketStreamEventRecorder
> delegate(
882 new SocketStreamEventRecorder(test_callback
.callback()));
883 delegate
->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose
,
884 base::Unretained(delegate
.get())));
886 scoped_refptr
<SocketStream
> socket_stream(
887 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
889 socket_stream
->set_context(&context
);
890 socket_stream
->SetClientSocketFactory(&mock_socket_factory
);
892 socket_stream
->Connect();
894 test_callback
.WaitForResult();
896 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
897 ASSERT_EQ(4U, events
.size());
899 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION
,
900 events
[0].event_type
);
901 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED
, events
[1].event_type
);
902 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[2].event_type
);
903 EXPECT_EQ(ERR_ABORTED
, events
[2].error_code
);
904 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[3].event_type
);
907 TEST_F(SocketStreamTest
, BeforeConnectFailed
) {
908 TestCompletionCallback test_callback
;
910 scoped_ptr
<SocketStreamEventRecorder
> delegate(
911 new SocketStreamEventRecorder(test_callback
.callback()));
913 TestURLRequestContext context
;
914 TestSocketStreamNetworkDelegate network_delegate
;
915 network_delegate
.SetBeforeConnectResult(ERR_ACCESS_DENIED
);
916 context
.set_network_delegate(&network_delegate
);
918 scoped_refptr
<SocketStream
> socket_stream(
919 new SocketStream(GURL("ws://example.com/demo"), delegate
.get()));
921 socket_stream
->set_context(&context
);
923 socket_stream
->Connect();
925 test_callback
.WaitForResult();
927 const std::vector
<SocketStreamEvent
>& events
= delegate
->GetSeenEvents();
928 ASSERT_EQ(2U, events
.size());
930 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR
, events
[0].event_type
);
931 EXPECT_EQ(ERR_ACCESS_DENIED
, events
[0].error_code
);
932 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE
, events
[1].event_type
);
935 // Check that a connect failure, followed by the delegate calling DetachDelegate
936 // and deleting itself in the OnError callback, is handled correctly.
937 TEST_F(SocketStreamTest
, OnErrorDetachDelegate
) {
938 MockClientSocketFactory mock_socket_factory
;
939 TestCompletionCallback test_callback
;
941 // SelfDeletingDelegate is self-owning; we just need a pointer to it to
942 // connect it and the SocketStream.
943 SelfDeletingDelegate
* delegate
=
944 new SelfDeletingDelegate(test_callback
.callback());
945 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
946 StaticSocketDataProvider data
;
947 data
.set_connect_data(mock_connect
);
948 mock_socket_factory
.AddSocketDataProvider(&data
);
950 TestURLRequestContext context
;
951 scoped_refptr
<SocketStream
> socket_stream(
952 new SocketStream(GURL("ws://localhost:9998/echo"), delegate
));
953 socket_stream
->set_context(&context
);
954 socket_stream
->SetClientSocketFactory(&mock_socket_factory
);
955 delegate
->set_socket_stream(socket_stream
);
956 // The delegate pointer will become invalid during the test. Set it to NULL to
957 // avoid holding a dangling pointer.
960 socket_stream
->Connect();
962 EXPECT_EQ(OK
, test_callback
.WaitForResult());