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