Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: net/spdy/spdy_websocket_stream_unittest.cc

Issue 723343002: Update from https://crrev.com/304121 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_websocket_stream.cc ('k') | net/spdy/spdy_websocket_test_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 ~SpdyWebSocketStreamEventRecorder() override {}
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 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 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 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 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 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 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 void SetUp() override {
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 void TearDown() override { base::MessageLoop::current()->RunUntilIdle(); }
212
213 void Prepare(SpdyStreamId stream_id) {
214 stream_id_ = stream_id;
215
216 request_frame_.reset(spdy_util_.ConstructSpdyWebSocketSynStream(
217 stream_id_,
218 "/echo",
219 "example.com",
220 "http://example.com/wsdemo"));
221
222 response_frame_.reset(
223 spdy_util_.ConstructSpdyWebSocketSynReply(stream_id_));
224
225 message_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
226 kMessageFrame,
227 kMessageFrameLength,
228 stream_id_,
229 false));
230
231 closing_frame_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
232 kClosingFrame,
233 kClosingFrameLength,
234 stream_id_,
235 false));
236
237 closing_frame_fin_.reset(spdy_util_.ConstructSpdyWebSocketDataFrame(
238 kClosingFrame,
239 kClosingFrameLength,
240 stream_id_,
241 true));
242 }
243
244 void InitSession(MockRead* reads, size_t reads_count,
245 MockWrite* writes, size_t writes_count) {
246 data_.reset(new OrderedSocketData(reads, reads_count,
247 writes, writes_count));
248 session_deps_.socket_factory->AddSocketDataProvider(data_.get());
249 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
250 session_ = CreateInsecureSpdySession(
251 http_session_, spdy_session_key_, BoundNetLog());
252 }
253
254 void SendRequest() {
255 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
256 spdy_util_.SetHeader("path", "/echo", headers.get());
257 spdy_util_.SetHeader("host", "example.com", headers.get());
258 spdy_util_.SetHeader("version", "WebSocket/13", headers.get());
259 spdy_util_.SetHeader("scheme", "ws", headers.get());
260 spdy_util_.SetHeader("origin", "http://example.com/wsdemo", headers.get());
261 websocket_stream_->SendRequest(headers.Pass());
262 }
263
264 SpdyWebSocketTestUtil spdy_util_;
265 SpdySettingsIds spdy_settings_id_to_set_;
266 SpdySettingsFlags spdy_settings_flags_to_set_;
267 uint32 spdy_settings_value_to_set_;
268 SettingsMap spdy_settings_to_send_;
269 SpdySessionDependencies session_deps_;
270 scoped_ptr<OrderedSocketData> data_;
271 scoped_refptr<HttpNetworkSession> http_session_;
272 base::WeakPtr<SpdySession> session_;
273 scoped_ptr<SpdyWebSocketStream> websocket_stream_;
274 SpdyStreamId stream_id_;
275 SpdyStreamId created_stream_id_;
276 scoped_ptr<SpdyFrame> request_frame_;
277 scoped_ptr<SpdyFrame> response_frame_;
278 scoped_ptr<SpdyFrame> message_frame_;
279 scoped_ptr<SpdyFrame> closing_frame_;
280 scoped_ptr<SpdyFrame> closing_frame_fin_;
281 HostPortPair host_port_pair_;
282 SpdySessionKey spdy_session_key_;
283 TestCompletionCallback completion_callback_;
284 TestCompletionCallback sync_callback_;
285
286 static const char kMessageFrame[];
287 static const char kClosingFrame[];
288 static const size_t kMessageFrameLength;
289 static const size_t kClosingFrameLength;
290 };
291
292 INSTANTIATE_TEST_CASE_P(
293 NextProto,
294 SpdyWebSocketStreamTest,
295 testing::Values(kProtoDeprecatedSPDY2,
296 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
297
298 // TODO(toyoshim): Replace old framing data to new one, then use HEADERS and
299 // data frames.
300 const char SpdyWebSocketStreamTest::kMessageFrame[] = "\x81\x05hello";
301 const char SpdyWebSocketStreamTest::kClosingFrame[] = "\x88\0";
302 const size_t SpdyWebSocketStreamTest::kMessageFrameLength =
303 arraysize(SpdyWebSocketStreamTest::kMessageFrame) - 1;
304 const size_t SpdyWebSocketStreamTest::kClosingFrameLength =
305 arraysize(SpdyWebSocketStreamTest::kClosingFrame) - 1;
306
307 TEST_P(SpdyWebSocketStreamTest, Basic) {
308 Prepare(1);
309 MockWrite writes[] = {
310 CreateMockWrite(*request_frame_.get(), 1),
311 CreateMockWrite(*message_frame_.get(), 3),
312 CreateMockWrite(*closing_frame_.get(), 5)
313 };
314
315 MockRead reads[] = {
316 CreateMockRead(*response_frame_.get(), 2),
317 CreateMockRead(*message_frame_.get(), 4),
318 // Skip sequence 6 to notify closing has been sent.
319 CreateMockRead(*closing_frame_.get(), 7),
320 MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event.
321 };
322
323 InitSession(reads, arraysize(reads), writes, arraysize(writes));
324
325 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
326 delegate.SetOnReceivedHeader(
327 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
328 base::Unretained(this)));
329 delegate.SetOnReceivedData(
330 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
331 base::Unretained(this)));
332
333 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
334
335 BoundNetLog net_log;
336 GURL url("ws://example.com/echo");
337 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
338
339 ASSERT_TRUE(websocket_stream_->stream_.get());
340
341 SendRequest();
342
343 completion_callback_.WaitForResult();
344
345 EXPECT_EQ(stream_id_, created_stream_id_);
346
347 websocket_stream_.reset();
348
349 const std::vector<SpdyWebSocketStreamEvent>& events =
350 delegate.GetSeenEvents();
351 ASSERT_EQ(7U, events.size());
352
353 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
354 events[0].event_type);
355 EXPECT_EQ(OK, events[0].result);
356 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
357 events[1].event_type);
358 EXPECT_EQ(OK, events[1].result);
359 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
360 events[2].event_type);
361 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
362 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
363 events[3].event_type);
364 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
365 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
366 events[4].event_type);
367 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[4].result);
368 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
369 events[5].event_type);
370 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
371 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
372 events[6].event_type);
373 EXPECT_EQ(OK, events[6].result);
374
375 // EOF close SPDY session.
376 EXPECT_FALSE(
377 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
378 EXPECT_TRUE(data()->at_read_eof());
379 EXPECT_TRUE(data()->at_write_eof());
380 }
381
382 // A SPDY websocket may still send it's close frame after
383 // recieving a close with SPDY stream FIN.
384 TEST_P(SpdyWebSocketStreamTest, RemoteCloseWithFin) {
385 Prepare(1);
386 MockWrite writes[] = {
387 CreateMockWrite(*request_frame_.get(), 1),
388 CreateMockWrite(*closing_frame_.get(), 4),
389 };
390 MockRead reads[] = {
391 CreateMockRead(*response_frame_.get(), 2),
392 CreateMockRead(*closing_frame_fin_.get(), 3),
393 MockRead(SYNCHRONOUS, 0, 5) // EOF cause OnCloseSpdyStream event.
394 };
395 InitSession(reads, arraysize(reads), writes, arraysize(writes));
396
397 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
398 delegate.SetOnReceivedData(
399 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
400 base::Unretained(this)));
401
402 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
403 BoundNetLog net_log;
404 GURL url("ws://example.com/echo");
405 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
406
407 SendRequest();
408 completion_callback_.WaitForResult();
409 websocket_stream_.reset();
410
411 const std::vector<SpdyWebSocketStreamEvent>& events =
412 delegate.GetSeenEvents();
413 EXPECT_EQ(5U, events.size());
414
415 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
416 events[0].event_type);
417 EXPECT_EQ(OK, events[0].result);
418 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
419 events[1].event_type);
420 EXPECT_EQ(OK, events[1].result);
421 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
422 events[2].event_type);
423 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[2].result);
424 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
425 events[3].event_type);
426 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[3].result);
427 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
428 events[4].event_type);
429 EXPECT_EQ(OK, events[4].result);
430
431 // EOF closes SPDY session.
432 EXPECT_FALSE(
433 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
434 EXPECT_TRUE(data()->at_read_eof());
435 EXPECT_TRUE(data()->at_write_eof());
436 }
437
438 TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) {
439 Prepare(1);
440 MockWrite writes[] = {
441 CreateMockWrite(*request_frame_.get(), 1),
442 CreateMockWrite(*message_frame_.get(), 3)
443 };
444
445 MockRead reads[] = {
446 CreateMockRead(*response_frame_.get(), 2),
447 CreateMockRead(*message_frame_.get(), 4),
448 MockRead(ASYNC, ERR_IO_PENDING, 5)
449 };
450
451 InitSession(reads, arraysize(reads), writes, arraysize(writes));
452
453 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
454 delegate.SetOnReceivedHeader(
455 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
456 base::Unretained(this)));
457 delegate.SetOnReceivedData(
458 base::Bind(&SpdyWebSocketStreamTest::DoSync,
459 base::Unretained(this)));
460
461 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
462
463 BoundNetLog net_log;
464 GURL url("ws://example.com/echo");
465 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
466
467 SendRequest();
468
469 sync_callback_.WaitForResult();
470
471 // WebSocketStream destruction remove its SPDY stream from the session.
472 EXPECT_TRUE(session_->IsStreamActive(stream_id_));
473 websocket_stream_.reset();
474 EXPECT_FALSE(session_->IsStreamActive(stream_id_));
475
476 const std::vector<SpdyWebSocketStreamEvent>& events =
477 delegate.GetSeenEvents();
478 ASSERT_GE(4U, events.size());
479
480 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
481 events[0].event_type);
482 EXPECT_EQ(OK, events[0].result);
483 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
484 events[1].event_type);
485 EXPECT_EQ(OK, events[1].result);
486 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
487 events[2].event_type);
488 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
489 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
490 events[3].event_type);
491 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
492
493 EXPECT_TRUE(
494 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
495 EXPECT_TRUE(data()->at_read_eof());
496 EXPECT_TRUE(data()->at_write_eof());
497 }
498
499 TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) {
500 Prepare(1);
501 MockWrite writes[] = {
502 CreateMockWrite(*request_frame_.get(), 1),
503 CreateMockWrite(*message_frame_.get(), 3),
504 CreateMockWrite(*closing_frame_.get(), 5)
505 };
506
507 MockRead reads[] = {
508 CreateMockRead(*response_frame_.get(), 2),
509 CreateMockRead(*message_frame_.get(), 4),
510 MockRead(ASYNC, ERR_IO_PENDING, 6)
511 };
512
513 InitSession(reads, arraysize(reads), writes, arraysize(writes));
514
515 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
516 delegate.SetOnReceivedHeader(
517 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
518 base::Unretained(this)));
519 delegate.SetOnReceivedData(
520 base::Bind(&SpdyWebSocketStreamTest::DoClose,
521 base::Unretained(this)));
522
523 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
524
525 BoundNetLog net_log;
526 GURL url("ws://example.com/echo");
527 ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));
528
529 SendRequest();
530
531 completion_callback_.WaitForResult();
532
533 // SPDY stream has already been removed from the session by Close().
534 EXPECT_FALSE(session_->IsStreamActive(stream_id_));
535 websocket_stream_.reset();
536
537 const std::vector<SpdyWebSocketStreamEvent>& events =
538 delegate.GetSeenEvents();
539 ASSERT_EQ(5U, events.size());
540
541 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
542 events[0].event_type);
543 EXPECT_EQ(OK, events[0].result);
544 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
545 events[1].event_type);
546 EXPECT_EQ(OK, events[1].result);
547 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
548 events[2].event_type);
549 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
550 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
551 events[3].event_type);
552 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
553 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, events[4].event_type);
554
555 EXPECT_TRUE(
556 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
557 }
558
559 TEST_P(SpdyWebSocketStreamTest, IOPending) {
560 Prepare(1);
561 scoped_ptr<SpdyFrame> settings_frame(
562 spdy_util_.ConstructSpdySettings(spdy_settings_to_send_));
563 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
564 MockWrite writes[] = {
565 CreateMockWrite(*settings_ack, 1),
566 CreateMockWrite(*request_frame_.get(), 2),
567 CreateMockWrite(*message_frame_.get(), 4),
568 CreateMockWrite(*closing_frame_.get(), 6)
569 };
570
571 MockRead reads[] = {
572 CreateMockRead(*settings_frame.get(), 0),
573 CreateMockRead(*response_frame_.get(), 3),
574 CreateMockRead(*message_frame_.get(), 5),
575 CreateMockRead(*closing_frame_.get(), 7),
576 MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event.
577 };
578
579 DeterministicSocketData data(reads, arraysize(reads),
580 writes, arraysize(writes));
581 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
582 http_session_ =
583 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
584
585 session_ = CreateInsecureSpdySession(
586 http_session_, spdy_session_key_, BoundNetLog());
587
588 // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another
589 // WebSocketStream under test.
590 SpdyWebSocketStreamEventRecorder block_delegate((CompletionCallback()));
591
592 scoped_ptr<SpdyWebSocketStream> block_stream(
593 new SpdyWebSocketStream(session_, &block_delegate));
594 BoundNetLog block_net_log;
595 GURL block_url("ws://example.com/block");
596 ASSERT_EQ(OK,
597 block_stream->InitializeStream(block_url, HIGHEST, block_net_log));
598
599 data.RunFor(1);
600
601 // Create a WebSocketStream under test.
602 SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
603 delegate.SetOnCreated(
604 base::Bind(&SpdyWebSocketStreamTest::DoSync,
605 base::Unretained(this)));
606 delegate.SetOnReceivedHeader(
607 base::Bind(&SpdyWebSocketStreamTest::DoSendHelloFrame,
608 base::Unretained(this)));
609 delegate.SetOnReceivedData(
610 base::Bind(&SpdyWebSocketStreamTest::DoSendClosingFrame,
611 base::Unretained(this)));
612
613 websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
614 BoundNetLog net_log;
615 GURL url("ws://example.com/echo");
616 ASSERT_EQ(ERR_IO_PENDING, websocket_stream_->InitializeStream(
617 url, HIGHEST, net_log));
618
619 // Delete the fist stream to allow create the second stream.
620 block_stream.reset();
621 ASSERT_EQ(OK, sync_callback_.WaitForResult());
622
623 SendRequest();
624
625 data.RunFor(8);
626 completion_callback_.WaitForResult();
627
628 websocket_stream_.reset();
629
630 const std::vector<SpdyWebSocketStreamEvent>& block_events =
631 block_delegate.GetSeenEvents();
632 ASSERT_EQ(0U, block_events.size());
633
634 const std::vector<SpdyWebSocketStreamEvent>& events =
635 delegate.GetSeenEvents();
636 ASSERT_EQ(8U, events.size());
637 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CREATED,
638 events[0].event_type);
639 EXPECT_EQ(0, events[0].result);
640 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
641 events[1].event_type);
642 EXPECT_EQ(OK, events[1].result);
643 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
644 events[2].event_type);
645 EXPECT_EQ(OK, events[2].result);
646 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
647 events[3].event_type);
648 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
649 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
650 events[4].event_type);
651 EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[4].result);
652 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
653 events[5].event_type);
654 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
655 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
656 events[6].event_type);
657 EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[6].result);
658 EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
659 events[7].event_type);
660 EXPECT_EQ(OK, events[7].result);
661
662 // EOF close SPDY session.
663 EXPECT_FALSE(
664 HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_));
665 EXPECT_TRUE(data.at_read_eof());
666 EXPECT_TRUE(data.at_write_eof());
667 }
668
669 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_websocket_stream.cc ('k') | net/spdy/spdy_websocket_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698