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

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

Issue 17382012: [SPDY] Refactor SpdyStream's handling of response headers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More updates from rebase Created 7 years, 6 months 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 | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | net/spdy/spdy_websocket_stream.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cstddef> 5 #include <cstddef>
6 #include <string> 6 #include <string>
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey())); 199 delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
200 EXPECT_EQ(std::string(kPostBody, kPostBodyLength), 200 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
201 delegate.TakeReceivedData()); 201 delegate.TakeReceivedData());
202 EXPECT_TRUE(data.at_write_eof()); 202 EXPECT_TRUE(data.at_write_eof());
203 } 203 }
204 204
205 TEST_P(SpdyStreamTest, PushedStream) { 205 TEST_P(SpdyStreamTest, PushedStream) {
206 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 206 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
207 scoped_refptr<SpdySession> spdy_session(CreateSpdySession()); 207 scoped_refptr<SpdySession> spdy_session(CreateSpdySession());
208 208
209 MockRead reads[] = { 209 scoped_ptr<SpdyFrame> initial_window_update(
210 MockRead(ASYNC, 0, 0), // EOF 210 spdy_util_.ConstructSpdyWindowUpdate(
211 }; 211 kSessionFlowControlStreamId,
212 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
213 if (spdy_util_.protocol() >= kProtoSPDY31)
214 AddWrite(*initial_window_update);
212 215
213 OrderedSocketData data(reads, arraysize(reads), NULL, 0); 216 AddReadEOF();
217
218 OrderedSocketData data(GetReads(), GetNumReads(),
219 GetWrites(), GetNumWrites());
214 MockConnect connect_data(SYNCHRONOUS, OK); 220 MockConnect connect_data(SYNCHRONOUS, OK);
215 data.set_connect_data(connect_data); 221 data.set_connect_data(connect_data);
216 222
217 session_deps_.socket_factory->AddSocketDataProvider(&data); 223 session_deps_.socket_factory->AddSocketDataProvider(&data);
218 224
219 InitializeSpdySession(spdy_session, host_port_pair_); 225 InitializeSpdySession(spdy_session, host_port_pair_);
220 BoundNetLog net_log; 226 BoundNetLog net_log;
221 227
222 // Conjure up a stream. 228 // Conjure up a stream.
223 SpdyStream stream(SPDY_PUSH_STREAM, 229 SpdyStream stream(SPDY_PUSH_STREAM,
224 spdy_session.get(), 230 spdy_session.get(),
225 std::string(), 231 std::string(),
226 DEFAULT_PRIORITY, 232 DEFAULT_PRIORITY,
227 kSpdyStreamInitialWindowSize, 233 kSpdyStreamInitialWindowSize,
228 kSpdyStreamInitialWindowSize, 234 kSpdyStreamInitialWindowSize,
229 net_log); 235 net_log);
230 stream.set_stream_id(2); 236 stream.set_stream_id(2);
231 EXPECT_FALSE(stream.response_received());
232 EXPECT_FALSE(stream.HasUrl()); 237 EXPECT_FALSE(stream.HasUrl());
233 238
234 // Set a couple of headers. 239 // Set a couple of headers.
235 SpdyHeaderBlock response; 240 SpdyHeaderBlock response;
236 spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &response); 241 spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &response);
237 stream.OnResponseHeadersReceived(response); 242 stream.OnInitialResponseHeadersReceived(
243 response, base::Time::Now(), base::TimeTicks::Now());
238 244
239 // Send some basic headers. 245 // Send some basic headers.
240 SpdyHeaderBlock headers; 246 SpdyHeaderBlock headers;
241 response[spdy_util_.GetStatusKey()] = "200"; 247 headers[spdy_util_.GetStatusKey()] = "200";
242 response[spdy_util_.GetVersionKey()] = "OK"; 248 headers[spdy_util_.GetVersionKey()] = "OK";
243 stream.OnHeaders(headers); 249 stream.OnAdditionalResponseHeadersReceived(headers);
244 250
245 stream.set_response_received();
246 EXPECT_TRUE(stream.response_received());
247 EXPECT_TRUE(stream.HasUrl()); 251 EXPECT_TRUE(stream.HasUrl());
248 EXPECT_EQ(kStreamUrl, stream.GetUrl().spec()); 252 EXPECT_EQ(kStreamUrl, stream.GetUrl().spec());
249 253
254 StreamDelegateDoNothing delegate(stream.GetWeakPtr());
255 stream.SetDelegate(&delegate);
256
257 base::MessageLoop::current()->RunUntilIdle();
258
259 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
260
250 spdy_session->CloseSessionOnError( 261 spdy_session->CloseSessionOnError(
251 ERR_CONNECTION_CLOSED, true, "Closing session"); 262 ERR_CONNECTION_CLOSED, true, "Closing session");
252 } 263 }
253 264
254 TEST_P(SpdyStreamTest, StreamError) { 265 TEST_P(SpdyStreamTest, StreamError) {
255 GURL url(kStreamUrl); 266 GURL url(kStreamUrl);
256 267
257 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 268 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
258 269
259 scoped_ptr<SpdyFrame> initial_window_update( 270 scoped_ptr<SpdyFrame> initial_window_update(
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 492 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
482 493
483 EXPECT_TRUE(delegate.send_headers_completed()); 494 EXPECT_TRUE(delegate.send_headers_completed());
484 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); 495 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
485 EXPECT_EQ("HTTP/1.1", 496 EXPECT_EQ("HTTP/1.1",
486 delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey())); 497 delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
487 EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 498 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
488 EXPECT_TRUE(data.at_write_eof()); 499 EXPECT_TRUE(data.at_write_eof());
489 } 500 }
490 501
502 // Receiving a header with uppercase ASCII should result in a protocol
503 // error.
504 TEST_P(SpdyStreamTest, UpperCaseHeaders) {
505 GURL url(kStreamUrl);
506
507 session_ =
508 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
509
510 scoped_ptr<SpdyFrame> initial_window_update(
511 spdy_util_.ConstructSpdyWindowUpdate(
512 kSessionFlowControlStreamId,
513 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
514 if (spdy_util_.protocol() >= kProtoSPDY31)
515 AddWrite(*initial_window_update);
516
517 scoped_ptr<SpdyFrame> syn(
518 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
519 AddWrite(*syn);
520
521 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
522 scoped_ptr<SpdyFrame>
523 reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
524 AddRead(*reply);
525
526 scoped_ptr<SpdyFrame> rst(
527 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
528 AddWrite(*rst);
529
530 AddReadEOF();
531
532 DeterministicSocketData data(GetReads(), GetNumReads(),
533 GetWrites(), GetNumWrites());
534 MockConnect connect_data(SYNCHRONOUS, OK);
535 data.set_connect_data(connect_data);
536
537 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
538
539 scoped_refptr<SpdySession> session(CreateSpdySession());
540
541 InitializeSpdySession(session, host_port_pair_);
542
543 base::WeakPtr<SpdyStream> stream =
544 CreateStreamSynchronously(
545 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
546 ASSERT_TRUE(stream.get() != NULL);
547
548 StreamDelegateDoNothing delegate(stream);
549 stream->SetDelegate(&delegate);
550
551 EXPECT_FALSE(stream->HasUrl());
552
553 scoped_ptr<SpdyHeaderBlock> headers(
554 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
555 EXPECT_EQ(ERR_IO_PENDING,
556 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
557 EXPECT_TRUE(stream->HasUrl());
558 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
559
560 // For the initial window update.
561 if (spdy_util_.protocol() >= kProtoSPDY31)
562 data.RunFor(1);
563
564 data.RunFor(4);
565
566 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
567 }
568
569 // Receiving a header with uppercase ASCII should result in a protocol
570 // error even for a push stream.
571 TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
572 GURL url(kStreamUrl);
573
574 session_ =
575 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
576
577 scoped_ptr<SpdyFrame> initial_window_update(
578 spdy_util_.ConstructSpdyWindowUpdate(
579 kSessionFlowControlStreamId,
580 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
581 if (spdy_util_.protocol() >= kProtoSPDY31)
582 AddWrite(*initial_window_update);
583
584 scoped_ptr<SpdyFrame> syn(
585 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
586 AddWrite(*syn);
587
588 scoped_ptr<SpdyFrame>
589 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
590 AddRead(*reply);
591
592 const char* const extra_headers[] = {"X-UpperCase", "yes"};
593 scoped_ptr<SpdyFrame>
594 push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
595 AddRead(*push);
596
597 scoped_ptr<SpdyFrame> rst(
598 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
599 AddWrite(*rst);
600
601 AddReadEOF();
602
603 DeterministicSocketData data(GetReads(), GetNumReads(),
604 GetWrites(), GetNumWrites());
605 MockConnect connect_data(SYNCHRONOUS, OK);
606 data.set_connect_data(connect_data);
607
608 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
609
610 scoped_refptr<SpdySession> session(CreateSpdySession());
611
612 InitializeSpdySession(session, host_port_pair_);
613
614 base::WeakPtr<SpdyStream> stream =
615 CreateStreamSynchronously(
616 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
617 ASSERT_TRUE(stream.get() != NULL);
618
619 StreamDelegateDoNothing delegate(stream);
620 stream->SetDelegate(&delegate);
621
622 EXPECT_FALSE(stream->HasUrl());
623
624 scoped_ptr<SpdyHeaderBlock> headers(
625 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
626 EXPECT_EQ(ERR_IO_PENDING,
627 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
628 EXPECT_TRUE(stream->HasUrl());
629 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
630
631 // For the initial window update.
632 if (spdy_util_.protocol() >= kProtoSPDY31)
633 data.RunFor(1);
634
635 data.RunFor(4);
636
637 base::WeakPtr<SpdyStream> push_stream;
638 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
639 EXPECT_FALSE(push_stream);
640
641 data.RunFor(1);
642
643 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
644 }
645
646 // Receiving a header with uppercase ASCII in a HEADERS frame should
647 // result in a protocol error.
648 TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
649 GURL url(kStreamUrl);
650
651 session_ =
652 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
653
654 scoped_ptr<SpdyFrame> initial_window_update(
655 spdy_util_.ConstructSpdyWindowUpdate(
656 kSessionFlowControlStreamId,
657 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
658 if (spdy_util_.protocol() >= kProtoSPDY31)
659 AddWrite(*initial_window_update);
660
661 scoped_ptr<SpdyFrame> syn(
662 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
663 AddWrite(*syn);
664
665 scoped_ptr<SpdyFrame>
666 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
667 AddRead(*reply);
668
669 scoped_ptr<SpdyFrame>
670 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
671 AddRead(*push);
672
673 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
674 (*late_headers)["X-UpperCase"] = "yes";
675 scoped_ptr<SpdyFrame> headers_frame(
676 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
677 false,
678 2,
679 LOWEST,
680 HEADERS,
681 CONTROL_FLAG_NONE,
682 0));
683 AddRead(*headers_frame);
684
685 scoped_ptr<SpdyFrame> rst(
686 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
687 AddWrite(*rst);
688
689 AddReadEOF();
690
691 DeterministicSocketData data(GetReads(), GetNumReads(),
692 GetWrites(), GetNumWrites());
693 MockConnect connect_data(SYNCHRONOUS, OK);
694 data.set_connect_data(connect_data);
695
696 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
697
698 scoped_refptr<SpdySession> session(CreateSpdySession());
699
700 InitializeSpdySession(session, host_port_pair_);
701
702 base::WeakPtr<SpdyStream> stream =
703 CreateStreamSynchronously(
704 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
705 ASSERT_TRUE(stream.get() != NULL);
706
707 StreamDelegateDoNothing delegate(stream);
708 stream->SetDelegate(&delegate);
709
710 EXPECT_FALSE(stream->HasUrl());
711
712 scoped_ptr<SpdyHeaderBlock> headers(
713 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
714 EXPECT_EQ(ERR_IO_PENDING,
715 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
716 EXPECT_TRUE(stream->HasUrl());
717 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
718
719 // For the initial window update.
720 if (spdy_util_.protocol() >= kProtoSPDY31)
721 data.RunFor(1);
722
723 data.RunFor(3);
724
725 base::WeakPtr<SpdyStream> push_stream;
726 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
727 EXPECT_TRUE(push_stream);
728
729 data.RunFor(1);
730
731 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
732 EXPECT_FALSE(push_stream);
733
734 data.RunFor(2);
735
736 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
737 }
738
739 // Receiving a duplicate header in a HEADERS frame should result in a
740 // protocol error.
741 TEST_P(SpdyStreamTest, DuplicateHeaders) {
742 GURL url(kStreamUrl);
743
744 session_ =
745 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
746
747 scoped_ptr<SpdyFrame> initial_window_update(
748 spdy_util_.ConstructSpdyWindowUpdate(
749 kSessionFlowControlStreamId,
750 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
751 if (spdy_util_.protocol() >= kProtoSPDY31)
752 AddWrite(*initial_window_update);
753
754 scoped_ptr<SpdyFrame> syn(
755 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
756 AddWrite(*syn);
757
758 scoped_ptr<SpdyFrame>
759 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
760 AddRead(*reply);
761
762 scoped_ptr<SpdyFrame>
763 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
764 AddRead(*push);
765
766 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
767 (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
768 scoped_ptr<SpdyFrame> headers_frame(
769 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
770 false,
771 2,
772 LOWEST,
773 HEADERS,
774 CONTROL_FLAG_NONE,
775 0));
776 AddRead(*headers_frame);
777
778 scoped_ptr<SpdyFrame> rst(
779 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
780 AddWrite(*rst);
781
782 AddReadEOF();
783
784 DeterministicSocketData data(GetReads(), GetNumReads(),
785 GetWrites(), GetNumWrites());
786 MockConnect connect_data(SYNCHRONOUS, OK);
787 data.set_connect_data(connect_data);
788
789 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
790
791 scoped_refptr<SpdySession> session(CreateSpdySession());
792
793 InitializeSpdySession(session, host_port_pair_);
794
795 base::WeakPtr<SpdyStream> stream =
796 CreateStreamSynchronously(
797 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
798 ASSERT_TRUE(stream.get() != NULL);
799
800 StreamDelegateDoNothing delegate(stream);
801 stream->SetDelegate(&delegate);
802
803 EXPECT_FALSE(stream->HasUrl());
804
805 scoped_ptr<SpdyHeaderBlock> headers(
806 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
807 EXPECT_EQ(ERR_IO_PENDING,
808 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
809 EXPECT_TRUE(stream->HasUrl());
810 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
811
812 // For the initial window update.
813 if (spdy_util_.protocol() >= kProtoSPDY31)
814 data.RunFor(1);
815
816 data.RunFor(3);
817
818 base::WeakPtr<SpdyStream> push_stream;
819 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
820 EXPECT_TRUE(push_stream);
821
822 data.RunFor(1);
823
824 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
825 EXPECT_FALSE(push_stream);
826
827 data.RunFor(2);
828
829 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
830 }
831
491 // The tests below are only for SPDY/3 and above. 832 // The tests below are only for SPDY/3 and above.
492 833
493 // Call IncreaseSendWindowSize on a stream with a large enough delta 834 // Call IncreaseSendWindowSize on a stream with a large enough delta
494 // to overflow an int32. The SpdyStream should handle that case 835 // to overflow an int32. The SpdyStream should handle that case
495 // gracefully. 836 // gracefully.
496 TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) { 837 TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
497 if (spdy_util_.protocol() < kProtoSPDY3) 838 if (spdy_util_.protocol() < kProtoSPDY3)
498 return; 839 return;
499 840
500 session_ = 841 session_ =
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) { 1138 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
798 RunResumeAfterUnstallBidirectionalTest( 1139 RunResumeAfterUnstallBidirectionalTest(
799 base::Bind(&AdjustStreamSendWindowSize)); 1140 base::Bind(&AdjustStreamSendWindowSize));
800 } 1141 }
801 1142
802 } // namespace 1143 } // namespace
803 1144
804 } // namespace test 1145 } // namespace test
805 1146
806 } // namespace net 1147 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | net/spdy/spdy_websocket_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698