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 16using base::StringPiece; 17using std::min; 18using testing::_; 19using testing::InSequence; 20using testing::Return; 21using testing::SaveArg; 22using testing::StrEq; 23using testing::StrictMock; 24 25namespace net { 26namespace test { 27namespace { 28 29const char kData1[] = "FooAndBar"; 30const char kData2[] = "EepAndBaz"; 31const size_t kDataLen = 9; 32const QuicGuid kGuid = 42; 33const QuicGuid kStreamId = 3; 34const bool kIsServer = true; 35const bool kShouldProcessData = true; 36 37class 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 64class 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 122TEST_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) 139TEST_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 153TEST_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 165TEST_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 178TEST_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 189TEST_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 225TEST_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 237TEST_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 247TEST_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 258TEST_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 271TEST_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 308TEST_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 337TEST_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 362TEST_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 391TEST_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 429TEST_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 478TEST_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 512TEST_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