Home | History | Annotate | Download | only in spdy
      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