Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/reliable_quic_stream.h"
      6 
      7 #include "net/quic/quic_connection.h"
      8 #include "net/quic/quic_spdy_compressor.h"
      9 #include "net/quic/quic_spdy_decompressor.h"
     10 #include "net/quic/quic_utils.h"
     11 #include "net/quic/spdy_utils.h"
     12 #include "net/quic/test_tools/quic_session_peer.h"
     13 #include "net/quic/test_tools/quic_test_utils.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 
     16 using base::StringPiece;
     17 using std::min;
     18 using testing::_;
     19 using testing::InSequence;
     20 using testing::Return;
     21 using testing::SaveArg;
     22 using testing::StrEq;
     23 using testing::StrictMock;
     24 
     25 namespace net {
     26 namespace test {
     27 namespace {
     28 
     29 const char kData1[] = "FooAndBar";
     30 const char kData2[] = "EepAndBaz";
     31 const size_t kDataLen = 9;
     32 const QuicGuid kGuid = 42;
     33 const QuicGuid kStreamId = 3;
     34 const bool kIsServer = true;
     35 const bool kShouldProcessData = true;
     36 
     37 class TestStream : public ReliableQuicStream {
     38  public:
     39   TestStream(QuicStreamId id,
     40                          QuicSession* session,
     41                          bool should_process_data)
     42       : ReliableQuicStream(id, session),
     43         should_process_data_(should_process_data) {
     44   }
     45 
     46   virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE {
     47     EXPECT_NE(0u, data_len);
     48     DVLOG(1) << "ProcessData data_len: " << data_len;
     49     data_ += string(data, data_len);
     50     return should_process_data_ ? data_len : 0;
     51   }
     52 
     53   using ReliableQuicStream::WriteData;
     54   using ReliableQuicStream::CloseReadSide;
     55   using ReliableQuicStream::CloseWriteSide;
     56 
     57   const string& data() const { return data_; }
     58 
     59  private:
     60   bool should_process_data_;
     61   string data_;
     62 };
     63 
     64 class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
     65  public:
     66   ReliableQuicStreamTest() {
     67     headers_[":host"] = "www.google.com";
     68     headers_[":path"] = "/index.hml";
     69     headers_[":scheme"] = "https";
     70     headers_["cookie"] =
     71         "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
     72         "__utmc=160408618; "
     73         "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
     74         "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
     75         "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
     76         "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
     77         "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
     78         "1zFMi5vzcns38-8_Sns; "
     79         "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
     80         "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
     81         "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
     82         "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
     83         "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
     84         "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
     85         "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
     86         "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
     87         "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
     88         "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
     89         "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
     90         "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
     91         "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
     92         "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
     93         "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
     94   }
     95 
     96   void Initialize(bool stream_should_process_data) {
     97     connection_ = new testing::StrictMock<MockConnection>(
     98         kGuid, IPEndPoint(), kIsServer);
     99     session_.reset(new testing::StrictMock<MockSession>(
    100         connection_, kIsServer));
    101     stream_.reset(new TestStream(kStreamId, session_.get(),
    102                                  stream_should_process_data));
    103     stream2_.reset(new TestStream(kStreamId + 2, session_.get(),
    104                                  stream_should_process_data));
    105     compressor_.reset(new QuicSpdyCompressor());
    106     decompressor_.reset(new QuicSpdyDecompressor);
    107     write_blocked_list_ =
    108         QuicSessionPeer::GetWriteblockedStreams(session_.get());
    109   }
    110 
    111  protected:
    112   MockConnection* connection_;
    113   scoped_ptr<MockSession> session_;
    114   scoped_ptr<TestStream> stream_;
    115   scoped_ptr<TestStream> stream2_;
    116   scoped_ptr<QuicSpdyCompressor> compressor_;
    117   scoped_ptr<QuicSpdyDecompressor> decompressor_;
    118   SpdyHeaderBlock headers_;
    119   BlockedList<QuicStreamId>* write_blocked_list_;
    120 };
    121 
    122 TEST_F(ReliableQuicStreamTest, WriteAllData) {
    123   Initialize(kShouldProcessData);
    124 
    125   connection_->options()->max_packet_length =
    126       1 + QuicPacketCreator::StreamFramePacketOverhead(
    127           connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion,
    128           PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
    129   // TODO(rch): figure out how to get StrEq working here.
    130   //EXPECT_CALL(*session_, WriteData(kStreamId, StrEq(kData1), _, _)).WillOnce(
    131   EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce(
    132       Return(QuicConsumedData(kDataLen, true)));
    133   EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed);
    134   EXPECT_TRUE(write_blocked_list_->IsEmpty());
    135 }
    136 
    137 // TODO(rtenneti): Death tests crash on OS_ANDROID.
    138 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID)
    139 TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) {
    140   Initialize(kShouldProcessData);
    141 
    142   // Write no data and no fin.  If we consume nothing we should not be write
    143   // blocked.
    144   EXPECT_DEBUG_DEATH({
    145     EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce(
    146         Return(QuicConsumedData(0, false)));
    147     stream_->WriteData(StringPiece(), false);
    148   EXPECT_TRUE(write_blocked_list_->IsEmpty());
    149   }, "");
    150 }
    151 #endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID)
    152 
    153 TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) {
    154   Initialize(kShouldProcessData);
    155 
    156   // Write some data and no fin.  If we consume some but not all of the data,
    157   // we should be write blocked a not all the data was consumed.
    158   EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce(
    159       Return(QuicConsumedData(1, false)));
    160   stream_->WriteData(StringPiece(kData1, 2), false);
    161   ASSERT_EQ(1, write_blocked_list_->NumObjects());
    162 }
    163 
    164 
    165 TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) {
    166   Initialize(kShouldProcessData);
    167 
    168   // Write some data and no fin.  If we consume all the data but not the fin,
    169   // we should be write blocked because the fin was not consumed.
    170   // (This should never actually happen as the fin should be sent out with the
    171   // last data)
    172   EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce(
    173       Return(QuicConsumedData(2, false)));
    174   stream_->WriteData(StringPiece(kData1, 2), true);
    175   ASSERT_EQ(1, write_blocked_list_->NumObjects());
    176 }
    177 
    178 TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) {
    179   Initialize(kShouldProcessData);
    180 
    181   // Write no data and a fin.  If we consume nothing we should be write blocked,
    182   // as the fin was not consumed.
    183   EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce(
    184       Return(QuicConsumedData(0, false)));
    185   stream_->WriteData(StringPiece(), true);
    186   ASSERT_EQ(1, write_blocked_list_->NumObjects());
    187 }
    188 
    189 TEST_F(ReliableQuicStreamTest, WriteData) {
    190   Initialize(kShouldProcessData);
    191 
    192   EXPECT_TRUE(write_blocked_list_->IsEmpty());
    193   connection_->options()->max_packet_length =
    194       1 + QuicPacketCreator::StreamFramePacketOverhead(
    195           connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion,
    196           PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
    197   // TODO(rch): figure out how to get StrEq working here.
    198   //EXPECT_CALL(*session_, WriteData(_, StrEq(kData1), _, _)).WillOnce(
    199   EXPECT_CALL(*session_, WriteData(_, _, _, _)).WillOnce(
    200       Return(QuicConsumedData(kDataLen - 1, false)));
    201   // The return will be kDataLen, because the last byte gets buffered.
    202   EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed);
    203   EXPECT_FALSE(write_blocked_list_->IsEmpty());
    204 
    205   // Queue a bytes_consumed write.
    206   EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed);
    207 
    208   // Make sure we get the tail of the first write followed by the bytes_consumed
    209   InSequence s;
    210   //EXPECT_CALL(*session_, WriteData(_, StrEq(&kData1[kDataLen - 1]), _, _)).
    211   EXPECT_CALL(*session_, WriteData(_, _, _, _)).
    212       WillOnce(Return(QuicConsumedData(1, false)));
    213   //EXPECT_CALL(*session_, WriteData(_, StrEq(kData2), _, _)).
    214   EXPECT_CALL(*session_, WriteData(_, _, _, _)).
    215       WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
    216   stream_->OnCanWrite();
    217 
    218   // And finally the end of the bytes_consumed
    219   //EXPECT_CALL(*session_, WriteData(_, StrEq(&kData2[kDataLen - 2]), _, _)).
    220   EXPECT_CALL(*session_, WriteData(_, _, _, _)).
    221       WillOnce(Return(QuicConsumedData(2, true)));
    222   stream_->OnCanWrite();
    223 }
    224 
    225 TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) {
    226   Initialize(kShouldProcessData);
    227 
    228   stream_->CloseReadSide();
    229   stream_->CloseWriteSide();
    230   EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
    231   EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
    232   stream_->ConnectionClose(QUIC_INTERNAL_ERROR, false);
    233   EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
    234   EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
    235 }
    236 
    237 TEST_F(ReliableQuicStreamTest, ProcessHeaders) {
    238   Initialize(kShouldProcessData);
    239 
    240   string compressed_headers = compressor_->CompressHeaders(headers_);
    241   QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
    242 
    243   stream_->OnStreamFrame(frame);
    244   EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data());
    245 }
    246 
    247 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) {
    248   Initialize(kShouldProcessData);
    249 
    250   string compressed_headers = compressor_->CompressHeaders(headers_);
    251   compressed_headers.replace(0, 1, 1, '\xFF');  // Illegal header id.
    252   QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
    253 
    254   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID));
    255   stream_->OnStreamFrame(frame);
    256 }
    257 
    258 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) {
    259   Initialize(kShouldProcessData);
    260 
    261   string compressed_headers = compressor_->CompressHeaders(headers_);
    262   string body = "this is the body";
    263   string data = compressed_headers + body;
    264   QuicStreamFrame frame(kStreamId, false, 0, data);
    265 
    266   stream_->OnStreamFrame(frame);
    267   EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
    268             stream_->data());
    269 }
    270 
    271 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) {
    272   Initialize(kShouldProcessData);
    273 
    274   string compressed_headers = compressor_->CompressHeaders(headers_);
    275   string body = "this is the body";
    276   string data = compressed_headers + body;
    277 
    278   for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
    279     Initialize(kShouldProcessData);
    280     for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
    281       size_t remaining_data = data.length() - offset;
    282       StringPiece fragment(data.data() + offset,
    283                            min(fragment_size, remaining_data));
    284       QuicStreamFrame frame(kStreamId, false, offset, fragment);
    285 
    286       stream_->OnStreamFrame(frame);
    287     }
    288     ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
    289               stream_->data()) << "fragment_size: " << fragment_size;
    290   }
    291 
    292   for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
    293     Initialize(kShouldProcessData);
    294 
    295     StringPiece fragment1(data.data(), split_point);
    296     QuicStreamFrame frame1(kStreamId, false, 0, fragment1);
    297     stream_->OnStreamFrame(frame1);
    298 
    299     StringPiece fragment2(data.data() + split_point, data.size() - split_point);
    300     QuicStreamFrame frame2(kStreamId, false, split_point, fragment2);
    301     stream_->OnStreamFrame(frame2);
    302 
    303     ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
    304               stream_->data()) << "split_point: " << split_point;
    305   }
    306 }
    307 
    308 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) {
    309   Initialize(!kShouldProcessData);
    310 
    311   string compressed_headers = compressor_->CompressHeaders(headers_);
    312   string body = "this is the body";
    313   string data = compressed_headers + body;
    314   QuicStreamFrame frame(kStreamId, false, 0, data);
    315   string uncompressed_headers =
    316       SpdyUtils::SerializeUncompressedHeaders(headers_);
    317   string uncompressed_data = uncompressed_headers + body;
    318 
    319   stream_->OnStreamFrame(frame);
    320   EXPECT_EQ(uncompressed_headers, stream_->data());
    321 
    322   char buffer[2048];
    323   ASSERT_LT(data.length(), arraysize(buffer));
    324   struct iovec vec;
    325   vec.iov_base = buffer;
    326   vec.iov_len = arraysize(buffer);
    327 
    328   size_t bytes_read = stream_->Readv(&vec, 1);
    329   EXPECT_EQ(uncompressed_headers.length(), bytes_read);
    330   EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read));
    331 
    332   bytes_read = stream_->Readv(&vec, 1);
    333   EXPECT_EQ(body.length(), bytes_read);
    334   EXPECT_EQ(body, string(buffer, bytes_read));
    335 }
    336 
    337 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
    338   Initialize(!kShouldProcessData);
    339 
    340   string compressed_headers = compressor_->CompressHeaders(headers_);
    341   string body = "this is the body";
    342   string data = compressed_headers + body;
    343   QuicStreamFrame frame(kStreamId, false, 0, data);
    344   string uncompressed_headers =
    345       SpdyUtils::SerializeUncompressedHeaders(headers_);
    346   string uncompressed_data = uncompressed_headers + body;
    347 
    348   stream_->OnStreamFrame(frame);
    349   EXPECT_EQ(uncompressed_headers, stream_->data());
    350 
    351   char buffer[1];
    352   struct iovec vec;
    353   vec.iov_base = buffer;
    354   vec.iov_len = arraysize(buffer);
    355   for (size_t i = 0; i < uncompressed_data.length(); ++i) {
    356     size_t bytes_read = stream_->Readv(&vec, 1);
    357     ASSERT_EQ(1u, bytes_read);
    358     EXPECT_EQ(uncompressed_data.data()[i], buffer[0]);
    359   }
    360 }
    361 
    362 TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
    363   Initialize(!kShouldProcessData);
    364 
    365   string compressed_headers = compressor_->CompressHeaders(headers_);
    366   string body = "this is the body";
    367   string data = compressed_headers + body;
    368   QuicStreamFrame frame(kStreamId, false, 0, data);
    369   string uncompressed_headers =
    370       SpdyUtils::SerializeUncompressedHeaders(headers_);
    371   string uncompressed_data = uncompressed_headers + body;
    372 
    373   stream_->OnStreamFrame(frame);
    374   EXPECT_EQ(uncompressed_headers, stream_->data());
    375 
    376   char buffer1[1];
    377   char buffer2[1];
    378   struct iovec vec[2];
    379   vec[0].iov_base = buffer1;
    380   vec[0].iov_len = arraysize(buffer1);
    381   vec[1].iov_base = buffer2;
    382   vec[1].iov_len = arraysize(buffer2);
    383   for (size_t i = 0; i < uncompressed_data.length(); i += 2) {
    384     size_t bytes_read = stream_->Readv(vec, 2);
    385     ASSERT_EQ(2u, bytes_read) << i;
    386     ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i;
    387     ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i;
    388   }
    389 }
    390 
    391 TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) {
    392   Initialize(kShouldProcessData);
    393 
    394   string compressed_headers1 = compressor_->CompressHeaders(headers_);
    395   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
    396   string decompressed_headers1 =
    397       SpdyUtils::SerializeUncompressedHeaders(headers_);
    398 
    399   headers_["content-type"] = "text/plain";
    400   string compressed_headers2 = compressor_->CompressHeaders(headers_);
    401   // Corrupt the compressed data.
    402   compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1;
    403   QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2);
    404   string decompressed_headers2 =
    405       SpdyUtils::SerializeUncompressedHeaders(headers_);
    406 
    407   // Deliver frame2 to stream2 out of order.  The decompressor is not
    408   // available yet, so no data will be processed.  The compressed data
    409   // will be buffered until OnDecompressorAvailable() is called
    410   // to process it.
    411   stream2_->OnStreamFrame(frame2);
    412   EXPECT_EQ("", stream2_->data());
    413 
    414   // Now deliver frame1 to stream1.  The decompressor is available so
    415   // the data will be processed, and the decompressor will become
    416   // available for stream2.
    417   stream_->OnStreamFrame(frame1);
    418   EXPECT_EQ(decompressed_headers1, stream_->data());
    419 
    420   // Verify that the decompressor is available, and inform stream2
    421   // that it can now decompress the buffered compressed data.    Since
    422   // the compressed data is corrupt, the stream will shutdown the session.
    423   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
    424   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE));
    425   stream2_->OnDecompressorAvailable();
    426   EXPECT_EQ("", stream2_->data());
    427 }
    428 
    429 TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) {
    430   Initialize(kShouldProcessData);
    431 
    432   string compressed_headers1 = compressor_->CompressHeaders(headers_);
    433   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
    434   string decompressed_headers1 =
    435       SpdyUtils::SerializeUncompressedHeaders(headers_);
    436 
    437   headers_["content-type"] = "text/plain";
    438   string compressed_headers2 = compressor_->CompressHeaders(headers_);
    439   string partial_compressed_headers =
    440       compressed_headers2.substr(0, compressed_headers2.length() / 2);
    441   QuicStreamFrame frame2(stream2_->id(), false, 0, partial_compressed_headers);
    442   string decompressed_headers2 =
    443       SpdyUtils::SerializeUncompressedHeaders(headers_);
    444 
    445   // Deliver frame2 to stream2 out of order.  The decompressor is not
    446   // available yet, so no data will be processed.  The compressed data
    447   // will be buffered until OnDecompressorAvailable() is called
    448   // to process it.
    449   stream2_->OnStreamFrame(frame2);
    450   EXPECT_EQ("", stream2_->data());
    451 
    452   // Now deliver frame1 to stream1.  The decompressor is available so
    453   // the data will be processed, and the decompressor will become
    454   // available for stream2.
    455   stream_->OnStreamFrame(frame1);
    456   EXPECT_EQ(decompressed_headers1, stream_->data());
    457 
    458   // Verify that the decompressor is available, and inform stream2
    459   // that it can now decompress the buffered compressed data.  Since
    460   // the compressed data is incomplete it will not be passed to
    461   // the stream.
    462   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
    463   stream2_->OnDecompressorAvailable();
    464   EXPECT_EQ("", stream2_->data());
    465 
    466   // Now send remaining data and verify that we have now received the
    467   // compressed headers.
    468   string remaining_compressed_headers =
    469       compressed_headers2.substr(partial_compressed_headers.length());
    470 
    471   QuicStreamFrame frame3(stream2_->id(), false,
    472                          partial_compressed_headers.length(),
    473                          remaining_compressed_headers);
    474   stream2_->OnStreamFrame(frame3);
    475   EXPECT_EQ(decompressed_headers2, stream2_->data());
    476 }
    477 
    478 TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) {
    479   Initialize(kShouldProcessData);
    480 
    481   string compressed_headers1 = compressor_->CompressHeaders(headers_);
    482   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
    483   string decompressed_headers1 =
    484       SpdyUtils::SerializeUncompressedHeaders(headers_);
    485 
    486   headers_["content-type"] = "text/plain";
    487   string compressed_headers2 = compressor_->CompressHeaders(headers_);
    488   QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2);
    489   string decompressed_headers2 =
    490       SpdyUtils::SerializeUncompressedHeaders(headers_);
    491 
    492   // Deliver frame2 to stream2 out of order.  The decompressor is not
    493   // available yet, so no data will be processed.  The compressed data
    494   // will be buffered until OnDecompressorAvailable() is called
    495   // to process it.
    496   stream2_->OnStreamFrame(frame2);
    497   EXPECT_EQ("", stream2_->data());
    498 
    499   // Now deliver frame1 to stream1.  The decompressor is available so
    500   // the data will be processed, and the decompressor will become
    501   // available for stream2.
    502   stream_->OnStreamFrame(frame1);
    503   EXPECT_EQ(decompressed_headers1, stream_->data());
    504 
    505   // Verify that the decompressor is available, and inform stream2
    506   // that it can now decompress the buffered compressed data.
    507   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
    508   stream2_->OnDecompressorAvailable();
    509   EXPECT_EQ(decompressed_headers2, stream2_->data());
    510 }
    511 
    512 TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) {
    513   Initialize(!kShouldProcessData);
    514 
    515   string compressed_headers = compressor_->CompressHeaders(headers_);
    516   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers);
    517   string decompressed_headers =
    518       SpdyUtils::SerializeUncompressedHeaders(headers_);
    519 
    520   // Send the headers to the stream and verify they were decompressed.
    521   stream_->OnStreamFrame(frame1);
    522   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
    523 
    524   // Verify that we are now able to handle the body data,
    525   // even though the stream has not processed the headers.
    526   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID))
    527       .Times(0);
    528   QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
    529                          "body data");
    530   stream_->OnStreamFrame(frame2);
    531 }
    532 
    533 }  // namespace
    534 }  // namespace test
    535 }  // namespace net
    536