- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / reliable_quic_stream_test.cc
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   WriteBlockedList<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   EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
130       Return(QuicConsumedData(kDataLen, true)));
131   EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed);
132   EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams());
133 }
134
135 // TODO(rtenneti): Death tests crash on OS_ANDROID.
136 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID)
137 TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) {
138   Initialize(kShouldProcessData);
139
140   // Write no data and no fin.  If we consume nothing we should not be write
141   // blocked.
142   EXPECT_DEBUG_DEATH({
143     EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
144         Return(QuicConsumedData(0, false)));
145     stream_->WriteData(StringPiece(), false);
146     EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams());
147   }, "");
148 }
149 #endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID)
150
151 TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) {
152   Initialize(kShouldProcessData);
153
154   // Write some data and no fin.  If we consume some but not all of the data,
155   // we should be write blocked a not all the data was consumed.
156   EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
157       Return(QuicConsumedData(1, false)));
158   stream_->WriteData(StringPiece(kData1, 2), false);
159   ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams());
160 }
161
162
163 TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) {
164   Initialize(kShouldProcessData);
165
166   // Write some data and no fin.  If we consume all the data but not the fin,
167   // we should be write blocked because the fin was not consumed.
168   // (This should never actually happen as the fin should be sent out with the
169   // last data)
170   EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
171       Return(QuicConsumedData(2, false)));
172   stream_->WriteData(StringPiece(kData1, 2), true);
173   ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams());
174 }
175
176 TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) {
177   Initialize(kShouldProcessData);
178
179   // Write no data and a fin.  If we consume nothing we should be write blocked,
180   // as the fin was not consumed.
181   EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
182       Return(QuicConsumedData(0, false)));
183   stream_->WriteData(StringPiece(), true);
184   ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams());
185 }
186
187 TEST_F(ReliableQuicStreamTest, WriteData) {
188   Initialize(kShouldProcessData);
189
190   EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams());
191   connection_->options()->max_packet_length =
192       1 + QuicPacketCreator::StreamFramePacketOverhead(
193           connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion,
194           PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
195   EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).WillOnce(
196       Return(QuicConsumedData(kDataLen - 1, false)));
197   // The return will be kDataLen, because the last byte gets buffered.
198   EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed);
199   EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams());
200
201   // Queue a bytes_consumed write.
202   EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed);
203
204   // Make sure we get the tail of the first write followed by the bytes_consumed
205   InSequence s;
206   EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
207       WillOnce(Return(QuicConsumedData(1, false)));
208   EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
209       WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
210   stream_->OnCanWrite();
211
212   // And finally the end of the bytes_consumed.
213   EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
214       WillOnce(Return(QuicConsumedData(2, true)));
215   stream_->OnCanWrite();
216 }
217
218 TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) {
219   Initialize(kShouldProcessData);
220
221   stream_->CloseReadSide();
222   stream_->CloseWriteSide();
223   EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
224   EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
225   stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, false);
226   EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
227   EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
228 }
229
230 TEST_F(ReliableQuicStreamTest, ProcessHeaders) {
231   Initialize(kShouldProcessData);
232
233   string compressed_headers =
234       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
235   QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
236
237   stream_->OnStreamFrame(frame);
238   EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data());
239   EXPECT_EQ(static_cast<QuicPriority>(kHighestPriority),
240             stream_->EffectivePriority());
241 }
242
243 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) {
244   Initialize(kShouldProcessData);
245
246   string compressed_headers =
247       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
248   compressed_headers.replace(4, 1, 1, '\xFF');  // Illegal header id.
249   QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
250
251   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID));
252   stream_->OnStreamFrame(frame);
253 }
254
255 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) {
256   Initialize(kShouldProcessData);
257
258   string compressed_headers =
259       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
260   string body = "this is the body";
261   string data = compressed_headers + body;
262   QuicStreamFrame frame(kStreamId, false, 0, data);
263
264   stream_->OnStreamFrame(frame);
265   EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
266             stream_->data());
267 }
268
269 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) {
270   Initialize(kShouldProcessData);
271
272   string compressed_headers =
273       compressor_->CompressHeadersWithPriority(kLowestPriority, headers_);
274   string body = "this is the body";
275   string data = compressed_headers + body;
276
277   for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
278     Initialize(kShouldProcessData);
279     for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
280       size_t remaining_data = data.length() - offset;
281       StringPiece fragment(data.data() + offset,
282                            min(fragment_size, remaining_data));
283       QuicStreamFrame frame(kStreamId, false, offset, fragment);
284
285       stream_->OnStreamFrame(frame);
286     }
287     ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
288               stream_->data()) << "fragment_size: " << fragment_size;
289   }
290
291   for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
292     Initialize(kShouldProcessData);
293
294     StringPiece fragment1(data.data(), split_point);
295     QuicStreamFrame frame1(kStreamId, false, 0, fragment1);
296     stream_->OnStreamFrame(frame1);
297
298     StringPiece fragment2(data.data() + split_point, data.size() - split_point);
299     QuicStreamFrame frame2(kStreamId, false, split_point, fragment2);
300     stream_->OnStreamFrame(frame2);
301
302     ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
303               stream_->data()) << "split_point: " << split_point;
304   }
305   EXPECT_EQ(static_cast<QuicPriority>(kLowestPriority),
306             stream_->EffectivePriority());
307 }
308
309 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) {
310   Initialize(!kShouldProcessData);
311
312   string compressed_headers =
313       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
314   string body = "this is the body";
315   string data = compressed_headers + body;
316   QuicStreamFrame frame(kStreamId, false, 0, data);
317   string uncompressed_headers =
318       SpdyUtils::SerializeUncompressedHeaders(headers_);
319   string uncompressed_data = uncompressed_headers + body;
320
321   stream_->OnStreamFrame(frame);
322   EXPECT_EQ(uncompressed_headers, stream_->data());
323
324   char buffer[2048];
325   ASSERT_LT(data.length(), arraysize(buffer));
326   struct iovec vec;
327   vec.iov_base = buffer;
328   vec.iov_len = arraysize(buffer);
329
330   size_t bytes_read = stream_->Readv(&vec, 1);
331   EXPECT_EQ(uncompressed_headers.length(), bytes_read);
332   EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read));
333
334   bytes_read = stream_->Readv(&vec, 1);
335   EXPECT_EQ(body.length(), bytes_read);
336   EXPECT_EQ(body, string(buffer, bytes_read));
337 }
338
339 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
340   Initialize(!kShouldProcessData);
341
342   string compressed_headers =
343       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
344   string body = "this is the body";
345   string data = compressed_headers + body;
346   QuicStreamFrame frame(kStreamId, false, 0, data);
347   string uncompressed_headers =
348       SpdyUtils::SerializeUncompressedHeaders(headers_);
349   string uncompressed_data = uncompressed_headers + body;
350
351   stream_->OnStreamFrame(frame);
352   EXPECT_EQ(uncompressed_headers, stream_->data());
353
354   char buffer[1];
355   struct iovec vec;
356   vec.iov_base = buffer;
357   vec.iov_len = arraysize(buffer);
358   for (size_t i = 0; i < uncompressed_data.length(); ++i) {
359     size_t bytes_read = stream_->Readv(&vec, 1);
360     ASSERT_EQ(1u, bytes_read);
361     EXPECT_EQ(uncompressed_data.data()[i], buffer[0]);
362   }
363 }
364
365 TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
366   Initialize(!kShouldProcessData);
367
368   string compressed_headers =
369       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
370   string body = "this is the body";
371   string data = compressed_headers + body;
372   QuicStreamFrame frame(kStreamId, false, 0, data);
373   string uncompressed_headers =
374       SpdyUtils::SerializeUncompressedHeaders(headers_);
375   string uncompressed_data = uncompressed_headers + body;
376
377   stream_->OnStreamFrame(frame);
378   EXPECT_EQ(uncompressed_headers, stream_->data());
379
380   char buffer1[1];
381   char buffer2[1];
382   struct iovec vec[2];
383   vec[0].iov_base = buffer1;
384   vec[0].iov_len = arraysize(buffer1);
385   vec[1].iov_base = buffer2;
386   vec[1].iov_len = arraysize(buffer2);
387   for (size_t i = 0; i < uncompressed_data.length(); i += 2) {
388     size_t bytes_read = stream_->Readv(vec, 2);
389     ASSERT_EQ(2u, bytes_read) << i;
390     ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i;
391     ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i;
392   }
393 }
394
395 TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) {
396   Initialize(kShouldProcessData);
397
398   string compressed_headers1 =
399       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
400   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
401   string decompressed_headers1 =
402       SpdyUtils::SerializeUncompressedHeaders(headers_);
403
404   headers_["content-type"] = "text/plain";
405   string compressed_headers2 =
406       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
407   // Corrupt the compressed data.
408   compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1;
409   QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2);
410   string decompressed_headers2 =
411       SpdyUtils::SerializeUncompressedHeaders(headers_);
412
413   // Deliver frame2 to stream2 out of order.  The decompressor is not
414   // available yet, so no data will be processed.  The compressed data
415   // will be buffered until OnDecompressorAvailable() is called
416   // to process it.
417   stream2_->OnStreamFrame(frame2);
418   EXPECT_EQ("", stream2_->data());
419
420   // Now deliver frame1 to stream1.  The decompressor is available so
421   // the data will be processed, and the decompressor will become
422   // available for stream2.
423   stream_->OnStreamFrame(frame1);
424   EXPECT_EQ(decompressed_headers1, stream_->data());
425
426   // Verify that the decompressor is available, and inform stream2
427   // that it can now decompress the buffered compressed data.    Since
428   // the compressed data is corrupt, the stream will shutdown the session.
429   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
430   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE));
431   stream2_->OnDecompressorAvailable();
432   EXPECT_EQ("", stream2_->data());
433 }
434
435 TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) {
436   Initialize(kShouldProcessData);
437
438   string compressed_headers1 =
439       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
440   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
441   string decompressed_headers1 =
442       SpdyUtils::SerializeUncompressedHeaders(headers_);
443
444   headers_["content-type"] = "text/plain";
445   string compressed_headers2 =
446       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
447   string partial_compressed_headers =
448       compressed_headers2.substr(0, compressed_headers2.length() / 2);
449   QuicStreamFrame frame2(stream2_->id(), false, 0, partial_compressed_headers);
450   string decompressed_headers2 =
451       SpdyUtils::SerializeUncompressedHeaders(headers_);
452
453   // Deliver frame2 to stream2 out of order.  The decompressor is not
454   // available yet, so no data will be processed.  The compressed data
455   // will be buffered until OnDecompressorAvailable() is called
456   // to process it.
457   stream2_->OnStreamFrame(frame2);
458   EXPECT_EQ("", stream2_->data());
459
460   // Now deliver frame1 to stream1.  The decompressor is available so
461   // the data will be processed, and the decompressor will become
462   // available for stream2.
463   stream_->OnStreamFrame(frame1);
464   EXPECT_EQ(decompressed_headers1, stream_->data());
465
466   // Verify that the decompressor is available, and inform stream2
467   // that it can now decompress the buffered compressed data.  Since
468   // the compressed data is incomplete it will not be passed to
469   // the stream.
470   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
471   stream2_->OnDecompressorAvailable();
472   EXPECT_EQ("", stream2_->data());
473
474   // Now send remaining data and verify that we have now received the
475   // compressed headers.
476   string remaining_compressed_headers =
477       compressed_headers2.substr(partial_compressed_headers.length());
478
479   QuicStreamFrame frame3(stream2_->id(), false,
480                          partial_compressed_headers.length(),
481                          remaining_compressed_headers);
482   stream2_->OnStreamFrame(frame3);
483   EXPECT_EQ(decompressed_headers2, stream2_->data());
484 }
485
486 TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) {
487   Initialize(kShouldProcessData);
488
489   string compressed_headers1 =
490       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
491   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
492   string decompressed_headers1 =
493       SpdyUtils::SerializeUncompressedHeaders(headers_);
494
495   headers_["content-type"] = "text/plain";
496   string compressed_headers2 =
497       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
498   QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2);
499   string decompressed_headers2 =
500       SpdyUtils::SerializeUncompressedHeaders(headers_);
501
502   // Deliver frame2 to stream2 out of order.  The decompressor is not
503   // available yet, so no data will be processed.  The compressed data
504   // will be buffered until OnDecompressorAvailable() is called
505   // to process it.
506   stream2_->OnStreamFrame(frame2);
507   EXPECT_EQ("", stream2_->data());
508
509   // Now deliver frame1 to stream1.  The decompressor is available so
510   // the data will be processed, and the decompressor will become
511   // available for stream2.
512   stream_->OnStreamFrame(frame1);
513   EXPECT_EQ(decompressed_headers1, stream_->data());
514
515   // Verify that the decompressor is available, and inform stream2
516   // that it can now decompress the buffered compressed data.
517   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
518   stream2_->OnDecompressorAvailable();
519   EXPECT_EQ(decompressed_headers2, stream2_->data());
520 }
521
522 TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) {
523   Initialize(!kShouldProcessData);
524
525   string compressed_headers =
526       compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
527   QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers);
528   string decompressed_headers =
529       SpdyUtils::SerializeUncompressedHeaders(headers_);
530
531   // Send the headers to the stream and verify they were decompressed.
532   stream_->OnStreamFrame(frame1);
533   EXPECT_EQ(2u, session_->decompressor()->current_header_id());
534
535   // Verify that we are now able to handle the body data,
536   // even though the stream has not processed the headers.
537   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID))
538       .Times(0);
539   QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
540                          "body data");
541   stream_->OnStreamFrame(frame2);
542 }
543
544 }  // namespace
545 }  // namespace test
546 }  // namespace net