| OLD | NEW |
| (Empty) |
| 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_stream/socket_stream.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 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" | |
| 25 | |
| 26 using base::ASCIIToUTF16; | |
| 27 | |
| 28 namespace net { | |
| 29 | |
| 30 namespace { | |
| 31 | |
| 32 struct SocketStreamEvent { | |
| 33 enum EventType { | |
| 34 EVENT_START_OPEN_CONNECTION, EVENT_CONNECTED, EVENT_SENT_DATA, | |
| 35 EVENT_RECEIVED_DATA, EVENT_CLOSE, EVENT_AUTH_REQUIRED, EVENT_ERROR, | |
| 36 }; | |
| 37 | |
| 38 SocketStreamEvent(EventType type, | |
| 39 SocketStream* socket_stream, | |
| 40 int num, | |
| 41 const std::string& str, | |
| 42 AuthChallengeInfo* auth_challenge_info, | |
| 43 int error) | |
| 44 : event_type(type), socket(socket_stream), number(num), data(str), | |
| 45 auth_info(auth_challenge_info), error_code(error) {} | |
| 46 | |
| 47 EventType event_type; | |
| 48 SocketStream* socket; | |
| 49 int number; | |
| 50 std::string data; | |
| 51 scoped_refptr<AuthChallengeInfo> auth_info; | |
| 52 int error_code; | |
| 53 }; | |
| 54 | |
| 55 class SocketStreamEventRecorder : public SocketStream::Delegate { | |
| 56 public: | |
| 57 // |callback| will be run when the OnClose() or OnError() method is called. | |
| 58 // For OnClose(), |callback| is called with OK. For OnError(), it's called | |
| 59 // with the error code. | |
| 60 explicit SocketStreamEventRecorder(const CompletionCallback& callback) | |
| 61 : callback_(callback) {} | |
| 62 ~SocketStreamEventRecorder() override {} | |
| 63 | |
| 64 void SetOnStartOpenConnection( | |
| 65 const base::Callback<int(SocketStreamEvent*)>& callback) { | |
| 66 on_start_open_connection_ = callback; | |
| 67 } | |
| 68 void SetOnConnected( | |
| 69 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
| 70 on_connected_ = callback; | |
| 71 } | |
| 72 void SetOnSentData( | |
| 73 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
| 74 on_sent_data_ = callback; | |
| 75 } | |
| 76 void SetOnReceivedData( | |
| 77 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
| 78 on_received_data_ = callback; | |
| 79 } | |
| 80 void SetOnClose(const base::Callback<void(SocketStreamEvent*)>& callback) { | |
| 81 on_close_ = callback; | |
| 82 } | |
| 83 void SetOnAuthRequired( | |
| 84 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
| 85 on_auth_required_ = callback; | |
| 86 } | |
| 87 void SetOnError(const base::Callback<void(SocketStreamEvent*)>& callback) { | |
| 88 on_error_ = callback; | |
| 89 } | |
| 90 | |
| 91 int OnStartOpenConnection(SocketStream* socket, | |
| 92 const CompletionCallback& callback) override { | |
| 93 connection_callback_ = callback; | |
| 94 events_.push_back( | |
| 95 SocketStreamEvent(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 96 socket, 0, std::string(), NULL, OK)); | |
| 97 if (!on_start_open_connection_.is_null()) | |
| 98 return on_start_open_connection_.Run(&events_.back()); | |
| 99 return OK; | |
| 100 } | |
| 101 void OnConnected(SocketStream* socket, | |
| 102 int num_pending_send_allowed) override { | |
| 103 events_.push_back( | |
| 104 SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED, | |
| 105 socket, num_pending_send_allowed, std::string(), | |
| 106 NULL, OK)); | |
| 107 if (!on_connected_.is_null()) | |
| 108 on_connected_.Run(&events_.back()); | |
| 109 } | |
| 110 void OnSentData(SocketStream* socket, int amount_sent) override { | |
| 111 events_.push_back( | |
| 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()); | |
| 116 } | |
| 117 void OnReceivedData(SocketStream* socket, | |
| 118 const char* data, | |
| 119 int len) override { | |
| 120 events_.push_back( | |
| 121 SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA, socket, len, | |
| 122 std::string(data, len), NULL, OK)); | |
| 123 if (!on_received_data_.is_null()) | |
| 124 on_received_data_.Run(&events_.back()); | |
| 125 } | |
| 126 void OnClose(SocketStream* socket) override { | |
| 127 events_.push_back( | |
| 128 SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE, socket, 0, | |
| 129 std::string(), NULL, OK)); | |
| 130 if (!on_close_.is_null()) | |
| 131 on_close_.Run(&events_.back()); | |
| 132 if (!callback_.is_null()) | |
| 133 callback_.Run(OK); | |
| 134 } | |
| 135 void OnAuthRequired(SocketStream* socket, | |
| 136 AuthChallengeInfo* auth_info) override { | |
| 137 events_.push_back( | |
| 138 SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED, socket, 0, | |
| 139 std::string(), auth_info, OK)); | |
| 140 if (!on_auth_required_.is_null()) | |
| 141 on_auth_required_.Run(&events_.back()); | |
| 142 } | |
| 143 void OnError(const SocketStream* socket, int error) override { | |
| 144 events_.push_back( | |
| 145 SocketStreamEvent(SocketStreamEvent::EVENT_ERROR, NULL, 0, | |
| 146 std::string(), NULL, error)); | |
| 147 if (!on_error_.is_null()) | |
| 148 on_error_.Run(&events_.back()); | |
| 149 if (!callback_.is_null()) | |
| 150 callback_.Run(error); | |
| 151 } | |
| 152 | |
| 153 void DoClose(SocketStreamEvent* event) { | |
| 154 event->socket->Close(); | |
| 155 } | |
| 156 void DoRestartWithAuth(SocketStreamEvent* event) { | |
| 157 VLOG(1) << "RestartWithAuth username=" << credentials_.username() | |
| 158 << " password=" << credentials_.password(); | |
| 159 event->socket->RestartWithAuth(credentials_); | |
| 160 } | |
| 161 void SetAuthInfo(const AuthCredentials& credentials) { | |
| 162 credentials_ = credentials; | |
| 163 } | |
| 164 // Wakes up the SocketStream waiting for completion of OnStartOpenConnection() | |
| 165 // of its delegate. | |
| 166 void CompleteConnection(int result) { | |
| 167 connection_callback_.Run(result); | |
| 168 } | |
| 169 | |
| 170 const std::vector<SocketStreamEvent>& GetSeenEvents() const { | |
| 171 return events_; | |
| 172 } | |
| 173 | |
| 174 private: | |
| 175 std::vector<SocketStreamEvent> events_; | |
| 176 base::Callback<int(SocketStreamEvent*)> on_start_open_connection_; | |
| 177 base::Callback<void(SocketStreamEvent*)> on_connected_; | |
| 178 base::Callback<void(SocketStreamEvent*)> on_sent_data_; | |
| 179 base::Callback<void(SocketStreamEvent*)> on_received_data_; | |
| 180 base::Callback<void(SocketStreamEvent*)> on_close_; | |
| 181 base::Callback<void(SocketStreamEvent*)> on_auth_required_; | |
| 182 base::Callback<void(SocketStreamEvent*)> on_error_; | |
| 183 const CompletionCallback callback_; | |
| 184 CompletionCallback connection_callback_; | |
| 185 AuthCredentials credentials_; | |
| 186 | |
| 187 DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder); | |
| 188 }; | |
| 189 | |
| 190 // This is used for the test OnErrorDetachDelegate. | |
| 191 class SelfDeletingDelegate : public SocketStream::Delegate { | |
| 192 public: | |
| 193 // |callback| must cause the test message loop to exit when called. | |
| 194 explicit SelfDeletingDelegate(const CompletionCallback& callback) | |
| 195 : socket_stream_(), callback_(callback) {} | |
| 196 | |
| 197 ~SelfDeletingDelegate() override {} | |
| 198 | |
| 199 // Call DetachDelegate(), delete |this|, then run the callback. | |
| 200 void OnError(const SocketStream* socket, int error) override { | |
| 201 // callback_ will be deleted when we delete |this|, so copy it to call it | |
| 202 // afterwards. | |
| 203 CompletionCallback callback = callback_; | |
| 204 socket_stream_->DetachDelegate(); | |
| 205 delete this; | |
| 206 callback.Run(OK); | |
| 207 } | |
| 208 | |
| 209 // This can't be passed in the constructor because this object needs to be | |
| 210 // created before SocketStream. | |
| 211 void set_socket_stream(const scoped_refptr<SocketStream>& socket_stream) { | |
| 212 socket_stream_ = socket_stream; | |
| 213 EXPECT_EQ(socket_stream_->delegate(), this); | |
| 214 } | |
| 215 | |
| 216 void OnConnected(SocketStream* socket, | |
| 217 int max_pending_send_allowed) override { | |
| 218 ADD_FAILURE() << "OnConnected() should not be called"; | |
| 219 } | |
| 220 void OnSentData(SocketStream* socket, int amount_sent) override { | |
| 221 ADD_FAILURE() << "OnSentData() should not be called"; | |
| 222 } | |
| 223 void OnReceivedData(SocketStream* socket, | |
| 224 const char* data, | |
| 225 int len) override { | |
| 226 ADD_FAILURE() << "OnReceivedData() should not be called"; | |
| 227 } | |
| 228 void OnClose(SocketStream* socket) override { | |
| 229 ADD_FAILURE() << "OnClose() should not be called"; | |
| 230 } | |
| 231 | |
| 232 private: | |
| 233 scoped_refptr<SocketStream> socket_stream_; | |
| 234 const CompletionCallback callback_; | |
| 235 | |
| 236 DISALLOW_COPY_AND_ASSIGN(SelfDeletingDelegate); | |
| 237 }; | |
| 238 | |
| 239 class TestURLRequestContextWithProxy : public TestURLRequestContext { | |
| 240 public: | |
| 241 explicit TestURLRequestContextWithProxy(const std::string& proxy) | |
| 242 : TestURLRequestContext(true) { | |
| 243 context_storage_.set_proxy_service(ProxyService::CreateFixed(proxy)); | |
| 244 Init(); | |
| 245 } | |
| 246 ~TestURLRequestContextWithProxy() override {} | |
| 247 }; | |
| 248 | |
| 249 class TestSocketStreamNetworkDelegate : public TestNetworkDelegate { | |
| 250 public: | |
| 251 TestSocketStreamNetworkDelegate() | |
| 252 : before_connect_result_(OK) {} | |
| 253 ~TestSocketStreamNetworkDelegate() override {} | |
| 254 | |
| 255 int OnBeforeSocketStreamConnect(SocketStream* stream, | |
| 256 const CompletionCallback& callback) override { | |
| 257 return before_connect_result_; | |
| 258 } | |
| 259 | |
| 260 void SetBeforeConnectResult(int result) { | |
| 261 before_connect_result_ = result; | |
| 262 } | |
| 263 | |
| 264 private: | |
| 265 int before_connect_result_; | |
| 266 }; | |
| 267 | |
| 268 } // namespace | |
| 269 | |
| 270 class SocketStreamTest : public PlatformTest { | |
| 271 public: | |
| 272 ~SocketStreamTest() override {} | |
| 273 void SetUp() override { | |
| 274 mock_socket_factory_.reset(); | |
| 275 handshake_request_ = kWebSocketHandshakeRequest; | |
| 276 handshake_response_ = kWebSocketHandshakeResponse; | |
| 277 } | |
| 278 void TearDown() override { mock_socket_factory_.reset(); } | |
| 279 | |
| 280 virtual void SetWebSocketHandshakeMessage( | |
| 281 const char* request, const char* response) { | |
| 282 handshake_request_ = request; | |
| 283 handshake_response_ = response; | |
| 284 } | |
| 285 virtual void AddWebSocketMessage(const std::string& message) { | |
| 286 messages_.push_back(message); | |
| 287 } | |
| 288 | |
| 289 virtual MockClientSocketFactory* GetMockClientSocketFactory() { | |
| 290 mock_socket_factory_.reset(new MockClientSocketFactory); | |
| 291 return mock_socket_factory_.get(); | |
| 292 } | |
| 293 | |
| 294 // Functions for SocketStreamEventRecorder to handle calls to the | |
| 295 // SocketStream::Delegate methods from the SocketStream. | |
| 296 | |
| 297 virtual void DoSendWebSocketHandshake(SocketStreamEvent* event) { | |
| 298 event->socket->SendData( | |
| 299 handshake_request_.data(), handshake_request_.size()); | |
| 300 } | |
| 301 | |
| 302 virtual void DoCloseFlushPendingWriteTest(SocketStreamEvent* event) { | |
| 303 // handshake response received. | |
| 304 for (size_t i = 0; i < messages_.size(); i++) { | |
| 305 std::vector<char> frame; | |
| 306 frame.push_back('\0'); | |
| 307 frame.insert(frame.end(), messages_[i].begin(), messages_[i].end()); | |
| 308 frame.push_back('\xff'); | |
| 309 EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size())); | |
| 310 } | |
| 311 // Actual StreamSocket close must happen after all frames queued by | |
| 312 // SendData above are sent out. | |
| 313 event->socket->Close(); | |
| 314 } | |
| 315 | |
| 316 virtual void DoCloseFlushPendingWriteTestWithSetContextNull( | |
| 317 SocketStreamEvent* event) { | |
| 318 event->socket->DetachContext(); | |
| 319 // handshake response received. | |
| 320 for (size_t i = 0; i < messages_.size(); i++) { | |
| 321 std::vector<char> frame; | |
| 322 frame.push_back('\0'); | |
| 323 frame.insert(frame.end(), messages_[i].begin(), messages_[i].end()); | |
| 324 frame.push_back('\xff'); | |
| 325 EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size())); | |
| 326 } | |
| 327 // Actual StreamSocket close must happen after all frames queued by | |
| 328 // SendData above are sent out. | |
| 329 event->socket->Close(); | |
| 330 } | |
| 331 | |
| 332 virtual void DoFailByTooBigDataAndClose(SocketStreamEvent* event) { | |
| 333 std::string frame(event->number + 1, 0x00); | |
| 334 VLOG(1) << event->number; | |
| 335 EXPECT_FALSE(event->socket->SendData(&frame[0], frame.size())); | |
| 336 event->socket->Close(); | |
| 337 } | |
| 338 | |
| 339 virtual int DoSwitchToSpdyTest(SocketStreamEvent* event) { | |
| 340 return ERR_PROTOCOL_SWITCHED; | |
| 341 } | |
| 342 | |
| 343 // Notifies |io_test_callback_| of that this method is called, and keeps the | |
| 344 // SocketStream waiting. | |
| 345 virtual int DoIOPending(SocketStreamEvent* event) { | |
| 346 io_test_callback_.callback().Run(OK); | |
| 347 return ERR_IO_PENDING; | |
| 348 } | |
| 349 | |
| 350 static const char kWebSocketHandshakeRequest[]; | |
| 351 static const char kWebSocketHandshakeResponse[]; | |
| 352 | |
| 353 protected: | |
| 354 TestCompletionCallback io_test_callback_; | |
| 355 | |
| 356 private: | |
| 357 std::string handshake_request_; | |
| 358 std::string handshake_response_; | |
| 359 std::vector<std::string> messages_; | |
| 360 | |
| 361 scoped_ptr<MockClientSocketFactory> mock_socket_factory_; | |
| 362 }; | |
| 363 | |
| 364 const char SocketStreamTest::kWebSocketHandshakeRequest[] = | |
| 365 "GET /demo HTTP/1.1\r\n" | |
| 366 "Host: example.com\r\n" | |
| 367 "Connection: Upgrade\r\n" | |
| 368 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" | |
| 369 "Sec-WebSocket-Protocol: sample\r\n" | |
| 370 "Upgrade: WebSocket\r\n" | |
| 371 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" | |
| 372 "Origin: http://example.com\r\n" | |
| 373 "\r\n" | |
| 374 "^n:ds[4U"; | |
| 375 | |
| 376 const char SocketStreamTest::kWebSocketHandshakeResponse[] = | |
| 377 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" | |
| 378 "Upgrade: WebSocket\r\n" | |
| 379 "Connection: Upgrade\r\n" | |
| 380 "Sec-WebSocket-Origin: http://example.com\r\n" | |
| 381 "Sec-WebSocket-Location: ws://example.com/demo\r\n" | |
| 382 "Sec-WebSocket-Protocol: sample\r\n" | |
| 383 "\r\n" | |
| 384 "8jKS'y:G*Co,Wxa-"; | |
| 385 | |
| 386 TEST_F(SocketStreamTest, CloseFlushPendingWrite) { | |
| 387 TestCompletionCallback test_callback; | |
| 388 | |
| 389 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 390 new SocketStreamEventRecorder(test_callback.callback())); | |
| 391 delegate->SetOnConnected(base::Bind( | |
| 392 &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this))); | |
| 393 delegate->SetOnReceivedData(base::Bind( | |
| 394 &SocketStreamTest::DoCloseFlushPendingWriteTest, | |
| 395 base::Unretained(this))); | |
| 396 | |
| 397 TestURLRequestContext context; | |
| 398 | |
| 399 scoped_refptr<SocketStream> socket_stream( | |
| 400 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 401 &context, NULL)); | |
| 402 | |
| 403 MockWrite data_writes[] = { | |
| 404 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest), | |
| 405 MockWrite(ASYNC, "\0message1\xff", 10), | |
| 406 MockWrite(ASYNC, "\0message2\xff", 10) | |
| 407 }; | |
| 408 MockRead data_reads[] = { | |
| 409 MockRead(SocketStreamTest::kWebSocketHandshakeResponse), | |
| 410 // Server doesn't close the connection after handshake. | |
| 411 MockRead(ASYNC, ERR_IO_PENDING) | |
| 412 }; | |
| 413 AddWebSocketMessage("message1"); | |
| 414 AddWebSocketMessage("message2"); | |
| 415 | |
| 416 DelayedSocketData data_provider( | |
| 417 1, data_reads, arraysize(data_reads), | |
| 418 data_writes, arraysize(data_writes)); | |
| 419 | |
| 420 MockClientSocketFactory* mock_socket_factory = | |
| 421 GetMockClientSocketFactory(); | |
| 422 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
| 423 | |
| 424 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
| 425 | |
| 426 socket_stream->Connect(); | |
| 427 | |
| 428 test_callback.WaitForResult(); | |
| 429 | |
| 430 EXPECT_TRUE(data_provider.at_read_eof()); | |
| 431 EXPECT_TRUE(data_provider.at_write_eof()); | |
| 432 | |
| 433 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 434 ASSERT_EQ(7U, events.size()); | |
| 435 | |
| 436 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 437 events[0].event_type); | |
| 438 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 439 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type); | |
| 440 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type); | |
| 441 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type); | |
| 442 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type); | |
| 443 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type); | |
| 444 } | |
| 445 | |
| 446 TEST_F(SocketStreamTest, ResolveFailure) { | |
| 447 TestCompletionCallback test_callback; | |
| 448 | |
| 449 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 450 new SocketStreamEventRecorder(test_callback.callback())); | |
| 451 | |
| 452 // Make resolver fail. | |
| 453 TestURLRequestContext context; | |
| 454 scoped_ptr<MockHostResolver> mock_host_resolver( | |
| 455 new MockHostResolver()); | |
| 456 mock_host_resolver->rules()->AddSimulatedFailure("example.com"); | |
| 457 context.set_host_resolver(mock_host_resolver.get()); | |
| 458 | |
| 459 scoped_refptr<SocketStream> socket_stream( | |
| 460 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 461 &context, NULL)); | |
| 462 | |
| 463 // No read/write on socket is expected. | |
| 464 StaticSocketDataProvider data_provider(NULL, 0, NULL, 0); | |
| 465 MockClientSocketFactory* mock_socket_factory = | |
| 466 GetMockClientSocketFactory(); | |
| 467 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
| 468 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
| 469 | |
| 470 socket_stream->Connect(); | |
| 471 | |
| 472 test_callback.WaitForResult(); | |
| 473 | |
| 474 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 475 ASSERT_EQ(2U, events.size()); | |
| 476 | |
| 477 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type); | |
| 478 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type); | |
| 479 } | |
| 480 | |
| 481 TEST_F(SocketStreamTest, ExceedMaxPendingSendAllowed) { | |
| 482 TestCompletionCallback test_callback; | |
| 483 | |
| 484 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 485 new SocketStreamEventRecorder(test_callback.callback())); | |
| 486 delegate->SetOnConnected(base::Bind( | |
| 487 &SocketStreamTest::DoFailByTooBigDataAndClose, base::Unretained(this))); | |
| 488 | |
| 489 TestURLRequestContext context; | |
| 490 | |
| 491 scoped_refptr<SocketStream> socket_stream( | |
| 492 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 493 &context, NULL)); | |
| 494 | |
| 495 DelayedSocketData data_provider(1, NULL, 0, NULL, 0); | |
| 496 | |
| 497 MockClientSocketFactory* mock_socket_factory = | |
| 498 GetMockClientSocketFactory(); | |
| 499 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
| 500 | |
| 501 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
| 502 | |
| 503 socket_stream->Connect(); | |
| 504 | |
| 505 test_callback.WaitForResult(); | |
| 506 | |
| 507 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 508 ASSERT_EQ(4U, events.size()); | |
| 509 | |
| 510 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 511 events[0].event_type); | |
| 512 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 513 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type); | |
| 514 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
| 515 } | |
| 516 | |
| 517 TEST_F(SocketStreamTest, BasicAuthProxy) { | |
| 518 MockClientSocketFactory mock_socket_factory; | |
| 519 MockWrite data_writes1[] = { | |
| 520 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
| 521 "Host: example.com\r\n" | |
| 522 "Proxy-Connection: keep-alive\r\n\r\n"), | |
| 523 }; | |
| 524 MockRead data_reads1[] = { | |
| 525 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), | |
| 526 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), | |
| 527 MockRead("\r\n"), | |
| 528 }; | |
| 529 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), | |
| 530 data_writes1, arraysize(data_writes1)); | |
| 531 mock_socket_factory.AddSocketDataProvider(&data1); | |
| 532 | |
| 533 MockWrite data_writes2[] = { | |
| 534 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
| 535 "Host: example.com\r\n" | |
| 536 "Proxy-Connection: keep-alive\r\n" | |
| 537 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
| 538 }; | |
| 539 MockRead data_reads2[] = { | |
| 540 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
| 541 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
| 542 MockRead("\r\n"), | |
| 543 // SocketStream::DoClose is run asynchronously. Socket can be read after | |
| 544 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate | |
| 545 // server doesn't close the connection. | |
| 546 MockRead(ASYNC, ERR_IO_PENDING) | |
| 547 }; | |
| 548 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), | |
| 549 data_writes2, arraysize(data_writes2)); | |
| 550 mock_socket_factory.AddSocketDataProvider(&data2); | |
| 551 | |
| 552 TestCompletionCallback test_callback; | |
| 553 | |
| 554 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 555 new SocketStreamEventRecorder(test_callback.callback())); | |
| 556 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
| 557 base::Unretained(delegate.get()))); | |
| 558 delegate->SetAuthInfo(AuthCredentials(ASCIIToUTF16("foo"), | |
| 559 ASCIIToUTF16("bar"))); | |
| 560 delegate->SetOnAuthRequired(base::Bind( | |
| 561 &SocketStreamEventRecorder::DoRestartWithAuth, | |
| 562 base::Unretained(delegate.get()))); | |
| 563 | |
| 564 TestURLRequestContextWithProxy context("myproxy:70"); | |
| 565 | |
| 566 scoped_refptr<SocketStream> socket_stream( | |
| 567 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 568 &context, NULL)); | |
| 569 | |
| 570 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
| 571 | |
| 572 socket_stream->Connect(); | |
| 573 | |
| 574 test_callback.WaitForResult(); | |
| 575 | |
| 576 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 577 ASSERT_EQ(5U, events.size()); | |
| 578 | |
| 579 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 580 events[0].event_type); | |
| 581 EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[1].event_type); | |
| 582 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[2].event_type); | |
| 583 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[3].event_type); | |
| 584 EXPECT_EQ(ERR_ABORTED, events[3].error_code); | |
| 585 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type); | |
| 586 | |
| 587 // TODO(eroman): Add back NetLogTest here... | |
| 588 } | |
| 589 | |
| 590 TEST_F(SocketStreamTest, BasicAuthProxyWithAuthCache) { | |
| 591 MockClientSocketFactory mock_socket_factory; | |
| 592 MockWrite data_writes[] = { | |
| 593 // WebSocket(SocketStream) always uses CONNECT when it is configured to use | |
| 594 // proxy so the port may not be 443. | |
| 595 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
| 596 "Host: example.com\r\n" | |
| 597 "Proxy-Connection: keep-alive\r\n" | |
| 598 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
| 599 }; | |
| 600 MockRead data_reads[] = { | |
| 601 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
| 602 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
| 603 MockRead("\r\n"), | |
| 604 MockRead(ASYNC, ERR_IO_PENDING) | |
| 605 }; | |
| 606 StaticSocketDataProvider data(data_reads, arraysize(data_reads), | |
| 607 data_writes, arraysize(data_writes)); | |
| 608 mock_socket_factory.AddSocketDataProvider(&data); | |
| 609 | |
| 610 TestCompletionCallback test_callback; | |
| 611 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 612 new SocketStreamEventRecorder(test_callback.callback())); | |
| 613 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
| 614 base::Unretained(delegate.get()))); | |
| 615 | |
| 616 TestURLRequestContextWithProxy context("myproxy:70"); | |
| 617 HttpAuthCache* auth_cache = | |
| 618 context.http_transaction_factory()->GetSession()->http_auth_cache(); | |
| 619 auth_cache->Add(GURL("http://myproxy:70"), | |
| 620 "MyRealm1", | |
| 621 HttpAuth::AUTH_SCHEME_BASIC, | |
| 622 "Basic realm=MyRealm1", | |
| 623 AuthCredentials(ASCIIToUTF16("foo"), | |
| 624 ASCIIToUTF16("bar")), | |
| 625 "/"); | |
| 626 | |
| 627 scoped_refptr<SocketStream> socket_stream( | |
| 628 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 629 &context, NULL)); | |
| 630 | |
| 631 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
| 632 | |
| 633 socket_stream->Connect(); | |
| 634 | |
| 635 test_callback.WaitForResult(); | |
| 636 | |
| 637 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 638 ASSERT_EQ(4U, events.size()); | |
| 639 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 640 events[0].event_type); | |
| 641 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 642 EXPECT_EQ(ERR_ABORTED, events[2].error_code); | |
| 643 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
| 644 } | |
| 645 | |
| 646 TEST_F(SocketStreamTest, WSSBasicAuthProxyWithAuthCache) { | |
| 647 MockClientSocketFactory mock_socket_factory; | |
| 648 MockWrite data_writes1[] = { | |
| 649 MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" | |
| 650 "Host: example.com\r\n" | |
| 651 "Proxy-Connection: keep-alive\r\n" | |
| 652 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
| 653 }; | |
| 654 MockRead data_reads1[] = { | |
| 655 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
| 656 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
| 657 MockRead("\r\n"), | |
| 658 MockRead(ASYNC, ERR_IO_PENDING) | |
| 659 }; | |
| 660 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), | |
| 661 data_writes1, arraysize(data_writes1)); | |
| 662 mock_socket_factory.AddSocketDataProvider(&data1); | |
| 663 | |
| 664 SSLSocketDataProvider data2(ASYNC, OK); | |
| 665 mock_socket_factory.AddSSLSocketDataProvider(&data2); | |
| 666 | |
| 667 TestCompletionCallback test_callback; | |
| 668 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 669 new SocketStreamEventRecorder(test_callback.callback())); | |
| 670 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
| 671 base::Unretained(delegate.get()))); | |
| 672 | |
| 673 TestURLRequestContextWithProxy context("myproxy:70"); | |
| 674 HttpAuthCache* auth_cache = | |
| 675 context.http_transaction_factory()->GetSession()->http_auth_cache(); | |
| 676 auth_cache->Add(GURL("http://myproxy:70"), | |
| 677 "MyRealm1", | |
| 678 HttpAuth::AUTH_SCHEME_BASIC, | |
| 679 "Basic realm=MyRealm1", | |
| 680 AuthCredentials(ASCIIToUTF16("foo"), | |
| 681 ASCIIToUTF16("bar")), | |
| 682 "/"); | |
| 683 | |
| 684 scoped_refptr<SocketStream> socket_stream( | |
| 685 new SocketStream(GURL("wss://example.com/demo"), delegate.get(), | |
| 686 &context, NULL)); | |
| 687 | |
| 688 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
| 689 | |
| 690 socket_stream->Connect(); | |
| 691 | |
| 692 test_callback.WaitForResult(); | |
| 693 | |
| 694 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 695 ASSERT_EQ(4U, events.size()); | |
| 696 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 697 events[0].event_type); | |
| 698 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 699 EXPECT_EQ(ERR_ABORTED, events[2].error_code); | |
| 700 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
| 701 } | |
| 702 | |
| 703 TEST_F(SocketStreamTest, IOPending) { | |
| 704 TestCompletionCallback test_callback; | |
| 705 | |
| 706 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 707 new SocketStreamEventRecorder(test_callback.callback())); | |
| 708 delegate->SetOnStartOpenConnection(base::Bind( | |
| 709 &SocketStreamTest::DoIOPending, base::Unretained(this))); | |
| 710 delegate->SetOnConnected(base::Bind( | |
| 711 &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this))); | |
| 712 delegate->SetOnReceivedData(base::Bind( | |
| 713 &SocketStreamTest::DoCloseFlushPendingWriteTest, | |
| 714 base::Unretained(this))); | |
| 715 | |
| 716 TestURLRequestContext context; | |
| 717 | |
| 718 scoped_refptr<SocketStream> socket_stream( | |
| 719 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 720 &context, NULL)); | |
| 721 | |
| 722 MockWrite data_writes[] = { | |
| 723 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest), | |
| 724 MockWrite(ASYNC, "\0message1\xff", 10), | |
| 725 MockWrite(ASYNC, "\0message2\xff", 10) | |
| 726 }; | |
| 727 MockRead data_reads[] = { | |
| 728 MockRead(SocketStreamTest::kWebSocketHandshakeResponse), | |
| 729 // Server doesn't close the connection after handshake. | |
| 730 MockRead(ASYNC, ERR_IO_PENDING) | |
| 731 }; | |
| 732 AddWebSocketMessage("message1"); | |
| 733 AddWebSocketMessage("message2"); | |
| 734 | |
| 735 DelayedSocketData data_provider( | |
| 736 1, data_reads, arraysize(data_reads), | |
| 737 data_writes, arraysize(data_writes)); | |
| 738 | |
| 739 MockClientSocketFactory* mock_socket_factory = | |
| 740 GetMockClientSocketFactory(); | |
| 741 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
| 742 | |
| 743 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
| 744 | |
| 745 socket_stream->Connect(); | |
| 746 io_test_callback_.WaitForResult(); | |
| 747 EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE, | |
| 748 socket_stream->next_state_); | |
| 749 delegate->CompleteConnection(OK); | |
| 750 | |
| 751 EXPECT_EQ(OK, test_callback.WaitForResult()); | |
| 752 | |
| 753 EXPECT_TRUE(data_provider.at_read_eof()); | |
| 754 EXPECT_TRUE(data_provider.at_write_eof()); | |
| 755 | |
| 756 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 757 ASSERT_EQ(7U, events.size()); | |
| 758 | |
| 759 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 760 events[0].event_type); | |
| 761 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 762 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type); | |
| 763 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type); | |
| 764 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type); | |
| 765 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type); | |
| 766 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type); | |
| 767 } | |
| 768 | |
| 769 TEST_F(SocketStreamTest, SwitchToSpdy) { | |
| 770 TestCompletionCallback test_callback; | |
| 771 | |
| 772 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 773 new SocketStreamEventRecorder(test_callback.callback())); | |
| 774 delegate->SetOnStartOpenConnection(base::Bind( | |
| 775 &SocketStreamTest::DoSwitchToSpdyTest, base::Unretained(this))); | |
| 776 | |
| 777 TestURLRequestContext context; | |
| 778 | |
| 779 scoped_refptr<SocketStream> socket_stream( | |
| 780 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 781 &context, NULL)); | |
| 782 | |
| 783 socket_stream->Connect(); | |
| 784 | |
| 785 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult()); | |
| 786 | |
| 787 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 788 ASSERT_EQ(2U, events.size()); | |
| 789 | |
| 790 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 791 events[0].event_type); | |
| 792 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type); | |
| 793 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code); | |
| 794 } | |
| 795 | |
| 796 TEST_F(SocketStreamTest, SwitchAfterPending) { | |
| 797 TestCompletionCallback test_callback; | |
| 798 | |
| 799 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 800 new SocketStreamEventRecorder(test_callback.callback())); | |
| 801 delegate->SetOnStartOpenConnection(base::Bind( | |
| 802 &SocketStreamTest::DoIOPending, base::Unretained(this))); | |
| 803 | |
| 804 TestURLRequestContext context; | |
| 805 | |
| 806 scoped_refptr<SocketStream> socket_stream( | |
| 807 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 808 &context, NULL)); | |
| 809 | |
| 810 socket_stream->Connect(); | |
| 811 io_test_callback_.WaitForResult(); | |
| 812 | |
| 813 EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE, | |
| 814 socket_stream->next_state_); | |
| 815 delegate->CompleteConnection(ERR_PROTOCOL_SWITCHED); | |
| 816 | |
| 817 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult()); | |
| 818 | |
| 819 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 820 ASSERT_EQ(2U, events.size()); | |
| 821 | |
| 822 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 823 events[0].event_type); | |
| 824 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type); | |
| 825 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code); | |
| 826 } | |
| 827 | |
| 828 // Test a connection though a secure proxy. | |
| 829 TEST_F(SocketStreamTest, SecureProxyConnectError) { | |
| 830 MockClientSocketFactory mock_socket_factory; | |
| 831 MockWrite data_writes[] = { | |
| 832 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
| 833 "Host: example.com\r\n" | |
| 834 "Proxy-Connection: keep-alive\r\n\r\n") | |
| 835 }; | |
| 836 MockRead data_reads[] = { | |
| 837 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
| 838 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
| 839 MockRead("\r\n"), | |
| 840 // SocketStream::DoClose is run asynchronously. Socket can be read after | |
| 841 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate | |
| 842 // server doesn't close the connection. | |
| 843 MockRead(ASYNC, ERR_IO_PENDING) | |
| 844 }; | |
| 845 StaticSocketDataProvider data(data_reads, arraysize(data_reads), | |
| 846 data_writes, arraysize(data_writes)); | |
| 847 mock_socket_factory.AddSocketDataProvider(&data); | |
| 848 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); | |
| 849 mock_socket_factory.AddSSLSocketDataProvider(&ssl); | |
| 850 | |
| 851 TestCompletionCallback test_callback; | |
| 852 TestURLRequestContextWithProxy context("https://myproxy:70"); | |
| 853 | |
| 854 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 855 new SocketStreamEventRecorder(test_callback.callback())); | |
| 856 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
| 857 base::Unretained(delegate.get()))); | |
| 858 | |
| 859 scoped_refptr<SocketStream> socket_stream( | |
| 860 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 861 &context, NULL)); | |
| 862 | |
| 863 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
| 864 | |
| 865 socket_stream->Connect(); | |
| 866 | |
| 867 test_callback.WaitForResult(); | |
| 868 | |
| 869 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 870 ASSERT_EQ(3U, events.size()); | |
| 871 | |
| 872 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 873 events[0].event_type); | |
| 874 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type); | |
| 875 EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, events[1].error_code); | |
| 876 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type); | |
| 877 } | |
| 878 | |
| 879 // Test a connection though a secure proxy. | |
| 880 TEST_F(SocketStreamTest, SecureProxyConnect) { | |
| 881 MockClientSocketFactory mock_socket_factory; | |
| 882 MockWrite data_writes[] = { | |
| 883 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
| 884 "Host: example.com\r\n" | |
| 885 "Proxy-Connection: keep-alive\r\n\r\n") | |
| 886 }; | |
| 887 MockRead data_reads[] = { | |
| 888 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
| 889 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
| 890 MockRead("\r\n"), | |
| 891 // SocketStream::DoClose is run asynchronously. Socket can be read after | |
| 892 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate | |
| 893 // server doesn't close the connection. | |
| 894 MockRead(ASYNC, ERR_IO_PENDING) | |
| 895 }; | |
| 896 StaticSocketDataProvider data(data_reads, arraysize(data_reads), | |
| 897 data_writes, arraysize(data_writes)); | |
| 898 mock_socket_factory.AddSocketDataProvider(&data); | |
| 899 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | |
| 900 mock_socket_factory.AddSSLSocketDataProvider(&ssl); | |
| 901 | |
| 902 TestCompletionCallback test_callback; | |
| 903 TestURLRequestContextWithProxy context("https://myproxy:70"); | |
| 904 | |
| 905 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 906 new SocketStreamEventRecorder(test_callback.callback())); | |
| 907 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
| 908 base::Unretained(delegate.get()))); | |
| 909 | |
| 910 scoped_refptr<SocketStream> socket_stream( | |
| 911 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 912 &context, NULL)); | |
| 913 | |
| 914 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
| 915 | |
| 916 socket_stream->Connect(); | |
| 917 | |
| 918 test_callback.WaitForResult(); | |
| 919 | |
| 920 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 921 ASSERT_EQ(4U, events.size()); | |
| 922 | |
| 923 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 924 events[0].event_type); | |
| 925 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 926 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type); | |
| 927 EXPECT_EQ(ERR_ABORTED, events[2].error_code); | |
| 928 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
| 929 } | |
| 930 | |
| 931 TEST_F(SocketStreamTest, BeforeConnectFailed) { | |
| 932 TestCompletionCallback test_callback; | |
| 933 | |
| 934 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 935 new SocketStreamEventRecorder(test_callback.callback())); | |
| 936 | |
| 937 TestURLRequestContext context; | |
| 938 TestSocketStreamNetworkDelegate network_delegate; | |
| 939 network_delegate.SetBeforeConnectResult(ERR_ACCESS_DENIED); | |
| 940 context.set_network_delegate(&network_delegate); | |
| 941 | |
| 942 scoped_refptr<SocketStream> socket_stream( | |
| 943 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 944 &context, NULL)); | |
| 945 | |
| 946 socket_stream->Connect(); | |
| 947 | |
| 948 test_callback.WaitForResult(); | |
| 949 | |
| 950 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 951 ASSERT_EQ(2U, events.size()); | |
| 952 | |
| 953 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type); | |
| 954 EXPECT_EQ(ERR_ACCESS_DENIED, events[0].error_code); | |
| 955 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type); | |
| 956 } | |
| 957 | |
| 958 // Check that a connect failure, followed by the delegate calling DetachDelegate | |
| 959 // and deleting itself in the OnError callback, is handled correctly. | |
| 960 TEST_F(SocketStreamTest, OnErrorDetachDelegate) { | |
| 961 MockClientSocketFactory mock_socket_factory; | |
| 962 TestCompletionCallback test_callback; | |
| 963 | |
| 964 // SelfDeletingDelegate is self-owning; we just need a pointer to it to | |
| 965 // connect it and the SocketStream. | |
| 966 SelfDeletingDelegate* delegate = | |
| 967 new SelfDeletingDelegate(test_callback.callback()); | |
| 968 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); | |
| 969 StaticSocketDataProvider data; | |
| 970 data.set_connect_data(mock_connect); | |
| 971 mock_socket_factory.AddSocketDataProvider(&data); | |
| 972 | |
| 973 TestURLRequestContext context; | |
| 974 scoped_refptr<SocketStream> socket_stream( | |
| 975 new SocketStream(GURL("ws://localhost:9998/echo"), delegate, | |
| 976 &context, NULL)); | |
| 977 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
| 978 delegate->set_socket_stream(socket_stream); | |
| 979 // The delegate pointer will become invalid during the test. Set it to NULL to | |
| 980 // avoid holding a dangling pointer. | |
| 981 delegate = NULL; | |
| 982 | |
| 983 socket_stream->Connect(); | |
| 984 | |
| 985 EXPECT_EQ(OK, test_callback.WaitForResult()); | |
| 986 } | |
| 987 | |
| 988 TEST_F(SocketStreamTest, NullContextSocketStreamShouldNotCrash) { | |
| 989 TestCompletionCallback test_callback; | |
| 990 | |
| 991 scoped_ptr<SocketStreamEventRecorder> delegate( | |
| 992 new SocketStreamEventRecorder(test_callback.callback())); | |
| 993 TestURLRequestContext context; | |
| 994 scoped_refptr<SocketStream> socket_stream( | |
| 995 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
| 996 &context, NULL)); | |
| 997 delegate->SetOnStartOpenConnection(base::Bind( | |
| 998 &SocketStreamTest::DoIOPending, base::Unretained(this))); | |
| 999 delegate->SetOnConnected(base::Bind( | |
| 1000 &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this))); | |
| 1001 delegate->SetOnReceivedData(base::Bind( | |
| 1002 &SocketStreamTest::DoCloseFlushPendingWriteTestWithSetContextNull, | |
| 1003 base::Unretained(this))); | |
| 1004 | |
| 1005 MockWrite data_writes[] = { | |
| 1006 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest), | |
| 1007 }; | |
| 1008 MockRead data_reads[] = { | |
| 1009 MockRead(SocketStreamTest::kWebSocketHandshakeResponse), | |
| 1010 }; | |
| 1011 AddWebSocketMessage("message1"); | |
| 1012 AddWebSocketMessage("message2"); | |
| 1013 | |
| 1014 DelayedSocketData data_provider( | |
| 1015 1, data_reads, arraysize(data_reads), | |
| 1016 data_writes, arraysize(data_writes)); | |
| 1017 | |
| 1018 MockClientSocketFactory* mock_socket_factory = GetMockClientSocketFactory(); | |
| 1019 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
| 1020 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
| 1021 | |
| 1022 socket_stream->Connect(); | |
| 1023 io_test_callback_.WaitForResult(); | |
| 1024 delegate->CompleteConnection(OK); | |
| 1025 EXPECT_EQ(OK, test_callback.WaitForResult()); | |
| 1026 | |
| 1027 EXPECT_TRUE(data_provider.at_read_eof()); | |
| 1028 EXPECT_TRUE(data_provider.at_write_eof()); | |
| 1029 | |
| 1030 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
| 1031 ASSERT_EQ(5U, events.size()); | |
| 1032 | |
| 1033 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
| 1034 events[0].event_type); | |
| 1035 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
| 1036 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type); | |
| 1037 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type); | |
| 1038 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type); | |
| 1039 } | |
| 1040 | |
| 1041 } // namespace net | |
| OLD | NEW |