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.
5 #include "net/quic/reliable_quic_stream.h"
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"
16 using base::StringPiece;
19 using testing::InSequence;
20 using testing::Return;
21 using testing::SaveArg;
23 using testing::StrictMock;
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;
37 class TestStream : public ReliableQuicStream {
39 TestStream(QuicStreamId id,
41 bool should_process_data)
42 : ReliableQuicStream(id, session),
43 should_process_data_(should_process_data) {
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;
53 using ReliableQuicStream::WriteData;
54 using ReliableQuicStream::CloseReadSide;
55 using ReliableQuicStream::CloseWriteSide;
57 const string& data() const { return data_; }
60 bool should_process_data_;
64 class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
66 ReliableQuicStreamTest() {
67 headers_[":host"] = "www.google.com";
68 headers_[":path"] = "/index.hml";
69 headers_[":scheme"] = "https";
71 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
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 ";
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());
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_;
122 TEST_F(ReliableQuicStreamTest, WriteAllData) {
123 Initialize(kShouldProcessData);
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());
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);
140 // Write no data and no fin. If we consume nothing we should not be write
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());
149 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID)
151 TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) {
152 Initialize(kShouldProcessData);
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());
163 TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) {
164 Initialize(kShouldProcessData);
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
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());
176 TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) {
177 Initialize(kShouldProcessData);
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());
187 TEST_F(ReliableQuicStreamTest, WriteData) {
188 Initialize(kShouldProcessData);
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());
201 // Queue a bytes_consumed write.
202 EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed);
204 // Make sure we get the tail of the first write followed by the bytes_consumed
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();
212 // And finally the end of the bytes_consumed.
213 EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
214 WillOnce(Return(QuicConsumedData(2, true)));
215 stream_->OnCanWrite();
218 TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) {
219 Initialize(kShouldProcessData);
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());
230 TEST_F(ReliableQuicStreamTest, ProcessHeaders) {
231 Initialize(kShouldProcessData);
233 string compressed_headers =
234 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
235 QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
237 stream_->OnStreamFrame(frame);
238 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data());
239 EXPECT_EQ(static_cast<QuicPriority>(kHighestPriority),
240 stream_->EffectivePriority());
243 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) {
244 Initialize(kShouldProcessData);
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);
251 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID));
252 stream_->OnStreamFrame(frame);
255 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) {
256 Initialize(kShouldProcessData);
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);
264 stream_->OnStreamFrame(frame);
265 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
269 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) {
270 Initialize(kShouldProcessData);
272 string compressed_headers =
273 compressor_->CompressHeadersWithPriority(kLowestPriority, headers_);
274 string body = "this is the body";
275 string data = compressed_headers + body;
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);
285 stream_->OnStreamFrame(frame);
287 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
288 stream_->data()) << "fragment_size: " << fragment_size;
291 for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
292 Initialize(kShouldProcessData);
294 StringPiece fragment1(data.data(), split_point);
295 QuicStreamFrame frame1(kStreamId, false, 0, fragment1);
296 stream_->OnStreamFrame(frame1);
298 StringPiece fragment2(data.data() + split_point, data.size() - split_point);
299 QuicStreamFrame frame2(kStreamId, false, split_point, fragment2);
300 stream_->OnStreamFrame(frame2);
302 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
303 stream_->data()) << "split_point: " << split_point;
305 EXPECT_EQ(static_cast<QuicPriority>(kLowestPriority),
306 stream_->EffectivePriority());
309 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) {
310 Initialize(!kShouldProcessData);
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;
321 stream_->OnStreamFrame(frame);
322 EXPECT_EQ(uncompressed_headers, stream_->data());
325 ASSERT_LT(data.length(), arraysize(buffer));
327 vec.iov_base = buffer;
328 vec.iov_len = arraysize(buffer);
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));
334 bytes_read = stream_->Readv(&vec, 1);
335 EXPECT_EQ(body.length(), bytes_read);
336 EXPECT_EQ(body, string(buffer, bytes_read));
339 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
340 Initialize(!kShouldProcessData);
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;
351 stream_->OnStreamFrame(frame);
352 EXPECT_EQ(uncompressed_headers, stream_->data());
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]);
365 TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
366 Initialize(!kShouldProcessData);
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;
377 stream_->OnStreamFrame(frame);
378 EXPECT_EQ(uncompressed_headers, stream_->data());
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;
395 TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) {
396 Initialize(kShouldProcessData);
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_);
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_);
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
417 stream2_->OnStreamFrame(frame2);
418 EXPECT_EQ("", stream2_->data());
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());
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());
435 TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) {
436 Initialize(kShouldProcessData);
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_);
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_);
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
457 stream2_->OnStreamFrame(frame2);
458 EXPECT_EQ("", stream2_->data());
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());
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
470 EXPECT_EQ(2u, session_->decompressor()->current_header_id());
471 stream2_->OnDecompressorAvailable();
472 EXPECT_EQ("", stream2_->data());
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());
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());
486 TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) {
487 Initialize(kShouldProcessData);
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_);
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_);
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
506 stream2_->OnStreamFrame(frame2);
507 EXPECT_EQ("", stream2_->data());
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());
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());
522 TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) {
523 Initialize(!kShouldProcessData);
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_);
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());
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))
539 QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
541 stream_->OnStreamFrame(frame2);