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                        kPrivacyModeDisabled);
     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(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
    116                     kProtoHTTP2Draft04));
    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("HTTP/1.1",
    173             delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
    174   EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
    175             delegate.TakeReceivedData());
    176   EXPECT_TRUE(data.at_write_eof());
    177 }
    178 
    179 TEST_P(SpdyStreamTest, PushedStream) {
    180   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    181 
    182   AddReadEOF();
    183 
    184   OrderedSocketData data(GetReads(), GetNumReads(),
    185                          GetWrites(), GetNumWrites());
    186   MockConnect connect_data(SYNCHRONOUS, OK);
    187   data.set_connect_data(connect_data);
    188 
    189   session_deps_.socket_factory->AddSocketDataProvider(&data);
    190 
    191   base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession());
    192 
    193   // Conjure up a stream.
    194   SpdyStream stream(SPDY_PUSH_STREAM,
    195                     spdy_session,
    196                     GURL(),
    197                     DEFAULT_PRIORITY,
    198                     kSpdyStreamInitialWindowSize,
    199                     kSpdyStreamInitialWindowSize,
    200                     BoundNetLog());
    201   stream.set_stream_id(2);
    202   EXPECT_FALSE(stream.HasUrlFromHeaders());
    203 
    204   // Set a couple of headers.
    205   SpdyHeaderBlock response;
    206   spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &response);
    207   stream.OnInitialResponseHeadersReceived(
    208       response, base::Time::Now(), base::TimeTicks::Now());
    209 
    210   // Send some basic headers.
    211   SpdyHeaderBlock headers;
    212   headers[spdy_util_.GetStatusKey()] = "200";
    213   headers[spdy_util_.GetVersionKey()] = "OK";
    214   stream.OnAdditionalResponseHeadersReceived(headers);
    215 
    216   EXPECT_TRUE(stream.HasUrlFromHeaders());
    217   EXPECT_EQ(kStreamUrl, stream.GetUrlFromHeaders().spec());
    218 
    219   StreamDelegateDoNothing delegate(stream.GetWeakPtr());
    220   stream.SetDelegate(&delegate);
    221 
    222   base::MessageLoop::current()->RunUntilIdle();
    223 
    224   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    225 
    226   EXPECT_TRUE(spdy_session == NULL);
    227 }
    228 
    229 TEST_P(SpdyStreamTest, StreamError) {
    230   GURL url(kStreamUrl);
    231 
    232   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    233 
    234   scoped_ptr<SpdyFrame> req(
    235       spdy_util_.ConstructSpdyPost(
    236           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    237   AddWrite(*req);
    238 
    239   scoped_ptr<SpdyFrame> resp(
    240       spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    241   AddRead(*resp);
    242 
    243   scoped_ptr<SpdyFrame> msg(
    244       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    245   AddWrite(*msg);
    246 
    247   scoped_ptr<SpdyFrame> echo(
    248       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    249   AddRead(*echo);
    250 
    251   AddReadEOF();
    252 
    253   CapturingBoundNetLog log;
    254 
    255   OrderedSocketData data(GetReads(), GetNumReads(),
    256                          GetWrites(), GetNumWrites());
    257   MockConnect connect_data(SYNCHRONOUS, OK);
    258   data.set_connect_data(connect_data);
    259 
    260   session_deps_.socket_factory->AddSocketDataProvider(&data);
    261 
    262   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    263 
    264   base::WeakPtr<SpdyStream> stream =
    265       CreateStreamSynchronously(
    266           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
    267   ASSERT_TRUE(stream.get() != NULL);
    268 
    269   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    270   stream->SetDelegate(&delegate);
    271 
    272   EXPECT_FALSE(stream->HasUrlFromHeaders());
    273 
    274   scoped_ptr<SpdyHeaderBlock> headers(
    275       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    276   EXPECT_EQ(ERR_IO_PENDING,
    277             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    278   EXPECT_TRUE(stream->HasUrlFromHeaders());
    279   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    280 
    281   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    282 
    283   const SpdyStreamId stream_id = delegate.stream_id();
    284 
    285   EXPECT_TRUE(delegate.send_headers_completed());
    286   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    287   EXPECT_EQ("HTTP/1.1",
    288             delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
    289   EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
    290             delegate.TakeReceivedData());
    291   EXPECT_TRUE(data.at_write_eof());
    292 
    293   // Check that the NetLog was filled reasonably.
    294   net::CapturingNetLog::CapturedEntryList entries;
    295   log.GetEntries(&entries);
    296   EXPECT_LT(0u, entries.size());
    297 
    298   // Check that we logged SPDY_STREAM_ERROR correctly.
    299   int pos = net::ExpectLogContainsSomewhere(
    300       entries, 0,
    301       net::NetLog::TYPE_SPDY_STREAM_ERROR,
    302       net::NetLog::PHASE_NONE);
    303 
    304   int stream_id2;
    305   ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
    306   EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
    307 }
    308 
    309 // Make sure that large blocks of data are properly split up into
    310 // frame-sized chunks for a request/response (i.e., an HTTP-like)
    311 // stream.
    312 TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
    313   GURL url(kStreamUrl);
    314 
    315   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    316 
    317   scoped_ptr<SpdyFrame> req(
    318       spdy_util_.ConstructSpdyPost(
    319           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    320   AddWrite(*req);
    321 
    322   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
    323   scoped_ptr<SpdyFrame> chunk(
    324       spdy_util_.ConstructSpdyBodyFrame(
    325           1, chunk_data.data(), chunk_data.length(), false));
    326   AddWrite(*chunk);
    327   AddWrite(*chunk);
    328 
    329   scoped_ptr<SpdyFrame> last_chunk(
    330       spdy_util_.ConstructSpdyBodyFrame(
    331           1, chunk_data.data(), chunk_data.length(), true));
    332   AddWrite(*last_chunk);
    333 
    334   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
    335   AddRead(*resp);
    336 
    337   AddReadEOF();
    338 
    339   OrderedSocketData data(GetReads(), GetNumReads(),
    340                          GetWrites(), GetNumWrites());
    341   MockConnect connect_data(SYNCHRONOUS, OK);
    342   data.set_connect_data(connect_data);
    343 
    344   session_deps_.socket_factory->AddSocketDataProvider(&data);
    345 
    346   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    347 
    348   base::WeakPtr<SpdyStream> stream =
    349       CreateStreamSynchronously(
    350           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    351   ASSERT_TRUE(stream.get() != NULL);
    352 
    353   std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
    354   StreamDelegateWithBody delegate(stream, body_data);
    355   stream->SetDelegate(&delegate);
    356 
    357   EXPECT_FALSE(stream->HasUrlFromHeaders());
    358 
    359   scoped_ptr<SpdyHeaderBlock> headers(
    360       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    361   EXPECT_EQ(ERR_IO_PENDING,
    362             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    363   EXPECT_TRUE(stream->HasUrlFromHeaders());
    364   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    365 
    366   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    367 
    368   EXPECT_TRUE(delegate.send_headers_completed());
    369   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    370   EXPECT_EQ("HTTP/1.1",
    371             delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
    372   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
    373   EXPECT_TRUE(data.at_write_eof());
    374 }
    375 
    376 // Make sure that large blocks of data are properly split up into
    377 // frame-sized chunks for a bidirectional (i.e., non-HTTP-like)
    378 // stream.
    379 TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
    380   GURL url(kStreamUrl);
    381 
    382   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    383 
    384   scoped_ptr<SpdyFrame> req(
    385       spdy_util_.ConstructSpdyPost(
    386           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    387   AddWrite(*req);
    388 
    389   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
    390   AddRead(*resp);
    391 
    392   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
    393   scoped_ptr<SpdyFrame> chunk(
    394       spdy_util_.ConstructSpdyBodyFrame(
    395           1, chunk_data.data(), chunk_data.length(), false));
    396   AddWrite(*chunk);
    397   AddWrite(*chunk);
    398   AddWrite(*chunk);
    399 
    400   AddReadEOF();
    401 
    402   OrderedSocketData data(GetReads(), GetNumReads(),
    403                          GetWrites(), GetNumWrites());
    404   MockConnect connect_data(SYNCHRONOUS, OK);
    405   data.set_connect_data(connect_data);
    406 
    407   session_deps_.socket_factory->AddSocketDataProvider(&data);
    408 
    409   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    410 
    411   base::WeakPtr<SpdyStream> stream =
    412       CreateStreamSynchronously(
    413           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
    414   ASSERT_TRUE(stream.get() != NULL);
    415 
    416   std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
    417   StreamDelegateSendImmediate delegate(stream, body_data);
    418   stream->SetDelegate(&delegate);
    419 
    420   EXPECT_FALSE(stream->HasUrlFromHeaders());
    421 
    422   scoped_ptr<SpdyHeaderBlock> headers(
    423       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    424   EXPECT_EQ(ERR_IO_PENDING,
    425             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    426   EXPECT_TRUE(stream->HasUrlFromHeaders());
    427   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    428 
    429   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    430 
    431   EXPECT_TRUE(delegate.send_headers_completed());
    432   EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
    433   EXPECT_EQ("HTTP/1.1",
    434             delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
    435   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
    436   EXPECT_TRUE(data.at_write_eof());
    437 }
    438 
    439 // Receiving a header with uppercase ASCII should result in a protocol
    440 // error.
    441 TEST_P(SpdyStreamTest, UpperCaseHeaders) {
    442   GURL url(kStreamUrl);
    443 
    444   session_ =
    445       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    446 
    447   scoped_ptr<SpdyFrame> syn(
    448       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    449   AddWrite(*syn);
    450 
    451   const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
    452   scoped_ptr<SpdyFrame>
    453       reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
    454   AddRead(*reply);
    455 
    456   scoped_ptr<SpdyFrame> rst(
    457       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
    458   AddWrite(*rst);
    459 
    460   AddReadEOF();
    461 
    462   DeterministicSocketData data(GetReads(), GetNumReads(),
    463                                GetWrites(), GetNumWrites());
    464   MockConnect connect_data(SYNCHRONOUS, OK);
    465   data.set_connect_data(connect_data);
    466 
    467   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    468 
    469   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    470 
    471   base::WeakPtr<SpdyStream> stream =
    472       CreateStreamSynchronously(
    473           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    474   ASSERT_TRUE(stream.get() != NULL);
    475 
    476   StreamDelegateDoNothing delegate(stream);
    477   stream->SetDelegate(&delegate);
    478 
    479   EXPECT_FALSE(stream->HasUrlFromHeaders());
    480 
    481   scoped_ptr<SpdyHeaderBlock> headers(
    482       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    483   EXPECT_EQ(ERR_IO_PENDING,
    484             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    485   EXPECT_TRUE(stream->HasUrlFromHeaders());
    486   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    487 
    488   data.RunFor(4);
    489 
    490   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
    491 }
    492 
    493 // Receiving a header with uppercase ASCII should result in a protocol
    494 // error even for a push stream.
    495 TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
    496   GURL url(kStreamUrl);
    497 
    498   session_ =
    499       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    500 
    501   scoped_ptr<SpdyFrame> syn(
    502       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    503   AddWrite(*syn);
    504 
    505   scoped_ptr<SpdyFrame>
    506       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    507   AddRead(*reply);
    508 
    509   const char* const extra_headers[] = {"X-UpperCase", "yes"};
    510   scoped_ptr<SpdyFrame>
    511       push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
    512   AddRead(*push);
    513 
    514   scoped_ptr<SpdyFrame> rst(
    515       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
    516   AddWrite(*rst);
    517 
    518   AddReadEOF();
    519 
    520   DeterministicSocketData data(GetReads(), GetNumReads(),
    521                                GetWrites(), GetNumWrites());
    522   MockConnect connect_data(SYNCHRONOUS, OK);
    523   data.set_connect_data(connect_data);
    524 
    525   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    526 
    527   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    528 
    529   base::WeakPtr<SpdyStream> stream =
    530       CreateStreamSynchronously(
    531           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    532   ASSERT_TRUE(stream.get() != NULL);
    533 
    534   StreamDelegateDoNothing delegate(stream);
    535   stream->SetDelegate(&delegate);
    536 
    537   EXPECT_FALSE(stream->HasUrlFromHeaders());
    538 
    539   scoped_ptr<SpdyHeaderBlock> headers(
    540       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    541   EXPECT_EQ(ERR_IO_PENDING,
    542             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    543   EXPECT_TRUE(stream->HasUrlFromHeaders());
    544   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    545 
    546   data.RunFor(4);
    547 
    548   base::WeakPtr<SpdyStream> push_stream;
    549   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    550   EXPECT_FALSE(push_stream);
    551 
    552   data.RunFor(1);
    553 
    554   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    555 }
    556 
    557 // Receiving a header with uppercase ASCII in a HEADERS frame should
    558 // result in a protocol error.
    559 TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
    560   GURL url(kStreamUrl);
    561 
    562   session_ =
    563       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    564 
    565   scoped_ptr<SpdyFrame> syn(
    566       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    567   AddWrite(*syn);
    568 
    569   scoped_ptr<SpdyFrame>
    570       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    571   AddRead(*reply);
    572 
    573   scoped_ptr<SpdyFrame>
    574       push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
    575   AddRead(*push);
    576 
    577   scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
    578   (*late_headers)["X-UpperCase"] = "yes";
    579   scoped_ptr<SpdyFrame> headers_frame(
    580       spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
    581                                            false,
    582                                            2,
    583                                            LOWEST,
    584                                            HEADERS,
    585                                            CONTROL_FLAG_NONE,
    586                                            0));
    587   AddRead(*headers_frame);
    588 
    589   scoped_ptr<SpdyFrame> rst(
    590       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
    591   AddWrite(*rst);
    592 
    593   AddReadEOF();
    594 
    595   DeterministicSocketData data(GetReads(), GetNumReads(),
    596                                GetWrites(), GetNumWrites());
    597   MockConnect connect_data(SYNCHRONOUS, OK);
    598   data.set_connect_data(connect_data);
    599 
    600   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    601 
    602   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    603 
    604   base::WeakPtr<SpdyStream> stream =
    605       CreateStreamSynchronously(
    606           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    607   ASSERT_TRUE(stream.get() != NULL);
    608 
    609   StreamDelegateDoNothing delegate(stream);
    610   stream->SetDelegate(&delegate);
    611 
    612   EXPECT_FALSE(stream->HasUrlFromHeaders());
    613 
    614   scoped_ptr<SpdyHeaderBlock> headers(
    615       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    616   EXPECT_EQ(ERR_IO_PENDING,
    617             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    618   EXPECT_TRUE(stream->HasUrlFromHeaders());
    619   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    620 
    621   data.RunFor(3);
    622 
    623   base::WeakPtr<SpdyStream> push_stream;
    624   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    625   EXPECT_TRUE(push_stream);
    626 
    627   data.RunFor(1);
    628 
    629   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    630   EXPECT_FALSE(push_stream);
    631 
    632   data.RunFor(2);
    633 
    634   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    635 }
    636 
    637 // Receiving a duplicate header in a HEADERS frame should result in a
    638 // protocol error.
    639 TEST_P(SpdyStreamTest, DuplicateHeaders) {
    640   GURL url(kStreamUrl);
    641 
    642   session_ =
    643       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    644 
    645   scoped_ptr<SpdyFrame> syn(
    646       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
    647   AddWrite(*syn);
    648 
    649   scoped_ptr<SpdyFrame>
    650       reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    651   AddRead(*reply);
    652 
    653   scoped_ptr<SpdyFrame>
    654       push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
    655   AddRead(*push);
    656 
    657   scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
    658   (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
    659   scoped_ptr<SpdyFrame> headers_frame(
    660       spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
    661                                            false,
    662                                            2,
    663                                            LOWEST,
    664                                            HEADERS,
    665                                            CONTROL_FLAG_NONE,
    666                                            0));
    667   AddRead(*headers_frame);
    668 
    669   scoped_ptr<SpdyFrame> rst(
    670       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
    671   AddWrite(*rst);
    672 
    673   AddReadEOF();
    674 
    675   DeterministicSocketData data(GetReads(), GetNumReads(),
    676                                GetWrites(), GetNumWrites());
    677   MockConnect connect_data(SYNCHRONOUS, OK);
    678   data.set_connect_data(connect_data);
    679 
    680   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    681 
    682   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    683 
    684   base::WeakPtr<SpdyStream> stream =
    685       CreateStreamSynchronously(
    686           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    687   ASSERT_TRUE(stream.get() != NULL);
    688 
    689   StreamDelegateDoNothing delegate(stream);
    690   stream->SetDelegate(&delegate);
    691 
    692   EXPECT_FALSE(stream->HasUrlFromHeaders());
    693 
    694   scoped_ptr<SpdyHeaderBlock> headers(
    695       spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
    696   EXPECT_EQ(ERR_IO_PENDING,
    697             stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
    698   EXPECT_TRUE(stream->HasUrlFromHeaders());
    699   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    700 
    701   data.RunFor(3);
    702 
    703   base::WeakPtr<SpdyStream> push_stream;
    704   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    705   EXPECT_TRUE(push_stream);
    706 
    707   data.RunFor(1);
    708 
    709   EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
    710   EXPECT_FALSE(push_stream);
    711 
    712   data.RunFor(2);
    713 
    714   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    715 }
    716 
    717 // The tests below are only for SPDY/3 and above.
    718 
    719 // Call IncreaseSendWindowSize on a stream with a large enough delta
    720 // to overflow an int32. The SpdyStream should handle that case
    721 // gracefully.
    722 TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
    723   if (spdy_util_.protocol() < kProtoSPDY3)
    724     return;
    725 
    726   session_ =
    727       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    728 
    729   scoped_ptr<SpdyFrame> req(
    730       spdy_util_.ConstructSpdyPost(
    731           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    732   AddWrite(*req);
    733 
    734   // Triggered by the overflowing call to IncreaseSendWindowSize
    735   // below.
    736   scoped_ptr<SpdyFrame> rst(
    737       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
    738   AddWrite(*rst);
    739 
    740   AddReadEOF();
    741 
    742   CapturingBoundNetLog log;
    743 
    744   DeterministicSocketData data(GetReads(), GetNumReads(),
    745                                GetWrites(), GetNumWrites());
    746   MockConnect connect_data(SYNCHRONOUS, OK);
    747   data.set_connect_data(connect_data);
    748 
    749   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    750 
    751   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    752   GURL url(kStreamUrl);
    753 
    754   base::WeakPtr<SpdyStream> stream =
    755       CreateStreamSynchronously(
    756           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
    757   ASSERT_TRUE(stream.get() != NULL);
    758   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    759   stream->SetDelegate(&delegate);
    760 
    761   scoped_ptr<SpdyHeaderBlock> headers(
    762       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    763   EXPECT_EQ(ERR_IO_PENDING,
    764             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    765   EXPECT_TRUE(stream->HasUrlFromHeaders());
    766   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    767 
    768   data.RunFor(1);
    769 
    770   int32 old_send_window_size = stream->send_window_size();
    771   ASSERT_GT(old_send_window_size, 0);
    772   int32 delta_window_size = kint32max - old_send_window_size + 1;
    773   stream->IncreaseSendWindowSize(delta_window_size);
    774   EXPECT_EQ(NULL, stream.get());
    775 
    776   data.RunFor(2);
    777 
    778   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
    779 }
    780 
    781 // Functions used with
    782 // RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
    783 
    784 void StallStream(const base::WeakPtr<SpdyStream>& stream) {
    785   // Reduce the send window size to 0 to stall.
    786   while (stream->send_window_size() > 0) {
    787     stream->DecreaseSendWindowSize(
    788         std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
    789   }
    790 }
    791 
    792 void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
    793                                   int32 delta_window_size) {
    794   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    795   stream->IncreaseSendWindowSize(delta_window_size);
    796   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    797 }
    798 
    799 void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
    800                                 int32 delta_window_size) {
    801   // Make sure that negative adjustments are handled properly.
    802   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    803   stream->AdjustSendWindowSize(-delta_window_size);
    804   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    805   stream->AdjustSendWindowSize(+delta_window_size);
    806   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    807   stream->AdjustSendWindowSize(+delta_window_size);
    808   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    809 }
    810 
    811 // Given an unstall function, runs a test to make sure that a
    812 // request/response (i.e., an HTTP-like) stream resumes after a stall
    813 // and unstall.
    814 void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
    815     const UnstallFunction& unstall_function) {
    816   GURL url(kStreamUrl);
    817 
    818   session_ =
    819       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    820 
    821   scoped_ptr<SpdyFrame> req(
    822       spdy_util_.ConstructSpdyPost(
    823           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    824   AddWrite(*req);
    825 
    826   scoped_ptr<SpdyFrame> body(
    827       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
    828   AddWrite(*body);
    829 
    830   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    831   AddRead(*resp);
    832 
    833   AddReadEOF();
    834 
    835   DeterministicSocketData data(GetReads(), GetNumReads(),
    836                                GetWrites(), GetNumWrites());
    837   MockConnect connect_data(SYNCHRONOUS, OK);
    838   data.set_connect_data(connect_data);
    839 
    840   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    841 
    842   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    843 
    844   base::WeakPtr<SpdyStream> stream =
    845       CreateStreamSynchronously(
    846           SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
    847   ASSERT_TRUE(stream.get() != NULL);
    848 
    849   StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
    850   stream->SetDelegate(&delegate);
    851 
    852   EXPECT_FALSE(stream->HasUrlFromHeaders());
    853   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    854 
    855   scoped_ptr<SpdyHeaderBlock> headers(
    856       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    857   EXPECT_EQ(ERR_IO_PENDING,
    858             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    859   EXPECT_TRUE(stream->HasUrlFromHeaders());
    860   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    861 
    862   StallStream(stream);
    863 
    864   data.RunFor(1);
    865 
    866   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    867 
    868   unstall_function.Run(stream, kPostBodyLength);
    869 
    870   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    871 
    872   data.RunFor(3);
    873 
    874   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    875 
    876   EXPECT_TRUE(delegate.send_headers_completed());
    877   EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
    878   EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
    879   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
    880   EXPECT_TRUE(data.at_write_eof());
    881 }
    882 
    883 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
    884   if (spdy_util_.protocol() < kProtoSPDY3)
    885     return;
    886 
    887   RunResumeAfterUnstallRequestResponseTest(
    888       base::Bind(&IncreaseStreamSendWindowSize));
    889 }
    890 
    891 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
    892   if (spdy_util_.protocol() < kProtoSPDY3)
    893     return;
    894 
    895   RunResumeAfterUnstallRequestResponseTest(
    896       base::Bind(&AdjustStreamSendWindowSize));
    897 }
    898 
    899 // Given an unstall function, runs a test to make sure that a
    900 // bidirectional (i.e., non-HTTP-like) stream resumes after a stall
    901 // and unstall.
    902 void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
    903     const UnstallFunction& unstall_function) {
    904   GURL url(kStreamUrl);
    905 
    906   session_ =
    907       SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
    908 
    909   scoped_ptr<SpdyFrame> req(
    910       spdy_util_.ConstructSpdyPost(
    911           kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
    912   AddWrite(*req);
    913 
    914   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
    915   AddRead(*resp);
    916 
    917   scoped_ptr<SpdyFrame> msg(
    918       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    919   AddWrite(*msg);
    920 
    921   scoped_ptr<SpdyFrame> echo(
    922       spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
    923   AddRead(*echo);
    924 
    925   AddReadEOF();
    926 
    927   DeterministicSocketData data(GetReads(), GetNumReads(),
    928                                GetWrites(), GetNumWrites());
    929   MockConnect connect_data(SYNCHRONOUS, OK);
    930   data.set_connect_data(connect_data);
    931 
    932   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
    933 
    934   base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
    935 
    936   base::WeakPtr<SpdyStream> stream =
    937       CreateStreamSynchronously(
    938           SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
    939   ASSERT_TRUE(stream.get() != NULL);
    940 
    941   StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
    942   stream->SetDelegate(&delegate);
    943 
    944   EXPECT_FALSE(stream->HasUrlFromHeaders());
    945 
    946   scoped_ptr<SpdyHeaderBlock> headers(
    947       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
    948   EXPECT_EQ(ERR_IO_PENDING,
    949             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
    950   EXPECT_TRUE(stream->HasUrlFromHeaders());
    951   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
    952 
    953   data.RunFor(1);
    954 
    955   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    956 
    957   StallStream(stream);
    958 
    959   data.RunFor(1);
    960 
    961   EXPECT_TRUE(stream->send_stalled_by_flow_control());
    962 
    963   unstall_function.Run(stream, kPostBodyLength);
    964 
    965   EXPECT_FALSE(stream->send_stalled_by_flow_control());
    966 
    967   data.RunFor(3);
    968 
    969   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
    970 
    971   EXPECT_TRUE(delegate.send_headers_completed());
    972   EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
    973   EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
    974   EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
    975             delegate.TakeReceivedData());
    976   EXPECT_TRUE(data.at_write_eof());
    977 }
    978 
    979 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
    980   if (spdy_util_.protocol() < kProtoSPDY3)
    981     return;
    982 
    983   RunResumeAfterUnstallBidirectionalTest(
    984       base::Bind(&IncreaseStreamSendWindowSize));
    985 }
    986 
    987 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
    988   if (spdy_util_.protocol() < kProtoSPDY3)
    989     return;
    990 
    991   RunResumeAfterUnstallBidirectionalTest(
    992       base::Bind(&AdjustStreamSendWindowSize));
    993 }
    994 
    995 }  // namespace
    996 
    997 }  // namespace test
    998 
    999 }  // namespace net
   1000