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 <cstddef>
      6 #include <string>
      7 #include <vector>
      8 
      9 #include "base/memory/ref_counted.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/stl_util.h"
     12 #include "base/strings/string_piece.h"
     13 #include "net/base/completion_callback.h"
     14 #include "net/base/net_log_unittest.h"
     15 #include "net/base/request_priority.h"
     16 #include "net/socket/next_proto.h"
     17 #include "net/socket/socket_test_util.h"
     18 #include "net/spdy/buffered_spdy_framer.h"
     19 #include "net/spdy/spdy_http_utils.h"
     20 #include "net/spdy/spdy_protocol.h"
     21 #include "net/spdy/spdy_session.h"
     22 #include "net/spdy/spdy_stream.h"
     23 #include "net/spdy/spdy_stream_test_util.h"
     24 #include "net/spdy/spdy_test_util_common.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 
     27 // TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
     28 //
     29 namespace net {
     30 
     31 namespace test {
     32 
     33 namespace {
     34 
     35 const char kStreamUrl[] = "http://www.google.com/";
     36 const char kPostBody[] = "\0hello!\xff";
     37 const size_t kPostBodyLength = arraysize(kPostBody);
     38 const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
     39 
     40 class SpdyStreamTest : public ::testing::Test,
     41                        public ::testing::WithParamInterface<NextProto> {
     42  protected:
     43   // A function that takes a SpdyStream and the number of bytes which
     44   // will unstall the next frame completely.
     45   typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32)>
     46       UnstallFunction;
     47 
     48   SpdyStreamTest()
     49       : spdy_util_(GetParam()),
     50         session_deps_(GetParam()),
     51         offset_(0) {}
     52 
     53   base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
     54     SpdySessionKey key(HostPortPair("www.google.com", 80),
     55                        ProxyServer::Direct(),
     56                        PRIVACY_MODE_DISABLED);
     57     return CreateInsecureSpdySession(session_, key, BoundNetLog());
     58   }
     59 
     60   virtual void TearDown() {
     61     base::MessageLoop::current()->RunUntilIdle();
     62   }
     63 
     64   void RunResumeAfterUnstallRequestResponseTest(
     65       const UnstallFunction& unstall_function);
     66 
     67   void RunResumeAfterUnstallBidirectionalTest(
     68       const UnstallFunction& unstall_function);
     69 
     70   // Add{Read,Write}() populates lists that are eventually passed to a
     71   // SocketData class. |frame| must live for the whole test.
     72 
     73   void AddRead(const SpdyFrame& frame) {
     74     reads_.push_back(CreateMockRead(frame, offset_++));
     75   }
     76 
     77   void AddWrite(const SpdyFrame& frame) {
     78     writes_.push_back(CreateMockWrite(frame, offset_++));
     79   }
     80 
     81   void AddReadEOF() {
     82     reads_.push_back(MockRead(ASYNC, 0, offset_++));
     83   }
     84 
     85   MockRead* GetReads() {
     86     return vector_as_array(&reads_);
     87   }
     88 
     89   size_t GetNumReads() const {
     90     return reads_.size();
     91   }
     92 
     93   MockWrite* GetWrites() {
     94     return vector_as_array(&writes_);
     95   }
     96 
     97   int GetNumWrites() const {
     98     return writes_.size();
     99   }
    100 
    101   SpdyTestUtil spdy_util_;
    102   SpdySessionDependencies session_deps_;
    103   scoped_refptr<HttpNetworkSession> session_;
    104 
    105  private:
    106   // Used by Add{Read,Write}() above.
    107   std::vector<MockWrite> writes_;
    108   std::vector<MockRead> reads_;
    109   int offset_;
    110 };
    111 
    112 INSTANTIATE_TEST_CASE_P(
    113     NextProto,
    114     SpdyStreamTest,
    115     testing::Values(kProtoDeprecatedSPDY2,
    116                     kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
    117 
    118 TEST_P(SpdyStreamTest, SendDataAfterOpen) {
    119   GURL url(kStreamUrl);
    120 
    121   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    122 
    123   scoped_ptr<SpdyFrame> req(
    124       spdy_util_.ConstructSpdyPost(
    125           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    126   AddWrite(*req);
    127 
    128   scoped_ptr<SpdyFrame> resp(
    129       spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
    130   AddRead(*resp);
    131 
    132   scoped_ptr<SpdyFrame> msg(
    133       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    134   AddWrite(*msg);
    135 
    136   scoped_ptr<SpdyFrame> echo(
    137       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    138   AddRead(*echo);
    139 
    140   AddReadEOF();
    141 
    142   OrderedSocketData data(GetReads(), GetNumReads(),
    143                          GetWrites(), GetNumWrites());
    144   MockConnect connect_data(SYNCHRONOUS, OK);
    145   data.set_connect_data(connect_data);
    146 
    147   session_deps_.socket_factory->AddSocketDataProvider(&data);
    148 
    149   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    150 
    151   base::WeakPtr<SpdyStream> stream =
    152       CreateStreamSynchronously(
    153           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
    154   ASSERT_TRUE(stream.get() != NULL);
    155 
    156   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    157   stream->SetDelegate(&delegate);
    158 
    159   EXPECT_FALSE(stream->HasUrlFromHeaders());
    160 
    161   scoped_ptr<SpdyHeaderBlock> headers(
    162       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    163   EXPECT_EQ(ERR_IO_PENDING,
    164             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    165   EXPECT_TRUE(stream->HasUrlFromHeaders());
    166   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    167 
    168   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    169 
    170   EXPECT_TRUE(delegate.send_headers_completed());
    171   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    172   EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
    173             delegate.TakeReceivedData());
    174   EXPECT_TRUE(data.at_write_eof());
    175 }
    176 
    177 TEST_P(SpdyStreamTest, PushedStream) {
    178   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    179 
    180   AddReadEOF();
    181 
    182   OrderedSocketData data(GetReads(), GetNumReads(),
    183                          GetWrites(), GetNumWrites());
    184   MockConnect connect_data(SYNCHRONOUS, OK);
    185   data.set_connect_data(connect_data);
    186 
    187   session_deps_.socket_factory->AddSocketDataProvider(&data);
    188 
    189   base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession());
    190 
    191   // Conjure up a stream.
    192   SpdyStream stream(SPDY_PUSH_STREAM,
    193                     spdy_session,
    194                     GURL(),
    195                     DEFAULT_PRIORITY,
    196                     kSpdyStreamInitialWindowSize,
    197                     kSpdyStreamInitialWindowSize,
    198                     BoundNetLog());
    199   stream.set_stream_id(2);
    200   EXPECT_FALSE(stream.HasUrlFromHeaders());
    201 
    202   // Set required request headers.
    203   SpdyHeaderBlock request_headers;
    204   spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &request_headers);
    205   stream.OnPushPromiseHeadersReceived(request_headers);
    206 
    207   // Send some basic response headers.
    208   SpdyHeaderBlock response;
    209   response[spdy_util_.GetStatusKey()] = "200";
    210   response[spdy_util_.GetVersionKey()] = "OK";
    211   stream.OnInitialResponseHeadersReceived(
    212       response, base::Time::Now(), base::TimeTicks::Now());
    213 
    214   // And some more headers.
    215   // TODO(baranovich): not valid for HTTP 2.
    216   SpdyHeaderBlock headers;
    217   headers["alpha"] = "beta";
    218   stream.OnAdditionalResponseHeadersReceived(headers);
    219 
    220   EXPECT_TRUE(stream.HasUrlFromHeaders());
    221   EXPECT_EQ(kStreamUrl, stream.GetUrlFromHeaders().spec());
    222 
    223   StreamDelegateDoNothing delegate(stream.GetWeakPtr());
    224   stream.SetDelegate(&delegate);
    225 
    226   base::MessageLoop::current()->RunUntilIdle();
    227 
    228   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    229   EXPECT_EQ("beta", delegate.GetResponseHeaderValue("alpha"));
    230 
    231   EXPECT_TRUE(spdy_session == NULL);
    232 }
    233 
    234 TEST_P(SpdyStreamTest, StreamError) {
    235   GURL url(kStreamUrl);
    236 
    237   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    238 
    239   scoped_ptr<SpdyFrame> req(
    240       spdy_util_.ConstructSpdyPost(
    241           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    242   AddWrite(*req);
    243 
    244   scoped_ptr<SpdyFrame> resp(
    245       spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    246   AddRead(*resp);
    247 
    248   scoped_ptr<SpdyFrame> msg(
    249       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    250   AddWrite(*msg);
    251 
    252   scoped_ptr<SpdyFrame> echo(
    253       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    254   AddRead(*echo);
    255 
    256   AddReadEOF();
    257 
    258   CapturingBoundNetLog log;
    259 
    260   OrderedSocketData data(GetReads(), GetNumReads(),
    261                          GetWrites(), GetNumWrites());
    262   MockConnect connect_data(SYNCHRONOUS, OK);
    263   data.set_connect_data(connect_data);
    264 
    265   session_deps_.socket_factory->AddSocketDataProvider(&data);
    266 
    267   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    268 
    269   base::WeakPtr<SpdyStream> stream =
    270       CreateStreamSynchronously(
    271           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
    272   ASSERT_TRUE(stream.get() != NULL);
    273 
    274   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    275   stream->SetDelegate(&delegate);
    276 
    277   EXPECT_FALSE(stream->HasUrlFromHeaders());
    278 
    279   scoped_ptr<SpdyHeaderBlock> headers(
    280       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    281   EXPECT_EQ(ERR_IO_PENDING,
    282             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    283   EXPECT_TRUE(stream->HasUrlFromHeaders());
    284   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    285 
    286   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    287 
    288   const SpdyStreamId stream_id = delegate.stream_id();
    289 
    290   EXPECT_TRUE(delegate.send_headers_completed());
    291   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    292   EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
    293             delegate.TakeReceivedData());
    294   EXPECT_TRUE(data.at_write_eof());
    295 
    296   // Check that the NetLog was filled reasonably.
    297   net::CapturingNetLog::CapturedEntryList entries;
    298   log.GetEntries(&entries);
    299   EXPECT_LT(0u, entries.size());
    300 
    301   // Check that we logged SPDY_STREAM_ERROR correctly.
    302   int pos = net::ExpectLogContainsSomewhere(
    303       entries, 0,
    304       net::NetLog::TYPE_SPDY_STREAM_ERROR,
    305       net::NetLog::PHASE_NONE);
    306 
    307   int stream_id2;
    308   ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
    309   EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
    310 }
    311 
    312 // Make sure that large blocks of data are properly split up into
    313 // frame-sized chunks for a request/response (i.e., an HTTP-like)
    314 // stream.
    315 TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
    316   GURL url(kStreamUrl);
    317 
    318   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    319 
    320   scoped_ptr<SpdyFrame> req(
    321       spdy_util_.ConstructSpdyPost(
    322           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    323   AddWrite(*req);
    324 
    325   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
    326   scoped_ptr<SpdyFrame> chunk(
    327       spdy_util_.ConstructSpdyBodyFrame(
    328           1, chunk_data.data(), chunk_data.length(), false));
    329   AddWrite(*chunk);
    330   AddWrite(*chunk);
    331 
    332   scoped_ptr<SpdyFrame> last_chunk(
    333       spdy_util_.ConstructSpdyBodyFrame(
    334           1, chunk_data.data(), chunk_data.length(), true));
    335   AddWrite(*last_chunk);
    336 
    337   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
    338   AddRead(*resp);
    339 
    340   AddReadEOF();
    341 
    342   OrderedSocketData data(GetReads(), GetNumReads(),
    343                          GetWrites(), GetNumWrites());
    344   MockConnect connect_data(SYNCHRONOUS, OK);
    345   data.set_connect_data(connect_data);
    346 
    347   session_deps_.socket_factory->AddSocketDataProvider(&data);
    348 
    349   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    350 
    351   base::WeakPtr<SpdyStream> stream =
    352       CreateStreamSynchronously(
    353           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    354   ASSERT_TRUE(stream.get() != NULL);
    355 
    356   std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
    357   StreamDelegateWithBody delegate(stream, body_data);
    358   stream->SetDelegate(&delegate);
    359 
    360   EXPECT_FALSE(stream->HasUrlFromHeaders());
    361 
    362   scoped_ptr<SpdyHeaderBlock> headers(
    363       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    364   EXPECT_EQ(ERR_IO_PENDING,
    365             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    366   EXPECT_TRUE(stream->HasUrlFromHeaders());
    367   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    368 
    369   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    370 
    371   EXPECT_TRUE(delegate.send_headers_completed());
    372   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    373   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
    374   EXPECT_TRUE(data.at_write_eof());
    375 }
    376 
    377 // Make sure that large blocks of data are properly split up into
    378 // frame-sized chunks for a bidirectional (i.e., non-HTTP-like)
    379 // stream.
    380 TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
    381   GURL url(kStreamUrl);
    382 
    383   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    384 
    385   scoped_ptr<SpdyFrame> req(
    386       spdy_util_.ConstructSpdyPost(
    387           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    388   AddWrite(*req);
    389 
    390   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
    391   AddRead(*resp);
    392 
    393   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
    394   scoped_ptr<SpdyFrame> chunk(
    395       spdy_util_.ConstructSpdyBodyFrame(
    396           1, chunk_data.data(), chunk_data.length(), false));
    397   AddWrite(*chunk);
    398   AddWrite(*chunk);
    399   AddWrite(*chunk);
    400 
    401   AddReadEOF();
    402 
    403   OrderedSocketData data(GetReads(), GetNumReads(),
    404                          GetWrites(), GetNumWrites());
    405   MockConnect connect_data(SYNCHRONOUS, OK);
    406   data.set_connect_data(connect_data);
    407 
    408   session_deps_.socket_factory->AddSocketDataProvider(&data);
    409 
    410   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    411 
    412   base::WeakPtr<SpdyStream> stream =
    413       CreateStreamSynchronously(
    414           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
    415   ASSERT_TRUE(stream.get() != NULL);
    416 
    417   std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
    418   StreamDelegateSendImmediate delegate(stream, body_data);
    419   stream->SetDelegate(&delegate);
    420 
    421   EXPECT_FALSE(stream->HasUrlFromHeaders());
    422 
    423   scoped_ptr<SpdyHeaderBlock> headers(
    424       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    425   EXPECT_EQ(ERR_IO_PENDING,
    426             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    427   EXPECT_TRUE(stream->HasUrlFromHeaders());
    428   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    429 
    430   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    431 
    432   EXPECT_TRUE(delegate.send_headers_completed());
    433   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    434   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
    435   EXPECT_TRUE(data.at_write_eof());
    436 }
    437 
    438 // Receiving a header with uppercase ASCII should result in a protocol
    439 // error.
    440 TEST_P(SpdyStreamTest, UpperCaseHeaders) {
    441   GURL url(kStreamUrl);
    442 
    443   session_ =
    444       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    445 
    446   scoped_ptr<SpdyFrame> syn(
    447       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    448   AddWrite(*syn);
    449 
    450   const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
    451   scoped_ptr<SpdyFrame>
    452       reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
    453   AddRead(*reply);
    454 
    455   scoped_ptr<SpdyFrame> rst(
    456       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
    457   AddWrite(*rst);
    458 
    459   AddReadEOF();
    460 
    461   DeterministicSocketData data(GetReads(), GetNumReads(),
    462                                GetWrites(), GetNumWrites());
    463   MockConnect connect_data(SYNCHRONOUS, OK);
    464   data.set_connect_data(connect_data);
    465 
    466   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    467 
    468   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    469 
    470   base::WeakPtr<SpdyStream> stream =
    471       CreateStreamSynchronously(
    472           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    473   ASSERT_TRUE(stream.get() != NULL);
    474 
    475   StreamDelegateDoNothing delegate(stream);
    476   stream->SetDelegate(&delegate);
    477 
    478   EXPECT_FALSE(stream->HasUrlFromHeaders());
    479 
    480   scoped_ptr<SpdyHeaderBlock> headers(
    481       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    482   EXPECT_EQ(ERR_IO_PENDING,
    483             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    484   EXPECT_TRUE(stream->HasUrlFromHeaders());
    485   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    486 
    487   data.RunFor(4);
    488 
    489   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
    490 }
    491 
    492 // Receiving a header with uppercase ASCII should result in a protocol
    493 // error even for a push stream.
    494 TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
    495   GURL url(kStreamUrl);
    496 
    497   session_ =
    498       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    499 
    500   scoped_ptr<SpdyFrame> syn(
    501       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    502   AddWrite(*syn);
    503 
    504   scoped_ptr<SpdyFrame>
    505       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    506   AddRead(*reply);
    507 
    508   const char* const extra_headers[] = {"X-UpperCase", "yes"};
    509   scoped_ptr<SpdyFrame>
    510       push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
    511   AddRead(*push);
    512 
    513   scoped_ptr<SpdyFrame> rst(
    514       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
    515   AddWrite(*rst);
    516 
    517   AddReadEOF();
    518 
    519   DeterministicSocketData data(GetReads(), GetNumReads(),
    520                                GetWrites(), GetNumWrites());
    521   MockConnect connect_data(SYNCHRONOUS, OK);
    522   data.set_connect_data(connect_data);
    523 
    524   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    525 
    526   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    527 
    528   base::WeakPtr<SpdyStream> stream =
    529       CreateStreamSynchronously(
    530           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    531   ASSERT_TRUE(stream.get() != NULL);
    532 
    533   StreamDelegateDoNothing delegate(stream);
    534   stream->SetDelegate(&delegate);
    535 
    536   EXPECT_FALSE(stream->HasUrlFromHeaders());
    537 
    538   scoped_ptr<SpdyHeaderBlock> headers(
    539       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    540   EXPECT_EQ(ERR_IO_PENDING,
    541             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    542   EXPECT_TRUE(stream->HasUrlFromHeaders());
    543   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    544 
    545   data.RunFor(4);
    546 
    547   base::WeakPtr<SpdyStream> push_stream;
    548   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    549   EXPECT_FALSE(push_stream);
    550 
    551   data.RunFor(1);
    552 
    553   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    554 }
    555 
    556 // Receiving a header with uppercase ASCII in a HEADERS frame should
    557 // result in a protocol error.
    558 TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
    559   GURL url(kStreamUrl);
    560 
    561   session_ =
    562       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    563 
    564   scoped_ptr<SpdyFrame> syn(
    565       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    566   AddWrite(*syn);
    567 
    568   scoped_ptr<SpdyFrame>
    569       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    570   AddRead(*reply);
    571 
    572   scoped_ptr<SpdyFrame>
    573       push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
    574   AddRead(*push);
    575 
    576   scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
    577   (*late_headers)["X-UpperCase"] = "yes";
    578   scoped_ptr<SpdyFrame> headers_frame(
    579       spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
    580                                            false,
    581                                            2,
    582                                            LOWEST,
    583                                            HEADERS,
    584                                            CONTROL_FLAG_NONE,
    585                                            0));
    586   AddRead(*headers_frame);
    587 
    588   scoped_ptr<SpdyFrame> rst(
    589       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
    590   AddWrite(*rst);
    591 
    592   AddReadEOF();
    593 
    594   DeterministicSocketData data(GetReads(), GetNumReads(),
    595                                GetWrites(), GetNumWrites());
    596   MockConnect connect_data(SYNCHRONOUS, OK);
    597   data.set_connect_data(connect_data);
    598 
    599   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    600 
    601   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    602 
    603   base::WeakPtr<SpdyStream> stream =
    604       CreateStreamSynchronously(
    605           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    606   ASSERT_TRUE(stream.get() != NULL);
    607 
    608   StreamDelegateDoNothing delegate(stream);
    609   stream->SetDelegate(&delegate);
    610 
    611   EXPECT_FALSE(stream->HasUrlFromHeaders());
    612 
    613   scoped_ptr<SpdyHeaderBlock> headers(
    614       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    615   EXPECT_EQ(ERR_IO_PENDING,
    616             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    617   EXPECT_TRUE(stream->HasUrlFromHeaders());
    618   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    619 
    620   data.RunFor(3);
    621 
    622   base::WeakPtr<SpdyStream> push_stream;
    623   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    624   EXPECT_TRUE(push_stream);
    625 
    626   data.RunFor(1);
    627 
    628   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    629   EXPECT_FALSE(push_stream);
    630 
    631   data.RunFor(2);
    632 
    633   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    634 }
    635 
    636 // Receiving a duplicate header in a HEADERS frame should result in a
    637 // protocol error.
    638 TEST_P(SpdyStreamTest, DuplicateHeaders) {
    639   GURL url(kStreamUrl);
    640 
    641   session_ =
    642       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    643 
    644   scoped_ptr<SpdyFrame> syn(
    645       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    646   AddWrite(*syn);
    647 
    648   scoped_ptr<SpdyFrame>
    649       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    650   AddRead(*reply);
    651 
    652   scoped_ptr<SpdyFrame>
    653       push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
    654   AddRead(*push);
    655 
    656   scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
    657   (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
    658   scoped_ptr<SpdyFrame> headers_frame(
    659       spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
    660                                            false,
    661                                            2,
    662                                            LOWEST,
    663                                            HEADERS,
    664                                            CONTROL_FLAG_NONE,
    665                                            0));
    666   AddRead(*headers_frame);
    667 
    668   scoped_ptr<SpdyFrame> rst(
    669       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
    670   AddWrite(*rst);
    671 
    672   AddReadEOF();
    673 
    674   DeterministicSocketData data(GetReads(), GetNumReads(),
    675                                GetWrites(), GetNumWrites());
    676   MockConnect connect_data(SYNCHRONOUS, OK);
    677   data.set_connect_data(connect_data);
    678 
    679   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    680 
    681   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    682 
    683   base::WeakPtr<SpdyStream> stream =
    684       CreateStreamSynchronously(
    685           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    686   ASSERT_TRUE(stream.get() != NULL);
    687 
    688   StreamDelegateDoNothing delegate(stream);
    689   stream->SetDelegate(&delegate);
    690 
    691   EXPECT_FALSE(stream->HasUrlFromHeaders());
    692 
    693   scoped_ptr<SpdyHeaderBlock> headers(
    694       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    695   EXPECT_EQ(ERR_IO_PENDING,
    696             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    697   EXPECT_TRUE(stream->HasUrlFromHeaders());
    698   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    699 
    700   data.RunFor(3);
    701 
    702   base::WeakPtr<SpdyStream> push_stream;
    703   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    704   EXPECT_TRUE(push_stream);
    705 
    706   data.RunFor(1);
    707 
    708   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    709   EXPECT_FALSE(push_stream);
    710 
    711   data.RunFor(2);
    712 
    713   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    714 }
    715 
    716 // The tests below are only for SPDY/3 and above.
    717 
    718 // Call IncreaseSendWindowSize on a stream with a large enough delta
    719 // to overflow an int32. The SpdyStream should handle that case
    720 // gracefully.
    721 TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
    722   if (spdy_util_.protocol() < kProtoSPDY3)
    723     return;
    724 
    725   session_ =
    726       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    727 
    728   scoped_ptr<SpdyFrame> req(
    729       spdy_util_.ConstructSpdyPost(
    730           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    731   AddWrite(*req);
    732 
    733   // Triggered by the overflowing call to IncreaseSendWindowSize
    734   // below.
    735   scoped_ptr<SpdyFrame> rst(
    736       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
    737   AddWrite(*rst);
    738 
    739   AddReadEOF();
    740 
    741   CapturingBoundNetLog log;
    742 
    743   DeterministicSocketData data(GetReads(), GetNumReads(),
    744                                GetWrites(), GetNumWrites());
    745   MockConnect connect_data(SYNCHRONOUS, OK);
    746   data.set_connect_data(connect_data);
    747 
    748   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    749 
    750   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    751   GURL url(kStreamUrl);
    752 
    753   base::WeakPtr<SpdyStream> stream =
    754       CreateStreamSynchronously(
    755           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
    756   ASSERT_TRUE(stream.get() != NULL);
    757   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    758   stream->SetDelegate(&delegate);
    759 
    760   scoped_ptr<SpdyHeaderBlock> headers(
    761       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    762   EXPECT_EQ(ERR_IO_PENDING,
    763             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    764   EXPECT_TRUE(stream->HasUrlFromHeaders());
    765   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    766 
    767   data.RunFor(1);
    768 
    769   int32 old_send_window_size = stream->send_window_size();
    770   ASSERT_GT(old_send_window_size, 0);
    771   int32 delta_window_size = kint32max - old_send_window_size + 1;
    772   stream->IncreaseSendWindowSize(delta_window_size);
    773   EXPECT_EQ(NULL, stream.get());
    774 
    775   data.RunFor(2);
    776 
    777   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
    778 }
    779 
    780 // Functions used with
    781 // RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
    782 
    783 void StallStream(const base::WeakPtr<SpdyStream>& stream) {
    784   // Reduce the send window size to 0 to stall.
    785   while (stream->send_window_size() > 0) {
    786     stream->DecreaseSendWindowSize(
    787         std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
    788   }
    789 }
    790 
    791 void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
    792                                   int32 delta_window_size) {
    793   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    794   stream->IncreaseSendWindowSize(delta_window_size);
    795   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    796 }
    797 
    798 void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
    799                                 int32 delta_window_size) {
    800   // Make sure that negative adjustments are handled properly.
    801   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    802   stream->AdjustSendWindowSize(-delta_window_size);
    803   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    804   stream->AdjustSendWindowSize(+delta_window_size);
    805   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    806   stream->AdjustSendWindowSize(+delta_window_size);
    807   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    808 }
    809 
    810 // Given an unstall function, runs a test to make sure that a
    811 // request/response (i.e., an HTTP-like) stream resumes after a stall
    812 // and unstall.
    813 void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
    814     const UnstallFunction& unstall_function) {
    815   GURL url(kStreamUrl);
    816 
    817   session_ =
    818       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    819 
    820   scoped_ptr<SpdyFrame> req(
    821       spdy_util_.ConstructSpdyPost(
    822           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    823   AddWrite(*req);
    824 
    825   scoped_ptr<SpdyFrame> body(
    826       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
    827   AddWrite(*body);
    828 
    829   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    830   AddRead(*resp);
    831 
    832   AddReadEOF();
    833 
    834   DeterministicSocketData data(GetReads(), GetNumReads(),
    835                                GetWrites(), GetNumWrites());
    836   MockConnect connect_data(SYNCHRONOUS, OK);
    837   data.set_connect_data(connect_data);
    838 
    839   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    840 
    841   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    842 
    843   base::WeakPtr<SpdyStream> stream =
    844       CreateStreamSynchronously(
    845           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    846   ASSERT_TRUE(stream.get() != NULL);
    847 
    848   StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
    849   stream->SetDelegate(&delegate);
    850 
    851   EXPECT_FALSE(stream->HasUrlFromHeaders());
    852   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    853 
    854   scoped_ptr<SpdyHeaderBlock> headers(
    855       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    856   EXPECT_EQ(ERR_IO_PENDING,
    857             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    858   EXPECT_TRUE(stream->HasUrlFromHeaders());
    859   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    860 
    861   StallStream(stream);
    862 
    863   data.RunFor(1);
    864 
    865   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    866 
    867   unstall_function.Run(stream, kPostBodyLength);
    868 
    869   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    870 
    871   data.RunFor(3);
    872 
    873   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    874 
    875   EXPECT_TRUE(delegate.send_headers_completed());
    876   EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
    877   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
    878   EXPECT_TRUE(data.at_write_eof());
    879 }
    880 
    881 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
    882   if (spdy_util_.protocol() < kProtoSPDY3)
    883     return;
    884 
    885   RunResumeAfterUnstallRequestResponseTest(
    886       base::Bind(&IncreaseStreamSendWindowSize));
    887 }
    888 
    889 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
    890   if (spdy_util_.protocol() < kProtoSPDY3)
    891     return;
    892 
    893   RunResumeAfterUnstallRequestResponseTest(
    894       base::Bind(&AdjustStreamSendWindowSize));
    895 }
    896 
    897 // Given an unstall function, runs a test to make sure that a
    898 // bidirectional (i.e., non-HTTP-like) stream resumes after a stall
    899 // and unstall.
    900 void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
    901     const UnstallFunction& unstall_function) {
    902   GURL url(kStreamUrl);
    903 
    904   session_ =
    905       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    906 
    907   scoped_ptr<SpdyFrame> req(
    908       spdy_util_.ConstructSpdyPost(
    909           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    910   AddWrite(*req);
    911 
    912   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    913   AddRead(*resp);
    914 
    915   scoped_ptr<SpdyFrame> msg(
    916       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    917   AddWrite(*msg);
    918 
    919   scoped_ptr<SpdyFrame> echo(
    920       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    921   AddRead(*echo);
    922 
    923   AddReadEOF();
    924 
    925   DeterministicSocketData data(GetReads(), GetNumReads(),
    926                                GetWrites(), GetNumWrites());
    927   MockConnect connect_data(SYNCHRONOUS, OK);
    928   data.set_connect_data(connect_data);
    929 
    930   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    931 
    932   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    933 
    934   base::WeakPtr<SpdyStream> stream =
    935       CreateStreamSynchronously(
    936           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
    937   ASSERT_TRUE(stream.get() != NULL);
    938 
    939   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    940   stream->SetDelegate(&delegate);
    941 
    942   EXPECT_FALSE(stream->HasUrlFromHeaders());
    943 
    944   scoped_ptr<SpdyHeaderBlock> headers(
    945       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    946   EXPECT_EQ(ERR_IO_PENDING,
    947             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    948   EXPECT_TRUE(stream->HasUrlFromHeaders());
    949   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    950 
    951   data.RunFor(1);
    952 
    953   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    954 
    955   StallStream(stream);
    956 
    957   data.RunFor(1);
    958 
    959   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    960 
    961   unstall_function.Run(stream, kPostBodyLength);
    962 
    963   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    964 
    965   data.RunFor(3);
    966 
    967   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    968 
    969   EXPECT_TRUE(delegate.send_headers_completed());
    970   EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
    971   EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
    972             delegate.TakeReceivedData());
    973   EXPECT_TRUE(data.at_write_eof());
    974 }
    975 
    976 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
    977   if (spdy_util_.protocol() < kProtoSPDY3)
    978     return;
    979 
    980   RunResumeAfterUnstallBidirectionalTest(
    981       base::Bind(&IncreaseStreamSendWindowSize));
    982 }
    983 
    984 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
    985   if (spdy_util_.protocol() < kProtoSPDY3)
    986     return;
    987 
    988   RunResumeAfterUnstallBidirectionalTest(
    989       base::Bind(&AdjustStreamSendWindowSize));
    990 }
    991 
    992 // Test calculation of amount of bytes received from network.
    993 TEST_P(SpdyStreamTest, ReceivedBytes) {
    994   GURL url(kStreamUrl);
    995 
    996   session_ =
    997       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    998 
    999   scoped_ptr<SpdyFrame> syn(
   1000       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
   1001   AddWrite(*syn);
   1002 
   1003   scoped_ptr<SpdyFrame>
   1004       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
   1005   AddRead(*reply);
   1006 
   1007   scoped_ptr<SpdyFrame> msg(
   1008       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
   1009   AddRead(*msg);
   1010 
   1011   AddReadEOF();
   1012 
   1013   DeterministicSocketData data(GetReads(), GetNumReads(),
   1014                                GetWrites(), GetNumWrites());
   1015   MockConnect connect_data(SYNCHRONOUS, OK);
   1016   data.set_connect_data(connect_data);
   1017 
   1018   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
   1019 
   1020   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
   1021 
   1022   base::WeakPtr<SpdyStream> stream =
   1023       CreateStreamSynchronously(
   1024           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
   1025   ASSERT_TRUE(stream.get() != NULL);
   1026 
   1027   StreamDelegateDoNothing delegate(stream);
   1028   stream->SetDelegate(&delegate);
   1029 
   1030   EXPECT_FALSE(stream->HasUrlFromHeaders());
   1031 
   1032   scoped_ptr<SpdyHeaderBlock> headers(
   1033       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
   1034   EXPECT_EQ(ERR_IO_PENDING,
   1035             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
   1036   EXPECT_TRUE(stream->HasUrlFromHeaders());
   1037   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
   1038 
   1039   int64 reply_frame_len = reply->size();
   1040   int64 data_header_len = spdy_util_.CreateFramer(false)
   1041       ->GetDataFrameMinimumSize();
   1042   int64 data_frame_len = data_header_len + kPostBodyLength;
   1043   int64 response_len = reply_frame_len + data_frame_len;
   1044 
   1045   EXPECT_EQ(0, stream->raw_received_bytes());
   1046   data.RunFor(1); // SYN
   1047   EXPECT_EQ(0, stream->raw_received_bytes());
   1048   data.RunFor(1); // REPLY
   1049   EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
   1050   data.RunFor(1); // DATA
   1051   EXPECT_EQ(response_len, stream->raw_received_bytes());
   1052   data.RunFor(1); // FIN
   1053 
   1054   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
   1055 }
   1056 
   1057 }  // namespace
   1058 
   1059 }  // namespace test
   1060 
   1061 }  // namespace net
   1062