Revert of Update WV test license server config to use portable sdk server. (https...
[chromium-blink-merge.git] / net / spdy / spdy_websocket_stream_unittest.cc
blob1813947dc1925737d84a190f143e88bdc36bbfeb
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.
5 #include "net/spdy/spdy_websocket_stream.h"
7 #include <string>
8 #include <vector>
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"
22 namespace net {
24 namespace {
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,
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) {}
44 EventType event_type;
45 SpdyHeaderBlock headers;
46 int result;
47 std::string data;
50 class SpdyWebSocketStreamEventRecorder : public SpdyWebSocketStream::Delegate {
51 public:
52 explicit SpdyWebSocketStreamEventRecorder(const CompletionCallback& callback)
53 : callback_(callback) {}
54 virtual ~SpdyWebSocketStreamEventRecorder() {}
56 typedef base::Callback<void(SpdyWebSocketStreamEvent*)> StreamEventCallback;
58 void SetOnCreated(const StreamEventCallback& callback) {
59 on_created_ = callback;
61 void SetOnSentHeaders(const StreamEventCallback& callback) {
62 on_sent_headers_ = callback;
64 void SetOnReceivedHeader(const StreamEventCallback& callback) {
65 on_received_header_ = callback;
67 void SetOnSentData(const StreamEventCallback& callback) {
68 on_sent_data_ = callback;
70 void SetOnReceivedData(const StreamEventCallback& callback) {
71 on_received_data_ = callback;
73 void SetOnClose(const StreamEventCallback& callback) {
74 on_close_ = callback;
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());
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());
95 virtual void OnSpdyResponseHeadersUpdated(
96 const SpdyHeaderBlock& response_headers) OVERRIDE {
97 events_.push_back(
98 SpdyWebSocketStreamEvent(
99 SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
100 response_headers,
102 std::string()));
103 if (!on_received_header_.is_null())
104 on_received_header_.Run(&events_.back());
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());
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);
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());
132 virtual void OnCloseSpdyStream() OVERRIDE {
133 events_.push_back(
134 SpdyWebSocketStreamEvent(
135 SpdyWebSocketStreamEvent::EVENT_CLOSE,
136 SpdyHeaderBlock(),
138 std::string()));
139 if (!on_close_.is_null())
140 on_close_.Run(&events_.back());
141 if (!callback_.is_null())
142 callback_.Run(OK);
145 const std::vector<SpdyWebSocketStreamEvent>& GetSeenEvents() const {
146 return events_;
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_;
159 DISALLOW_COPY_AND_ASSIGN(SpdyWebSocketStreamEventRecorder);
162 } // namespace
164 class SpdyWebSocketStreamTest
165 : public ::testing::Test,
166 public ::testing::WithParamInterface<NextProto> {
167 public:
168 OrderedSocketData* data() { return data_.get(); }
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);
176 void DoSendClosingFrame(SpdyWebSocketStreamEvent* event) {
177 websocket_stream_->SendData(kClosingFrame, kClosingFrameLength);
180 void DoClose(SpdyWebSocketStreamEvent* event) {
181 websocket_stream_->Close();
184 void DoSync(SpdyWebSocketStreamEvent* event) {
185 sync_callback_.callback().Run(OK);
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() {}
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);
206 spdy_settings_to_send_[spdy_settings_id_to_set_] =
207 SettingsFlagsAndValue(
208 SETTINGS_FLAG_PERSISTED, spdy_settings_value_to_set_);
211 virtual void TearDown() {
212 base::MessageLoop::current()->RunUntilIdle();
215 void Prepare(SpdyStreamId stream_id) {
216 stream_id_ = stream_id;
218 request_frame_.reset(spdy_util_.ConstructSpdyWebSocketSynStream(
219 stream_id_,
220 "/echo",
221 "example.com",
222 "http://example.com/wsdemo"));
224 response_frame_.reset(
225 spdy_util_.ConstructSpdyWebSocketSynReply(stream_id_));
227 message_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
228 kMessageFrame,
229 kMessageFrameLength,
230 stream_id_,
231 false));
233 closing_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
234 kClosingFrame,
235 kClosingFrameLength,
236 stream_id_,
237 false));
239 closing_frame_fin_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
240 kClosingFrame,
241 kClosingFrameLength,
242 stream_id_,
243 true));
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());
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());
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_;
288 static const char kMessageFrame[];
289 static const char kClosingFrame[];
290 static const size_t kMessageFrameLength;
291 static const size_t kClosingFrameLength;
294 INSTANTIATE_TEST_CASE_P(
295 NextProto,
296 SpdyWebSocketStreamTest,
297 testing::Values(kProtoDeprecatedSPDY2,
298 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
299 kProtoHTTP2Draft04));
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;
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)
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.
326 InitSession(reads, arraysize(reads), writes, arraysize(writes));
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)));
336 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
338 BoundNetLog net_log;
339 GURL url("ws://example.com/echo");
340 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
342 ASSERT_TRUE(websocket_stream_->stream_.get());
344 SendRequest();
346 completion_callback_.WaitForResult();
348 EXPECT_EQ(stream_id_, created_stream_id_);
350 websocket_stream_.reset();
352 const std::vector<SpdyWebSocketStreamEvent>& events =
353 delegate.GetSeenEvents();
354 ASSERT_EQ(7U, events.size());
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);
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());
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),
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.
398 InitSession(reads, arraysize(reads), writes, arraysize(writes));
400 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
401 delegate.SetOnReceivedData(
402 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
403 base::Unretained(this)));
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));
410 SendRequest();
411 completion_callback_.WaitForResult();
412 websocket_stream_.reset();
414 const std::vector<SpdyWebSocketStreamEvent>& events =
415 delegate.GetSeenEvents();
416 EXPECT_EQ(5U, events.size());
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);
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());
441 TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) {
442 Prepare(1);
443 MockWrite writes[] = {
444 CreateMockWrite(*request_frame_.get(), 1),
445 CreateMockWrite(*message_frame_.get(), 3)
448 MockRead reads[] = {
449 CreateMockRead(*response_frame_.get(), 2),
450 CreateMockRead(*message_frame_.get(), 4),
451 MockRead(ASYNC, ERR_IO_PENDING, 5)
454 InitSession(reads, arraysize(reads), writes, arraysize(writes));
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)));
464 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
466 BoundNetLog net_log;
467 GURL url("ws://example.com/echo");
468 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
470 SendRequest();
472 sync_callback_.WaitForResult();
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_));
479 const std::vector<SpdyWebSocketStreamEvent>& events =
480 delegate.GetSeenEvents();
481 ASSERT_GE(4U, events.size());
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);
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());
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)
510 MockRead reads[] = {
511 CreateMockRead(*response_frame_.get(), 2),
512 CreateMockRead(*message_frame_.get(), 4),
513 MockRead(ASYNC, ERR_IO_PENDING, 6)
516 InitSession(reads, arraysize(reads), writes, arraysize(writes));
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)));
526 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
528 BoundNetLog net_log;
529 GURL url("ws://example.com/echo");
530 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
532 SendRequest();
534 completion_callback_.WaitForResult();
536 // SPDY stream has already been removed from the session by Close().
537 EXPECT_FALSE(session_->IsStreamActive(stream_id_));
538 websocket_stream_.reset();
540 const std::vector<SpdyWebSocketStreamEvent>& events =
541 delegate.GetSeenEvents();
542 ASSERT_EQ(5U, events.size());
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);
558 EXPECT_TRUE(
559 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
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)
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.
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_);
586 session_ = CreateInsecureSpdySession(
587 http_session_, spdy_session_key_, BoundNetLog());
589 // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another
590 // WebSocketStream under test.
591 SpdyWebSocketStreamEventRecorder block_delegate((CompletionCallback()));
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));
600 data.RunFor(1);
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)));
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));
620 // Delete the fist stream to allow create the second stream.
621 block_stream.reset();
622 ASSERT_EQ(OK, sync_callback_.WaitForResult());
624 SendRequest();
626 data.RunFor(7);
627 completion_callback_.WaitForResult();
629 websocket_stream_.reset();
631 const std::vector<SpdyWebSocketStreamEvent>& block_events =
632 block_delegate.GetSeenEvents();
633 ASSERT_EQ(0U, block_events.size());
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);
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());
670 } // namespace net