1813947dc1925737d84a190f143e88bdc36bbfeb
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_websocket_stream_unittest.cc
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                                        kPrivacyModeDisabled);
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, kProtoSPDY4a2,
299                     kProtoHTTP2Draft04));
300
301 // TODO(toyoshim): Replace old framing data to new one, then use HEADERS and
302 // data frames.
303 const char SpdyWebSocketStreamTest::kMessageFrame[] = "\x81\x05hello";
304 const char SpdyWebSocketStreamTest::kClosingFrame[] = "\x88\0";
305 const size_t SpdyWebSocketStreamTest::kMessageFrameLength =
306     arraysize(SpdyWebSocketStreamTest::kMessageFrame) - 1;
307 const size_t SpdyWebSocketStreamTest::kClosingFrameLength =
308     arraysize(SpdyWebSocketStreamTest::kClosingFrame) - 1;
309
310 TEST_P(SpdyWebSocketStreamTest, Basic) {
311   Prepare(1);
312   MockWrite writes[] = {
313     CreateMockWrite(*request_frame_.get(), 1),
314     CreateMockWrite(*message_frame_.get(), 3),
315     CreateMockWrite(*closing_frame_.get(), 5)
316   };
317
318   MockRead reads[] = {
319     CreateMockRead(*response_frame_.get(), 2),
320     CreateMockRead(*message_frame_.get(), 4),
321     // Skip sequence 6 to notify closing has been sent.
322     CreateMockRead(*closing_frame_.get(), 7),
323     MockRead(SYNCHRONOUS, 0, 8)  // EOF cause OnCloseSpdyStream event.
324   };
325
326   InitSession(reads, arraysize(reads), writes, arraysize(writes));
327
328   SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
329   delegate.SetOnReceivedHeader(
330       base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
331                  base::Unretained(this)));
332   delegate.SetOnReceivedData(
333       base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
334                  base::Unretained(this)));
335
336   websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
337
338   BoundNetLog net_log;
339   GURL url("ws://example.com/echo");
340   ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
341
342   ASSERT_TRUE(websocket_stream_->stream_.get());
343
344   SendRequest();
345
346   completion_callback_.WaitForResult();
347
348   EXPECT_EQ(stream_id_, created_stream_id_);
349
350   websocket_stream_.reset();
351
352   const std::vector<SpdyWebSocketStreamEvent>& events =
353       delegate.GetSeenEvents();
354   ASSERT_EQ(7U, events.size());
355
356   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
357             events[0].event_type);
358   EXPECT_EQ(OK, events[0].result);
359   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
360             events[1].event_type);
361   EXPECT_EQ(OK, events[1].result);
362   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
363             events[2].event_type);
364   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
365   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
366             events[3].event_type);
367   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
368   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
369             events[4].event_type);
370   EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[4].result);
371   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
372             events[5].event_type);
373   EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
374   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
375             events[6].event_type);
376   EXPECT_EQ(OK, events[6].result);
377
378   // EOF close SPDY session.
379   EXPECT_FALSE(
380       HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
381   EXPECT_TRUE(data()->at_read_eof());
382   EXPECT_TRUE(data()->at_write_eof());
383 }
384
385 // A SPDY websocket may still send it's close frame after
386 // recieving a close with SPDY stream FIN.
387 TEST_P(SpdyWebSocketStreamTest, RemoteCloseWithFin) {
388   Prepare(1);
389   MockWrite writes[] = {
390     CreateMockWrite(*request_frame_.get(), 1),
391     CreateMockWrite(*closing_frame_.get(), 4),
392   };
393   MockRead reads[] = {
394     CreateMockRead(*response_frame_.get(), 2),
395     CreateMockRead(*closing_frame_fin_.get(), 3),
396     MockRead(SYNCHRONOUS, 0, 5)  // EOF cause OnCloseSpdyStream event.
397   };
398   InitSession(reads, arraysize(reads), writes, arraysize(writes));
399
400   SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
401   delegate.SetOnReceivedData(
402       base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
403                  base::Unretained(this)));
404
405   websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
406   BoundNetLog net_log;
407   GURL url("ws://example.com/echo");
408   ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
409
410   SendRequest();
411   completion_callback_.WaitForResult();
412   websocket_stream_.reset();
413
414   const std::vector<SpdyWebSocketStreamEvent>& events =
415       delegate.GetSeenEvents();
416   EXPECT_EQ(5U, events.size());
417
418   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
419             events[0].event_type);
420   EXPECT_EQ(OK, events[0].result);
421   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
422             events[1].event_type);
423   EXPECT_EQ(OK, events[1].result);
424   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
425             events[2].event_type);
426   EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[2].result);
427   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
428             events[3].event_type);
429   EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[3].result);
430   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
431             events[4].event_type);
432   EXPECT_EQ(OK, events[4].result);
433
434   // EOF closes SPDY session.
435   EXPECT_FALSE(
436       HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
437   EXPECT_TRUE(data()->at_read_eof());
438   EXPECT_TRUE(data()->at_write_eof());
439 }
440
441 TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) {
442   Prepare(1);
443   MockWrite writes[] = {
444     CreateMockWrite(*request_frame_.get(), 1),
445     CreateMockWrite(*message_frame_.get(), 3)
446   };
447
448   MockRead reads[] = {
449     CreateMockRead(*response_frame_.get(), 2),
450     CreateMockRead(*message_frame_.get(), 4),
451     MockRead(ASYNC, ERR_IO_PENDING, 5)
452   };
453
454   InitSession(reads, arraysize(reads), writes, arraysize(writes));
455
456   SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
457   delegate.SetOnReceivedHeader(
458       base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
459                  base::Unretained(this)));
460   delegate.SetOnReceivedData(
461       base::Bind(&SpdyWebSocketStreamTest::DoSync,
462                  base::Unretained(this)));
463
464   websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
465
466   BoundNetLog net_log;
467   GURL url("ws://example.com/echo");
468   ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
469
470   SendRequest();
471
472   sync_callback_.WaitForResult();
473
474   // WebSocketStream destruction remove its SPDY stream from the session.
475   EXPECT_TRUE(session_->IsStreamActive(stream_id_));
476   websocket_stream_.reset();
477   EXPECT_FALSE(session_->IsStreamActive(stream_id_));
478
479   const std::vector<SpdyWebSocketStreamEvent>& events =
480       delegate.GetSeenEvents();
481   ASSERT_GE(4U, events.size());
482
483   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
484             events[0].event_type);
485   EXPECT_EQ(OK, events[0].result);
486   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
487             events[1].event_type);
488   EXPECT_EQ(OK, events[1].result);
489   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
490             events[2].event_type);
491   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
492   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
493             events[3].event_type);
494   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
495
496   EXPECT_TRUE(
497       HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
498   EXPECT_TRUE(data()->at_read_eof());
499   EXPECT_TRUE(data()->at_write_eof());
500 }
501
502 TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) {
503   Prepare(1);
504   MockWrite writes[] = {
505     CreateMockWrite(*request_frame_.get(), 1),
506     CreateMockWrite(*message_frame_.get(), 3),
507     CreateMockWrite(*closing_frame_.get(), 5)
508   };
509
510   MockRead reads[] = {
511     CreateMockRead(*response_frame_.get(), 2),
512     CreateMockRead(*message_frame_.get(), 4),
513     MockRead(ASYNC, ERR_IO_PENDING, 6)
514   };
515
516   InitSession(reads, arraysize(reads), writes, arraysize(writes));
517
518   SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
519   delegate.SetOnReceivedHeader(
520       base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
521                  base::Unretained(this)));
522   delegate.SetOnReceivedData(
523       base::Bind(&SpdyWebSocketStreamTest::DoClose,
524                  base::Unretained(this)));
525
526   websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
527
528   BoundNetLog net_log;
529   GURL url("ws://example.com/echo");
530   ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
531
532   SendRequest();
533
534   completion_callback_.WaitForResult();
535
536   // SPDY stream has already been removed from the session by Close().
537   EXPECT_FALSE(session_->IsStreamActive(stream_id_));
538   websocket_stream_.reset();
539
540   const std::vector<SpdyWebSocketStreamEvent>& events =
541       delegate.GetSeenEvents();
542   ASSERT_EQ(5U, events.size());
543
544   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
545             events[0].event_type);
546   EXPECT_EQ(OK, events[0].result);
547   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
548             events[1].event_type);
549   EXPECT_EQ(OK, events[1].result);
550   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
551             events[2].event_type);
552   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
553   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
554             events[3].event_type);
555   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
556   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, events[4].event_type);
557
558   EXPECT_TRUE(
559       HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
560 }
561
562 TEST_P(SpdyWebSocketStreamTest, IOPending) {
563   Prepare(1);
564   scoped_ptr<SpdyFrame> settings_frame(
565       spdy_util_.ConstructSpdySettings(spdy_settings_to_send_));
566   MockWrite writes[] = {
567     CreateMockWrite(*request_frame_.get(), 1),
568     CreateMockWrite(*message_frame_.get(), 3),
569     CreateMockWrite(*closing_frame_.get(), 5)
570   };
571
572   MockRead reads[] = {
573     CreateMockRead(*settings_frame.get(), 0),
574     CreateMockRead(*response_frame_.get(), 2),
575     CreateMockRead(*message_frame_.get(), 4),
576     CreateMockRead(*closing_frame_.get(), 6),
577     MockRead(SYNCHRONOUS, 0, 7)  // EOF cause OnCloseSpdyStream event.
578   };
579
580   DeterministicSocketData data(reads, arraysize(reads),
581                                writes, arraysize(writes));
582   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
583   http_session_ =
584       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
585
586   session_ = CreateInsecureSpdySession(
587       http_session_, spdy_session_key_, BoundNetLog());
588
589   // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another
590   // WebSocketStream under test.
591   SpdyWebSocketStreamEventRecorder block_delegate((CompletionCallback()));
592
593   scoped_ptr<SpdyWebSocketStream> block_stream(
594       new SpdyWebSocketStream(session_, &block_delegate));
595   BoundNetLog block_net_log;
596   GURL block_url("ws://example.com/block");
597   ASSERT_EQ(OK,
598             block_stream->InitializeStream(block_url, HIGHEST, block_net_log));
599
600   data.RunFor(1);
601
602   // Create a WebSocketStream under test.
603   SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
604   delegate.SetOnCreated(
605       base::Bind(&SpdyWebSocketStreamTest::DoSync,
606                  base::Unretained(this)));
607   delegate.SetOnReceivedHeader(
608       base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
609                  base::Unretained(this)));
610   delegate.SetOnReceivedData(
611       base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
612                  base::Unretained(this)));
613
614   websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
615   BoundNetLog net_log;
616   GURL url("ws://example.com/echo");
617   ASSERT_EQ(ERR_IO_PENDING, websocket_stream_->InitializeStream(
618       url, HIGHEST, net_log));
619
620   // Delete the fist stream to allow create the second stream.
621   block_stream.reset();
622   ASSERT_EQ(OK, sync_callback_.WaitForResult());
623
624   SendRequest();
625
626   data.RunFor(7);
627   completion_callback_.WaitForResult();
628
629   websocket_stream_.reset();
630
631   const std::vector<SpdyWebSocketStreamEvent>& block_events =
632       block_delegate.GetSeenEvents();
633   ASSERT_EQ(0U, block_events.size());
634
635   const std::vector<SpdyWebSocketStreamEvent>& events =
636       delegate.GetSeenEvents();
637   ASSERT_EQ(8U, events.size());
638   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CREATED,
639             events[0].event_type);
640   EXPECT_EQ(0, events[0].result);
641   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
642             events[1].event_type);
643   EXPECT_EQ(OK, events[1].result);
644   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
645             events[2].event_type);
646   EXPECT_EQ(OK, events[2].result);
647   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
648             events[3].event_type);
649   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
650   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
651             events[4].event_type);
652   EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[4].result);
653   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
654             events[5].event_type);
655   EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
656   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
657             events[6].event_type);
658   EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[6].result);
659   EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
660             events[7].event_type);
661   EXPECT_EQ(OK, events[7].result);
662
663   // EOF close SPDY session.
664   EXPECT_FALSE(
665       HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
666   EXPECT_TRUE(data.at_read_eof());
667   EXPECT_TRUE(data.at_write_eof());
668 }
669
670 }  // namespace net