15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_headers_stream.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_utils.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/spdy_utils.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/test_tools/quic_connection_peer.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/test_tools/quic_session_peer.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/quic/test_tools/reliable_quic_stream_peer.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/spdy/spdy_protocol.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::StringPiece;
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using std::string;
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::Invoke;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::StrictMock;
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::WithArgs;
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::_;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net {
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace test {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MockVisitor : public SpdyFramerVisitorInterface {
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD1(OnError, void(SpdyFramer* framer));
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       size_t length,
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       bool fin));
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       const char* data,
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       size_t len,
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       bool fin));
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              const char* header_data,
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              size_t len));
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 SpdyStreamId associated_stream_id,
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 SpdyPriority priority,
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 bool fin,
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 bool unidirectional));
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 SpdyRstStreamStatus status));
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD1(OnSettings, void(bool clear_persisted));
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD0(OnSettingsAck, void());
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD0(OnSettingsEnd, void());
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              SpdyGoAwayStatus status));
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD3(OnHeaders, void(SpdyStreamId stream_id, bool fin, bool end));
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    uint32 delta_window_size));
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           size_t len));
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   SpdyStreamId promised_stream_id,
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   bool end));
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id,
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              uint32 max_age,
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              uint16 port,
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              StringPiece protocol_id,
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              StringPiece host,
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              StringPiece origin));
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> {
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static QuicVersionVector GetVersions() {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicVersionVector versions;
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    versions.push_back(QuicVersionMax());
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return versions;
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicHeadersStreamTest()
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : connection_(new StrictMock<MockConnection>(is_server(), GetVersions())),
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        session_(connection_),
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        body_("hello world"),
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        framer_(SPDY3) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    headers_[":version"]  = "HTTP/1.1";
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    headers_[":status"] = "200 Ok";
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    headers_["content-length"] = "11";
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    framer_.set_visitor(&visitor_);
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EXPECT_EQ(QuicVersionMax(), session_.connection()->version());
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_TRUE(headers_stream_ != NULL);
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  QuicConsumedData SaveIov(const IOVector& data) {
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const iovec* iov = data.iovec();
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int count = data.Capacity();
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int i = 0 ; i < count; ++i) {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return QuicConsumedData(saved_data_.length(), false);
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool SaveHeaderData(const char* data, int len) {
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    saved_header_data_.append(data, len);
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SaveHeaderDataStringPiece(StringPiece data) {
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    saved_header_data_.append(data.data(), data.length());
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      bool fin,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      QuicPriority priority) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     bool fin) {
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void WriteHeadersAndCheckData(QuicStreamId stream_id,
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                bool fin,
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicPriority priority,
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                SpdyFrameType type) {
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Write the headers and capture the outgoing data
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, NULL))
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    headers_stream_->WriteHeaders(stream_id, headers_, fin, NULL);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Parse the outgoing data and check that it matches was was written.
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (type == SYN_STREAM) {
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_CALL(visitor_, OnSynStream(stream_id, kNoAssociatedStream, 0,
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        // priority,
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        fin, kNotUnidirectional));
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        .WillRepeatedly(WithArgs<1, 2>(
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (fin) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, NULL, 0, true));
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    framer_.ProcessInput(saved_data_.data(), saved_data_.length());
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_FALSE(framer_.HasError()) << framer_.error_code();
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CheckHeaders();
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    saved_data_.clear();
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CheckHeaders() {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SpdyHeaderBlock headers;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(saved_header_data_.length(),
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               saved_header_data_.length(),
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &headers));
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(headers_, headers);
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    saved_header_data_.clear();
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool is_server() {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return GetParam();
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CloseConnection() {
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicConnectionPeer::CloseConnection(connection_);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const bool kNotUnidirectional = false;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const bool kNoAssociatedStream = false;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StrictMock<MockConnection>* connection_;
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StrictMock<MockSession> session_;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicHeadersStream* headers_stream_;
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyHeaderBlock headers_;
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  string body_;
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  string saved_data_;
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  string saved_header_data_;
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyFramer framer_;
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StrictMock<MockVisitor> visitor_;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(Tests, QuicHeadersStreamTest, testing::Bool());
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, StreamId) {
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(3u, headers_stream_->id());
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, EffectivePriority) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0u, headers_stream_->EffectivePriority());
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, WriteHeaders) {
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (QuicStreamId stream_id = kClientDataStreamId1;
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       stream_id < kClientDataStreamId3; stream_id += 2) {
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int count = 0; count < 2; ++count) {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool fin = (count == 0);
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (is_server()) {
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        WriteHeadersAndExpectSynReply(stream_id, fin);
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for (QuicPriority priority = 0; priority < 7; ++priority) {
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          WriteHeadersAndExpectSynStream(stream_id, fin, priority);
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessRawData) {
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (QuicStreamId stream_id = kClientDataStreamId1;
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       stream_id < kClientDataStreamId3; stream_id += 2) {
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int count = 0; count < 2; ++count) {
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool fin = (count == 0);
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (QuicPriority priority = 0; priority < 7; ++priority) {
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Replace with "WriteHeadersAndSaveData"
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_ptr<SpdySerializedFrame> frame;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (is_server()) {
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          SpdySynStreamIR syn_stream(stream_id);
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syn_stream.set_name_value_block(headers_);
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syn_stream.set_fin(fin);
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          frame.reset(framer_.SerializeSynStream(syn_stream));
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        } else {
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          SpdySynReplyIR syn_reply(stream_id);
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syn_reply.set_name_value_block(headers_);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syn_reply.set_fin(fin);
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          frame.reset(framer_.SerializeSynReply(syn_reply));
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            .WillRepeatedly(WithArgs<1>(
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                Invoke(this,
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EXPECT_CALL(session_,
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnStreamHeadersComplete(stream_id, fin, frame->size()));
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        headers_stream_->ProcessRawData(frame->data(), frame->size());
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        CheckHeaders();
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyDataIR data(2, "");
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             "SPDY DATA frame received."))
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  QUIC_INVALID_HEADERS_STREAM_DATA,
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  "SPDY RST_STREAM frame received."))
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdySettingsIR data;
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  QUIC_INVALID_HEADERS_STREAM_DATA,
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  "SPDY SETTINGS frame received."))
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyPingIR data(1);
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             "SPDY PING frame received."))
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             "SPDY GOAWAY frame received."))
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyHeadersIR data(1);
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             "SPDY HEADERS frame received."))
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SpdyWindowUpdateIR data(1, 1);
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*connection_,
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              SendConnectionCloseWithDetails(
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  QUIC_INVALID_HEADERS_STREAM_DATA,
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  "SPDY WINDOW_UPDATE frame received."))
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .WillOnce(InvokeWithoutArgs(this,
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &QuicHeadersStreamTest::CloseConnection));
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_stream_->ProcessRawData(frame->data(), frame->size());
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
328116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (connection_->version() < QUIC_VERSION_21) {
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_FALSE(headers_stream_->flow_controller()->IsEnabled());
331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_TRUE(headers_stream_->flow_controller()->IsEnabled());
333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      headers_stream_));
336e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
337e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace test
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace net
341