reliable_quic_stream_test.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/reliable_quic_stream.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_connection.h" 8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/quic_spdy_compressor.h" 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/quic_spdy_decompressor.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_utils.h" 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/spdy_utils.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/test_tools/quic_session_peer.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::StringPiece; 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using std::min; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::_; 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::InSequence; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::Return; 21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using testing::SaveArg; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::StrEq; 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using testing::StrictMock; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kData1[] = "FooAndBar"; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kData2[] = "EepAndBaz"; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kDataLen = 9; 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const QuicGuid kGuid = 42; 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const QuicGuid kStreamId = 3; 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const bool kIsServer = true; 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const bool kShouldProcessData = true; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class TestStream : public ReliableQuicStream { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) TestStream(QuicStreamId id, 40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicSession* session, 41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool should_process_data) 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) : ReliableQuicStream(id, session), 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) should_process_data_(should_process_data) { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE { 47558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_NE(0u, data_len); 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "ProcessData data_len: " << data_len; 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) data_ += string(data, data_len); 50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return should_process_data_ ? data_len : 0; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) using ReliableQuicStream::WriteData; 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) using ReliableQuicStream::CloseReadSide; 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) using ReliableQuicStream::CloseWriteSide; 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const string& data() const { return data_; } 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) private: 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool should_process_data_; 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string data_; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ReliableQuicStreamTest() { 67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) headers_[":host"] = "www.google.com"; 68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) headers_[":path"] = "/index.hml"; 69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) headers_[":scheme"] = "https"; 70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch headers_["cookie"] = 71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " 72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "__utmc=160408618; " 73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX" 74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX" 75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT" 76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0" 77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh" 78558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "1zFMi5vzcns38-8_Sns; " 79558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-" 80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339" 81558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c" 82558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%" 83558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4" 84558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1" 85558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP" 86558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6" 87558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b" 88558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6" 89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG" 90558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk" 91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn" 92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr" 93558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo "; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) void Initialize(bool stream_should_process_data) { 97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) connection_ = new testing::StrictMock<MockConnection>( 98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kGuid, IPEndPoint(), kIsServer); 99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) session_.reset(new testing::StrictMock<MockSession>( 100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) connection_, kIsServer)); 101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_.reset(new TestStream(kStreamId, session_.get(), 102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_should_process_data)); 103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream2_.reset(new TestStream(kStreamId + 2, session_.get(), 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_should_process_data)); 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) compressor_.reset(new QuicSpdyCompressor()); 106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) decompressor_.reset(new QuicSpdyDecompressor); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) write_blocked_list_ = 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) QuicSessionPeer::GetWriteblockedStreams(session_.get()); 109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) protected: 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnection* connection_; 113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<MockSession> session_; 114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<TestStream> stream_; 115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<TestStream> stream2_; 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<QuicSpdyCompressor> compressor_; 117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<QuicSpdyDecompressor> decompressor_; 118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyHeaderBlock headers_; 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BlockedList<QuicStreamId>* write_blocked_list_; 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, WriteAllData) { 123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_->options()->max_packet_length = 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1 + QuicPacketCreator::StreamFramePacketOverhead( 1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PACKET_8BYTE_GUID, !kIncludeVersion, 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): figure out how to get StrEq working here. 130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) //EXPECT_CALL(*session_, WriteData(kStreamId, StrEq(kData1), _, _)).WillOnce( 131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Return(QuicConsumedData(kDataLen, true))); 133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(write_blocked_list_->IsEmpty()); 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(rtenneti): Death tests crash on OS_ANDROID. 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID) 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) { 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Initialize(kShouldProcessData); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Write no data and no fin. If we consume nothing we should not be write 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // blocked. 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_DEBUG_DEATH({ 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Return(QuicConsumedData(0, false))); 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stream_->WriteData(StringPiece(), false); 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(write_blocked_list_->IsEmpty()); 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) }, ""); 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID) 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Initialize(kShouldProcessData); 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Write some data and no fin. If we consume some but not all of the data, 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // we should be write blocked a not all the data was consumed. 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Return(QuicConsumedData(1, false))); 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stream_->WriteData(StringPiece(kData1, 2), false); 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_EQ(1, write_blocked_list_->NumObjects()); 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Initialize(kShouldProcessData); 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Write some data and no fin. If we consume all the data but not the fin, 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // we should be write blocked because the fin was not consumed. 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // (This should never actually happen as the fin should be sent out with the 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // last data) 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Return(QuicConsumedData(2, false))); 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stream_->WriteData(StringPiece(kData1, 2), true); 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_EQ(1, write_blocked_list_->NumObjects()); 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) { 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Initialize(kShouldProcessData); 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Write no data and a fin. If we consume nothing we should be write blocked, 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // as the fin was not consumed. 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Return(QuicConsumedData(0, false))); 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stream_->WriteData(StringPiece(), true); 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_EQ(1, write_blocked_list_->NumObjects()); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, WriteData) { 190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(write_blocked_list_->IsEmpty()); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_->options()->max_packet_length = 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1 + QuicPacketCreator::StreamFramePacketOverhead( 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PACKET_8BYTE_GUID, !kIncludeVersion, 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): figure out how to get StrEq working here. 198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) //EXPECT_CALL(*session_, WriteData(_, StrEq(kData1), _, _)).WillOnce( 199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*session_, WriteData(_, _, _, _)).WillOnce( 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Return(QuicConsumedData(kDataLen - 1, false))); 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The return will be kDataLen, because the last byte gets buffered. 202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed); 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_FALSE(write_blocked_list_->IsEmpty()); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Queue a bytes_consumed write. 206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure we get the tail of the first write followed by the bytes_consumed 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InSequence s; 210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) //EXPECT_CALL(*session_, WriteData(_, StrEq(&kData1[kDataLen - 1]), _, _)). 211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*session_, WriteData(_, _, _, _)). 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WillOnce(Return(QuicConsumedData(1, false))); 213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) //EXPECT_CALL(*session_, WriteData(_, StrEq(kData2), _, _)). 214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*session_, WriteData(_, _, _, _)). 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); 216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnCanWrite(); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // And finally the end of the bytes_consumed 219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) //EXPECT_CALL(*session_, WriteData(_, StrEq(&kData2[kDataLen - 2]), _, _)). 220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*session_, WriteData(_, _, _, _)). 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WillOnce(Return(QuicConsumedData(2, true))); 222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnCanWrite(); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) { 226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 227b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->CloseReadSide(); 229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->CloseWriteSide(); 230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); 231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); 232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->ConnectionClose(QUIC_INTERNAL_ERROR, false); 233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); 234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); 235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeaders) { 238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, 0, compressed_headers); 242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data()); 245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) { 248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) compressed_headers.replace(0, 1, 1, '\xFF'); // Illegal header id. 252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, 0, compressed_headers); 253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)); 255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) { 259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string body = "this is the body"; 263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string data = compressed_headers + body; 264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, 0, data); 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, 268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->data()); 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) { 272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string body = "this is the body"; 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string data = compressed_headers + body; 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) { 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (size_t offset = 0; offset < data.size(); offset += fragment_size) { 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) size_t remaining_data = data.length() - offset; 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) StringPiece fragment(data.data() + offset, 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) min(fragment_size, remaining_data)); 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, offset, fragment); 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->data()) << "fragment_size: " << fragment_size; 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 291558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 292558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) { 293558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Initialize(kShouldProcessData); 294558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 295558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch StringPiece fragment1(data.data(), split_point); 296558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame1(kStreamId, false, 0, fragment1); 297558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream_->OnStreamFrame(frame1); 298558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 299558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch StringPiece fragment2(data.data() + split_point, data.size() - split_point); 300558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame2(kStreamId, false, split_point, fragment2); 301558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream_->OnStreamFrame(frame2); 302558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 303558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, 304558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream_->data()) << "split_point: " << split_point; 305558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) { 309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(!kShouldProcessData); 310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string body = "this is the body"; 313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string data = compressed_headers + body; 314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, 0, data); 315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string uncompressed_headers = 316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::SerializeUncompressedHeaders(headers_); 317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string uncompressed_data = uncompressed_headers + body; 318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(uncompressed_headers, stream_->data()); 321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 322558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch char buffer[2048]; 323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ASSERT_LT(data.length(), arraysize(buffer)); 324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) struct iovec vec; 325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec.iov_base = buffer; 326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec.iov_len = arraysize(buffer); 327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) size_t bytes_read = stream_->Readv(&vec, 1); 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(uncompressed_headers.length(), bytes_read); 330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read)); 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bytes_read = stream_->Readv(&vec, 1); 333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(body.length(), bytes_read); 334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(body, string(buffer, bytes_read)); 335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) { 338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(!kShouldProcessData); 339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string body = "this is the body"; 342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string data = compressed_headers + body; 343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, 0, data); 344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string uncompressed_headers = 345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::SerializeUncompressedHeaders(headers_); 346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string uncompressed_data = uncompressed_headers + body; 347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(uncompressed_headers, stream_->data()); 350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char buffer[1]; 352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) struct iovec vec; 353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec.iov_base = buffer; 354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec.iov_len = arraysize(buffer); 355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (size_t i = 0; i < uncompressed_data.length(); ++i) { 356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) size_t bytes_read = stream_->Readv(&vec, 1); 357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ASSERT_EQ(1u, bytes_read); 358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(uncompressed_data.data()[i], buffer[0]); 359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { 363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(!kShouldProcessData); 364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string body = "this is the body"; 367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string data = compressed_headers + body; 368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame(kStreamId, false, 0, data); 369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string uncompressed_headers = 370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::SerializeUncompressedHeaders(headers_); 371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string uncompressed_data = uncompressed_headers + body; 372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame); 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(uncompressed_headers, stream_->data()); 375b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char buffer1[1]; 377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char buffer2[1]; 378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) struct iovec vec[2]; 379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec[0].iov_base = buffer1; 380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec[0].iov_len = arraysize(buffer1); 381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec[1].iov_base = buffer2; 382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vec[1].iov_len = arraysize(buffer2); 383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (size_t i = 0; i < uncompressed_data.length(); i += 2) { 384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) size_t bytes_read = stream_->Readv(vec, 2); 385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ASSERT_EQ(2u, bytes_read) << i; 386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i; 387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i; 388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 391558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) { 392558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Initialize(kShouldProcessData); 393558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 394558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string compressed_headers1 = compressor_->CompressHeaders(headers_); 395558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); 396558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string decompressed_headers1 = 397558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch SpdyUtils::SerializeUncompressedHeaders(headers_); 398558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 399558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch headers_["content-type"] = "text/plain"; 400558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string compressed_headers2 = compressor_->CompressHeaders(headers_); 401558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Corrupt the compressed data. 402558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1; 403558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2); 404558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string decompressed_headers2 = 405558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch SpdyUtils::SerializeUncompressedHeaders(headers_); 406558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 407558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Deliver frame2 to stream2 out of order. The decompressor is not 408558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // available yet, so no data will be processed. The compressed data 409558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // will be buffered until OnDecompressorAvailable() is called 410558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // to process it. 411558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream2_->OnStreamFrame(frame2); 412558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ("", stream2_->data()); 413558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 414558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Now deliver frame1 to stream1. The decompressor is available so 415558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the data will be processed, and the decompressor will become 416558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // available for stream2. 417558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream_->OnStreamFrame(frame1); 418558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ(decompressed_headers1, stream_->data()); 419558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 420558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Verify that the decompressor is available, and inform stream2 421558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // that it can now decompress the buffered compressed data. Since 422558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the compressed data is corrupt, the stream will shutdown the session. 423558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ(2u, session_->decompressor()->current_header_id()); 424558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE)); 425558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream2_->OnDecompressorAvailable(); 426558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ("", stream2_->data()); 427558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 428558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 429558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) { 430558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Initialize(kShouldProcessData); 431558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 432558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string compressed_headers1 = compressor_->CompressHeaders(headers_); 433558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); 434558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string decompressed_headers1 = 435558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch SpdyUtils::SerializeUncompressedHeaders(headers_); 436558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 437558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch headers_["content-type"] = "text/plain"; 438558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string compressed_headers2 = compressor_->CompressHeaders(headers_); 439558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string partial_compressed_headers = 440558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch compressed_headers2.substr(0, compressed_headers2.length() / 2); 441558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame2(stream2_->id(), false, 0, partial_compressed_headers); 442558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string decompressed_headers2 = 443558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch SpdyUtils::SerializeUncompressedHeaders(headers_); 444558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 445558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Deliver frame2 to stream2 out of order. The decompressor is not 446558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // available yet, so no data will be processed. The compressed data 447558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // will be buffered until OnDecompressorAvailable() is called 448558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // to process it. 449558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream2_->OnStreamFrame(frame2); 450558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ("", stream2_->data()); 451558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 452558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Now deliver frame1 to stream1. The decompressor is available so 453558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the data will be processed, and the decompressor will become 454558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // available for stream2. 455558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream_->OnStreamFrame(frame1); 456558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ(decompressed_headers1, stream_->data()); 457558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 458558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Verify that the decompressor is available, and inform stream2 459558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // that it can now decompress the buffered compressed data. Since 460558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the compressed data is incomplete it will not be passed to 461558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the stream. 462558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ(2u, session_->decompressor()->current_header_id()); 463558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream2_->OnDecompressorAvailable(); 464558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ("", stream2_->data()); 465558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 466558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Now send remaining data and verify that we have now received the 467558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // compressed headers. 468558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch string remaining_compressed_headers = 469558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch compressed_headers2.substr(partial_compressed_headers.length()); 470558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 471558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicStreamFrame frame3(stream2_->id(), false, 472558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch partial_compressed_headers.length(), 473558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch remaining_compressed_headers); 474558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream2_->OnStreamFrame(frame3); 475558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ(decompressed_headers2, stream2_->data()); 476558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 477558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 478b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) { 479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(kShouldProcessData); 480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers1 = compressor_->CompressHeaders(headers_); 482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); 483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string decompressed_headers1 = 484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::SerializeUncompressedHeaders(headers_); 485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) headers_["content-type"] = "text/plain"; 487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers2 = compressor_->CompressHeaders(headers_); 488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2); 489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string decompressed_headers2 = 490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::SerializeUncompressedHeaders(headers_); 491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 492558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Deliver frame2 to stream2 out of order. The decompressor is not 493558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // available yet, so no data will be processed. The compressed data 494558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // will be buffered until OnDecompressorAvailable() is called 495558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // to process it. 496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream2_->OnStreamFrame(frame2); 497558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ("", stream2_->data()); 498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 499558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Now deliver frame1 to stream1. The decompressor is available so 500558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the data will be processed, and the decompressor will become 501558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // available for stream2. 502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame1); 503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(decompressed_headers1, stream_->data()); 504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 505558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Verify that the decompressor is available, and inform stream2 506558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // that it can now decompress the buffered compressed data. 507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(2u, session_->decompressor()->current_header_id()); 508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream2_->OnDecompressorAvailable(); 509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(decompressed_headers2, stream2_->data()); 510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) { 513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Initialize(!kShouldProcessData); 514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string compressed_headers = compressor_->CompressHeaders(headers_); 516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers); 517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string decompressed_headers = 518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::SerializeUncompressedHeaders(headers_); 519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Send the headers to the stream and verify they were decompressed. 521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame1); 522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(2u, session_->decompressor()->current_header_id()); 523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Verify that we are now able to handle the body data, 525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // even though the stream has not processed the headers. 526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)) 527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) .Times(0); 528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(), 529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) "body data"); 530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) stream_->OnStreamFrame(frame2); 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace test 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace net 536