1 // Copyright 2013 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/spdy/spdy_websocket_stream.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "net/base/completion_callback.h" 13 #include "net/proxy/proxy_server.h" 14 #include "net/socket/next_proto.h" 15 #include "net/socket/ssl_client_socket.h" 16 #include "net/spdy/spdy_http_utils.h" 17 #include "net/spdy/spdy_protocol.h" 18 #include "net/spdy/spdy_session.h" 19 #include "net/spdy/spdy_websocket_test_util.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace net { 23 24 namespace { 25 26 struct SpdyWebSocketStreamEvent { 27 enum EventType { 28 EVENT_CREATED, 29 EVENT_SENT_HEADERS, 30 EVENT_RECEIVED_HEADER, 31 EVENT_SENT_DATA, 32 EVENT_RECEIVED_DATA, 33 EVENT_CLOSE, 34 }; 35 SpdyWebSocketStreamEvent(EventType type, 36 const SpdyHeaderBlock& headers, 37 int result, 38 const std::string& data) 39 : event_type(type), 40 headers(headers), 41 result(result), 42 data(data) {} 43 44 EventType event_type; 45 SpdyHeaderBlock headers; 46 int result; 47 std::string data; 48 }; 49 50 class SpdyWebSocketStreamEventRecorder : public SpdyWebSocketStream::Delegate { 51 public: 52 explicit SpdyWebSocketStreamEventRecorder(const CompletionCallback& callback) 53 : callback_(callback) {} 54 virtual ~SpdyWebSocketStreamEventRecorder() {} 55 56 typedef base::Callback<void(SpdyWebSocketStreamEvent*)> StreamEventCallback; 57 58 void SetOnCreated(const StreamEventCallback& callback) { 59 on_created_ = callback; 60 } 61 void SetOnSentHeaders(const StreamEventCallback& callback) { 62 on_sent_headers_ = callback; 63 } 64 void SetOnReceivedHeader(const StreamEventCallback& callback) { 65 on_received_header_ = callback; 66 } 67 void SetOnSentData(const StreamEventCallback& callback) { 68 on_sent_data_ = callback; 69 } 70 void SetOnReceivedData(const StreamEventCallback& callback) { 71 on_received_data_ = callback; 72 } 73 void SetOnClose(const StreamEventCallback& callback) { 74 on_close_ = callback; 75 } 76 77 virtual void OnCreatedSpdyStream(int result) OVERRIDE { 78 events_.push_back( 79 SpdyWebSocketStreamEvent(SpdyWebSocketStreamEvent::EVENT_CREATED, 80 SpdyHeaderBlock(), 81 result, 82 std::string())); 83 if (!on_created_.is_null()) 84 on_created_.Run(&events_.back()); 85 } 86 virtual void OnSentSpdyHeaders() OVERRIDE { 87 events_.push_back( 88 SpdyWebSocketStreamEvent(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS, 89 SpdyHeaderBlock(), 90 OK, 91 std::string())); 92 if (!on_sent_data_.is_null()) 93 on_sent_data_.Run(&events_.back()); 94 } 95 virtual void OnSpdyResponseHeadersUpdated( 96 const SpdyHeaderBlock& response_headers) OVERRIDE { 97 events_.push_back( 98 SpdyWebSocketStreamEvent( 99 SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER, 100 response_headers, 101 OK, 102 std::string())); 103 if (!on_received_header_.is_null()) 104 on_received_header_.Run(&events_.back()); 105 } 106 virtual void OnSentSpdyData(size_t bytes_sent) OVERRIDE { 107 events_.push_back( 108 SpdyWebSocketStreamEvent( 109 SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 110 SpdyHeaderBlock(), 111 static_cast<int>(bytes_sent), 112 std::string())); 113 if (!on_sent_data_.is_null()) 114 on_sent_data_.Run(&events_.back()); 115 } 116 virtual void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) OVERRIDE { 117 std::string buffer_data; 118 size_t buffer_len = 0; 119 if (buffer) { 120 buffer_len = buffer->GetRemainingSize(); 121 buffer_data.append(buffer->GetRemainingData(), buffer_len); 122 } 123 events_.push_back( 124 SpdyWebSocketStreamEvent( 125 SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 126 SpdyHeaderBlock(), 127 buffer_len, 128 buffer_data)); 129 if (!on_received_data_.is_null()) 130 on_received_data_.Run(&events_.back()); 131 } 132 virtual void OnCloseSpdyStream() OVERRIDE { 133 events_.push_back( 134 SpdyWebSocketStreamEvent( 135 SpdyWebSocketStreamEvent::EVENT_CLOSE, 136 SpdyHeaderBlock(), 137 OK, 138 std::string())); 139 if (!on_close_.is_null()) 140 on_close_.Run(&events_.back()); 141 if (!callback_.is_null()) 142 callback_.Run(OK); 143 } 144 145 const std::vector<SpdyWebSocketStreamEvent>& GetSeenEvents() const { 146 return events_; 147 } 148 149 private: 150 std::vector<SpdyWebSocketStreamEvent> events_; 151 StreamEventCallback on_created_; 152 StreamEventCallback on_sent_headers_; 153 StreamEventCallback on_received_header_; 154 StreamEventCallback on_sent_data_; 155 StreamEventCallback on_received_data_; 156 StreamEventCallback on_close_; 157 CompletionCallback callback_; 158 159 DISALLOW_COPY_AND_ASSIGN(SpdyWebSocketStreamEventRecorder); 160 }; 161 162 } // namespace 163 164 class SpdyWebSocketStreamTest 165 : public ::testing::Test, 166 public ::testing::WithParamInterface<NextProto> { 167 public: 168 OrderedSocketData* data() { return data_.get(); } 169 170 void DoSendHelloFrame(SpdyWebSocketStreamEvent* event) { 171 // Record the actual stream_id. 172 created_stream_id_ = websocket_stream_->stream_->stream_id(); 173 websocket_stream_->SendData(kMessageFrame, kMessageFrameLength); 174 } 175 176 void DoSendClosingFrame(SpdyWebSocketStreamEvent* event) { 177 websocket_stream_->SendData(kClosingFrame, kClosingFrameLength); 178 } 179 180 void DoClose(SpdyWebSocketStreamEvent* event) { 181 websocket_stream_->Close(); 182 } 183 184 void DoSync(SpdyWebSocketStreamEvent* event) { 185 sync_callback_.callback().Run(OK); 186 } 187 188 protected: 189 SpdyWebSocketStreamTest() 190 : spdy_util_(GetParam()), 191 spdy_settings_id_to_set_(SETTINGS_MAX_CONCURRENT_STREAMS), 192 spdy_settings_flags_to_set_(SETTINGS_FLAG_PLEASE_PERSIST), 193 spdy_settings_value_to_set_(1), 194 session_deps_(GetParam()), 195 stream_id_(0), 196 created_stream_id_(0) {} 197 virtual ~SpdyWebSocketStreamTest() {} 198 199 virtual void SetUp() { 200 host_port_pair_.set_host("example.com"); 201 host_port_pair_.set_port(80); 202 spdy_session_key_ = SpdySessionKey(host_port_pair_, 203 ProxyServer::Direct(), 204 PRIVACY_MODE_DISABLED); 205 206 spdy_settings_to_send_[spdy_settings_id_to_set_] = 207 SettingsFlagsAndValue( 208 SETTINGS_FLAG_PERSISTED, spdy_settings_value_to_set_); 209 } 210 211 virtual void TearDown() { 212 base::MessageLoop::current()->RunUntilIdle(); 213 } 214 215 void Prepare(SpdyStreamId stream_id) { 216 stream_id_ = stream_id; 217 218 request_frame_.reset(spdy_util_.ConstructSpdyWebSocketSynStream( 219 stream_id_, 220 "/echo", 221 "example.com", 222 "http://example.com/wsdemo")); 223 224 response_frame_.reset( 225 spdy_util_.ConstructSpdyWebSocketSynReply(stream_id_)); 226 227 message_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame( 228 kMessageFrame, 229 kMessageFrameLength, 230 stream_id_, 231 false)); 232 233 closing_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame( 234 kClosingFrame, 235 kClosingFrameLength, 236 stream_id_, 237 false)); 238 239 closing_frame_fin_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame( 240 kClosingFrame, 241 kClosingFrameLength, 242 stream_id_, 243 true)); 244 } 245 246 void InitSession(MockRead* reads, size_t reads_count, 247 MockWrite* writes, size_t writes_count) { 248 data_.reset(new OrderedSocketData(reads, reads_count, 249 writes, writes_count)); 250 session_deps_.socket_factory->AddSocketDataProvider(data_.get()); 251 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 252 session_ = CreateInsecureSpdySession( 253 http_session_, spdy_session_key_, BoundNetLog()); 254 } 255 256 void SendRequest() { 257 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); 258 spdy_util_.SetHeader("path", "/echo", headers.get()); 259 spdy_util_.SetHeader("host", "example.com", headers.get()); 260 spdy_util_.SetHeader("version", "WebSocket/13", headers.get()); 261 spdy_util_.SetHeader("scheme", "ws", headers.get()); 262 spdy_util_.SetHeader("origin", "http://example.com/wsdemo", headers.get()); 263 websocket_stream_->SendRequest(headers.Pass()); 264 } 265 266 SpdyWebSocketTestUtil spdy_util_; 267 SpdySettingsIds spdy_settings_id_to_set_; 268 SpdySettingsFlags spdy_settings_flags_to_set_; 269 uint32 spdy_settings_value_to_set_; 270 SettingsMap spdy_settings_to_send_; 271 SpdySessionDependencies session_deps_; 272 scoped_ptr<OrderedSocketData> data_; 273 scoped_refptr<HttpNetworkSession> http_session_; 274 base::WeakPtr<SpdySession> session_; 275 scoped_ptr<SpdyWebSocketStream> websocket_stream_; 276 SpdyStreamId stream_id_; 277 SpdyStreamId created_stream_id_; 278 scoped_ptr<SpdyFrame> request_frame_; 279 scoped_ptr<SpdyFrame> response_frame_; 280 scoped_ptr<SpdyFrame> message_frame_; 281 scoped_ptr<SpdyFrame> closing_frame_; 282 scoped_ptr<SpdyFrame> closing_frame_fin_; 283 HostPortPair host_port_pair_; 284 SpdySessionKey spdy_session_key_; 285 TestCompletionCallback completion_callback_; 286 TestCompletionCallback sync_callback_; 287 288 static const char kMessageFrame[]; 289 static const char kClosingFrame[]; 290 static const size_t kMessageFrameLength; 291 static const size_t kClosingFrameLength; 292 }; 293 294 INSTANTIATE_TEST_CASE_P( 295 NextProto, 296 SpdyWebSocketStreamTest, 297 testing::Values(kProtoDeprecatedSPDY2, 298 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4)); 299 300 // TODO(toyoshim): Replace old framing data to new one, then use HEADERS and 301 // data frames. 302 const char SpdyWebSocketStreamTest::kMessageFrame[] = "\x81\x05hello"; 303 const char SpdyWebSocketStreamTest::kClosingFrame[] = "\x88\0"; 304 const size_t SpdyWebSocketStreamTest::kMessageFrameLength = 305 arraysize(SpdyWebSocketStreamTest::kMessageFrame) - 1; 306 const size_t SpdyWebSocketStreamTest::kClosingFrameLength = 307 arraysize(SpdyWebSocketStreamTest::kClosingFrame) - 1; 308 309 TEST_P(SpdyWebSocketStreamTest, Basic) { 310 Prepare(1); 311 MockWrite writes[] = { 312 CreateMockWrite(*request_frame_.get(), 1), 313 CreateMockWrite(*message_frame_.get(), 3), 314 CreateMockWrite(*closing_frame_.get(), 5) 315 }; 316 317 MockRead reads[] = { 318 CreateMockRead(*response_frame_.get(), 2), 319 CreateMockRead(*message_frame_.get(), 4), 320 // Skip sequence 6 to notify closing has been sent. 321 CreateMockRead(*closing_frame_.get(), 7), 322 MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event. 323 }; 324 325 InitSession(reads, arraysize(reads), writes, arraysize(writes)); 326 327 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); 328 delegate.SetOnReceivedHeader( 329 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame, 330 base::Unretained(this))); 331 delegate.SetOnReceivedData( 332 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame, 333 base::Unretained(this))); 334 335 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate)); 336 337 BoundNetLog net_log; 338 GURL url("ws://example.com/echo"); 339 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log)); 340 341 ASSERT_TRUE(websocket_stream_->stream_.get()); 342 343 SendRequest(); 344 345 completion_callback_.WaitForResult(); 346 347 EXPECT_EQ(stream_id_, created_stream_id_); 348 349 websocket_stream_.reset(); 350 351 const std::vector<SpdyWebSocketStreamEvent>& events = 352 delegate.GetSeenEvents(); 353 ASSERT_EQ(7U, events.size()); 354 355 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS, 356 events[0].event_type); 357 EXPECT_EQ(OK, events[0].result); 358 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER, 359 events[1].event_type); 360 EXPECT_EQ(OK, events[1].result); 361 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 362 events[2].event_type); 363 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result); 364 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 365 events[3].event_type); 366 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result); 367 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 368 events[4].event_type); 369 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[4].result); 370 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 371 events[5].event_type); 372 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result); 373 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, 374 events[6].event_type); 375 EXPECT_EQ(OK, events[6].result); 376 377 // EOF close SPDY session. 378 EXPECT_FALSE( 379 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); 380 EXPECT_TRUE(data()->at_read_eof()); 381 EXPECT_TRUE(data()->at_write_eof()); 382 } 383 384 // A SPDY websocket may still send it's close frame after 385 // recieving a close with SPDY stream FIN. 386 TEST_P(SpdyWebSocketStreamTest, RemoteCloseWithFin) { 387 Prepare(1); 388 MockWrite writes[] = { 389 CreateMockWrite(*request_frame_.get(), 1), 390 CreateMockWrite(*closing_frame_.get(), 4), 391 }; 392 MockRead reads[] = { 393 CreateMockRead(*response_frame_.get(), 2), 394 CreateMockRead(*closing_frame_fin_.get(), 3), 395 MockRead(SYNCHRONOUS, 0, 5) // EOF cause OnCloseSpdyStream event. 396 }; 397 InitSession(reads, arraysize(reads), writes, arraysize(writes)); 398 399 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); 400 delegate.SetOnReceivedData( 401 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame, 402 base::Unretained(this))); 403 404 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate)); 405 BoundNetLog net_log; 406 GURL url("ws://example.com/echo"); 407 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log)); 408 409 SendRequest(); 410 completion_callback_.WaitForResult(); 411 websocket_stream_.reset(); 412 413 const std::vector<SpdyWebSocketStreamEvent>& events = 414 delegate.GetSeenEvents(); 415 EXPECT_EQ(5U, events.size()); 416 417 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS, 418 events[0].event_type); 419 EXPECT_EQ(OK, events[0].result); 420 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER, 421 events[1].event_type); 422 EXPECT_EQ(OK, events[1].result); 423 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 424 events[2].event_type); 425 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[2].result); 426 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 427 events[3].event_type); 428 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[3].result); 429 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, 430 events[4].event_type); 431 EXPECT_EQ(OK, events[4].result); 432 433 // EOF closes SPDY session. 434 EXPECT_FALSE( 435 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); 436 EXPECT_TRUE(data()->at_read_eof()); 437 EXPECT_TRUE(data()->at_write_eof()); 438 } 439 440 TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) { 441 Prepare(1); 442 MockWrite writes[] = { 443 CreateMockWrite(*request_frame_.get(), 1), 444 CreateMockWrite(*message_frame_.get(), 3) 445 }; 446 447 MockRead reads[] = { 448 CreateMockRead(*response_frame_.get(), 2), 449 CreateMockRead(*message_frame_.get(), 4), 450 MockRead(ASYNC, ERR_IO_PENDING, 5) 451 }; 452 453 InitSession(reads, arraysize(reads), writes, arraysize(writes)); 454 455 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); 456 delegate.SetOnReceivedHeader( 457 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame, 458 base::Unretained(this))); 459 delegate.SetOnReceivedData( 460 base::Bind(&SpdyWebSocketStreamTest::DoSync, 461 base::Unretained(this))); 462 463 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate)); 464 465 BoundNetLog net_log; 466 GURL url("ws://example.com/echo"); 467 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log)); 468 469 SendRequest(); 470 471 sync_callback_.WaitForResult(); 472 473 // WebSocketStream destruction remove its SPDY stream from the session. 474 EXPECT_TRUE(session_->IsStreamActive(stream_id_)); 475 websocket_stream_.reset(); 476 EXPECT_FALSE(session_->IsStreamActive(stream_id_)); 477 478 const std::vector<SpdyWebSocketStreamEvent>& events = 479 delegate.GetSeenEvents(); 480 ASSERT_GE(4U, events.size()); 481 482 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS, 483 events[0].event_type); 484 EXPECT_EQ(OK, events[0].result); 485 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER, 486 events[1].event_type); 487 EXPECT_EQ(OK, events[1].result); 488 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 489 events[2].event_type); 490 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result); 491 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 492 events[3].event_type); 493 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result); 494 495 EXPECT_TRUE( 496 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); 497 EXPECT_TRUE(data()->at_read_eof()); 498 EXPECT_TRUE(data()->at_write_eof()); 499 } 500 501 TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) { 502 Prepare(1); 503 MockWrite writes[] = { 504 CreateMockWrite(*request_frame_.get(), 1), 505 CreateMockWrite(*message_frame_.get(), 3), 506 CreateMockWrite(*closing_frame_.get(), 5) 507 }; 508 509 MockRead reads[] = { 510 CreateMockRead(*response_frame_.get(), 2), 511 CreateMockRead(*message_frame_.get(), 4), 512 MockRead(ASYNC, ERR_IO_PENDING, 6) 513 }; 514 515 InitSession(reads, arraysize(reads), writes, arraysize(writes)); 516 517 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); 518 delegate.SetOnReceivedHeader( 519 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame, 520 base::Unretained(this))); 521 delegate.SetOnReceivedData( 522 base::Bind(&SpdyWebSocketStreamTest::DoClose, 523 base::Unretained(this))); 524 525 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate)); 526 527 BoundNetLog net_log; 528 GURL url("ws://example.com/echo"); 529 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log)); 530 531 SendRequest(); 532 533 completion_callback_.WaitForResult(); 534 535 // SPDY stream has already been removed from the session by Close(). 536 EXPECT_FALSE(session_->IsStreamActive(stream_id_)); 537 websocket_stream_.reset(); 538 539 const std::vector<SpdyWebSocketStreamEvent>& events = 540 delegate.GetSeenEvents(); 541 ASSERT_EQ(5U, events.size()); 542 543 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS, 544 events[0].event_type); 545 EXPECT_EQ(OK, events[0].result); 546 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER, 547 events[1].event_type); 548 EXPECT_EQ(OK, events[1].result); 549 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 550 events[2].event_type); 551 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result); 552 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 553 events[3].event_type); 554 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result); 555 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, events[4].event_type); 556 557 EXPECT_TRUE( 558 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); 559 } 560 561 TEST_P(SpdyWebSocketStreamTest, IOPending) { 562 Prepare(1); 563 scoped_ptr<SpdyFrame> settings_frame( 564 spdy_util_.ConstructSpdySettings(spdy_settings_to_send_)); 565 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck()); 566 MockWrite writes[] = { 567 CreateMockWrite(*settings_ack, 1), 568 CreateMockWrite(*request_frame_.get(), 2), 569 CreateMockWrite(*message_frame_.get(), 4), 570 CreateMockWrite(*closing_frame_.get(), 6) 571 }; 572 573 MockRead reads[] = { 574 CreateMockRead(*settings_frame.get(), 0), 575 CreateMockRead(*response_frame_.get(), 3), 576 CreateMockRead(*message_frame_.get(), 5), 577 CreateMockRead(*closing_frame_.get(), 7), 578 MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event. 579 }; 580 581 DeterministicSocketData data(reads, arraysize(reads), 582 writes, arraysize(writes)); 583 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 584 http_session_ = 585 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 586 587 session_ = CreateInsecureSpdySession( 588 http_session_, spdy_session_key_, BoundNetLog()); 589 590 // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another 591 // WebSocketStream under test. 592 SpdyWebSocketStreamEventRecorder block_delegate((CompletionCallback())); 593 594 scoped_ptr<SpdyWebSocketStream> block_stream( 595 new SpdyWebSocketStream(session_, &block_delegate)); 596 BoundNetLog block_net_log; 597 GURL block_url("ws://example.com/block"); 598 ASSERT_EQ(OK, 599 block_stream->InitializeStream(block_url, HIGHEST, block_net_log)); 600 601 data.RunFor(1); 602 603 // Create a WebSocketStream under test. 604 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); 605 delegate.SetOnCreated( 606 base::Bind(&SpdyWebSocketStreamTest::DoSync, 607 base::Unretained(this))); 608 delegate.SetOnReceivedHeader( 609 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame, 610 base::Unretained(this))); 611 delegate.SetOnReceivedData( 612 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame, 613 base::Unretained(this))); 614 615 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate)); 616 BoundNetLog net_log; 617 GURL url("ws://example.com/echo"); 618 ASSERT_EQ(ERR_IO_PENDING, websocket_stream_->InitializeStream( 619 url, HIGHEST, net_log)); 620 621 // Delete the fist stream to allow create the second stream. 622 block_stream.reset(); 623 ASSERT_EQ(OK, sync_callback_.WaitForResult()); 624 625 SendRequest(); 626 627 data.RunFor(8); 628 completion_callback_.WaitForResult(); 629 630 websocket_stream_.reset(); 631 632 const std::vector<SpdyWebSocketStreamEvent>& block_events = 633 block_delegate.GetSeenEvents(); 634 ASSERT_EQ(0U, block_events.size()); 635 636 const std::vector<SpdyWebSocketStreamEvent>& events = 637 delegate.GetSeenEvents(); 638 ASSERT_EQ(8U, events.size()); 639 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CREATED, 640 events[0].event_type); 641 EXPECT_EQ(0, events[0].result); 642 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS, 643 events[1].event_type); 644 EXPECT_EQ(OK, events[1].result); 645 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER, 646 events[2].event_type); 647 EXPECT_EQ(OK, events[2].result); 648 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 649 events[3].event_type); 650 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result); 651 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 652 events[4].event_type); 653 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[4].result); 654 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA, 655 events[5].event_type); 656 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result); 657 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA, 658 events[6].event_type); 659 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[6].result); 660 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, 661 events[7].event_type); 662 EXPECT_EQ(OK, events[7].result); 663 664 // EOF close SPDY session. 665 EXPECT_FALSE( 666 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); 667 EXPECT_TRUE(data.at_read_eof()); 668 EXPECT_TRUE(data.at_write_eof()); 669 } 670 671 } // namespace net 672