Land Recent QUIC Changes.
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob4022073339912fece64123e6a57e776dae4a70c7
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_headers_stream.h"
7 #include "net/quic/quic_flags.h"
8 #include "net/quic/quic_utils.h"
9 #include "net/quic/spdy_utils.h"
10 #include "net/quic/test_tools/quic_connection_peer.h"
11 #include "net/quic/test_tools/quic_session_peer.h"
12 #include "net/quic/test_tools/quic_test_utils.h"
13 #include "net/spdy/spdy_protocol.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using base::StringPiece;
17 using std::string;
18 using testing::Invoke;
19 using testing::StrictMock;
20 using testing::WithArgs;
21 using testing::_;
23 namespace net {
24 namespace test {
25 namespace {
27 class MockVisitor : public SpdyFramerVisitorInterface {
28 public:
29 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
30 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
31 size_t length,
32 bool fin));
33 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
34 const char* data,
35 size_t len,
36 bool fin));
37 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
38 const char* header_data,
39 size_t len));
40 MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
41 SpdyStreamId associated_stream_id,
42 SpdyPriority priority,
43 bool fin,
44 bool unidirectional));
45 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
46 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
47 SpdyRstStreamStatus status));
48 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
49 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
50 MOCK_METHOD0(OnSettingsAck, void());
51 MOCK_METHOD0(OnSettingsEnd, void());
52 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
53 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
54 SpdyGoAwayStatus status));
55 MOCK_METHOD3(OnHeaders, void(SpdyStreamId stream_id, bool fin, bool end));
56 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
57 uint32 delta_window_size));
58 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
59 size_t len));
60 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
61 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
62 SpdyStreamId promised_stream_id,
63 bool end));
64 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
65 MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id,
66 uint32 max_age,
67 uint16 port,
68 StringPiece protocol_id,
69 StringPiece host,
70 StringPiece origin));
73 class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> {
74 public:
75 static QuicVersionVector GetVersions() {
76 QuicVersionVector versions;
77 versions.push_back(QuicVersionMax());
78 return versions;
81 QuicHeadersStreamTest()
82 : connection_(new StrictMock<MockConnection>(is_server(), GetVersions())),
83 session_(connection_),
84 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
85 body_("hello world"),
86 framer_(SPDY3) {
87 headers_[":version"] = "HTTP/1.1";
88 headers_[":status"] = "200 Ok";
89 headers_["content-length"] = "11";
90 framer_.set_visitor(&visitor_);
91 EXPECT_EQ(QuicVersionMax(), session_.connection()->version());
92 EXPECT_TRUE(headers_stream_ != NULL);
95 QuicConsumedData SaveIov(const IOVector& data) {
96 const iovec* iov = data.iovec();
97 int count = data.Capacity();
98 for (int i = 0 ; i < count; ++i) {
99 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
101 return QuicConsumedData(saved_data_.length(), false);
104 bool SaveHeaderData(const char* data, int len) {
105 saved_header_data_.append(data, len);
106 return true;
109 void SaveHeaderDataStringPiece(StringPiece data) {
110 saved_header_data_.append(data.data(), data.length());
113 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
114 bool fin,
115 QuicPriority priority) {
116 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
119 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
120 bool fin) {
121 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
124 void WriteHeadersAndCheckData(QuicStreamId stream_id,
125 bool fin,
126 QuicPriority priority,
127 SpdyFrameType type) {
128 // Write the headers and capture the outgoing data
129 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, NULL))
130 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
131 headers_stream_->WriteHeaders(stream_id, headers_, fin, NULL);
133 // Parse the outgoing data and check that it matches was was written.
134 if (type == SYN_STREAM) {
135 EXPECT_CALL(visitor_, OnSynStream(stream_id, kNoAssociatedStream, 0,
136 // priority,
137 fin, kNotUnidirectional));
138 } else {
139 EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
141 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
142 .WillRepeatedly(WithArgs<1, 2>(
143 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
144 if (fin) {
145 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, NULL, 0, true));
147 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
148 EXPECT_FALSE(framer_.HasError()) << framer_.error_code();
150 CheckHeaders();
151 saved_data_.clear();
154 void CheckHeaders() {
155 SpdyHeaderBlock headers;
156 EXPECT_EQ(saved_header_data_.length(),
157 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
158 saved_header_data_.length(),
159 &headers));
160 EXPECT_EQ(headers_, headers);
161 saved_header_data_.clear();
164 bool is_server() {
165 return GetParam();
168 void CloseConnection() {
169 QuicConnectionPeer::CloseConnection(connection_);
172 static const bool kNotUnidirectional = false;
173 static const bool kNoAssociatedStream = false;
175 StrictMock<MockConnection>* connection_;
176 StrictMock<MockSession> session_;
177 QuicHeadersStream* headers_stream_;
178 SpdyHeaderBlock headers_;
179 string body_;
180 string saved_data_;
181 string saved_header_data_;
182 SpdyFramer framer_;
183 StrictMock<MockVisitor> visitor_;
186 INSTANTIATE_TEST_CASE_P(Tests, QuicHeadersStreamTest, testing::Bool());
188 TEST_P(QuicHeadersStreamTest, StreamId) {
189 EXPECT_EQ(3u, headers_stream_->id());
192 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
193 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
196 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
197 for (QuicStreamId stream_id = 5; stream_id < 9; stream_id +=2) {
198 for (int count = 0; count < 2; ++count) {
199 bool fin = (count == 0);
200 if (is_server()) {
201 WriteHeadersAndExpectSynReply(stream_id, fin);
202 } else {
203 for (QuicPriority priority = 0; priority < 7; ++priority) {
204 WriteHeadersAndExpectSynStream(stream_id, fin, priority);
211 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
212 for (QuicStreamId stream_id = 5; stream_id < 9; stream_id +=2) {
213 for (int count = 0; count < 2; ++count) {
214 bool fin = (count == 0);
215 for (QuicPriority priority = 0; priority < 7; ++priority) {
216 // Replace with "WriteHeadersAndSaveData"
217 scoped_ptr<SpdySerializedFrame> frame;
218 if (is_server()) {
219 SpdySynStreamIR syn_stream(stream_id);
220 syn_stream.set_name_value_block(headers_);
221 syn_stream.set_fin(fin);
222 frame.reset(framer_.SerializeSynStream(syn_stream));
223 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
224 } else {
225 SpdySynReplyIR syn_reply(stream_id);
226 syn_reply.set_name_value_block(headers_);
227 syn_reply.set_fin(fin);
228 frame.reset(framer_.SerializeSynReply(syn_reply));
230 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
231 .WillRepeatedly(WithArgs<1>(
232 Invoke(this,
233 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
234 EXPECT_CALL(session_,
235 OnStreamHeadersComplete(stream_id, fin, frame->size()));
236 headers_stream_->ProcessRawData(frame->data(), frame->size());
238 CheckHeaders();
244 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
245 SpdyDataIR data(2, "");
246 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
247 EXPECT_CALL(*connection_,
248 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
249 "SPDY DATA frame received."))
250 .WillOnce(InvokeWithoutArgs(this,
251 &QuicHeadersStreamTest::CloseConnection));
252 headers_stream_->ProcessRawData(frame->data(), frame->size());
255 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
256 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
257 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
258 EXPECT_CALL(*connection_,
259 SendConnectionCloseWithDetails(
260 QUIC_INVALID_HEADERS_STREAM_DATA,
261 "SPDY RST_STREAM frame received."))
262 .WillOnce(InvokeWithoutArgs(this,
263 &QuicHeadersStreamTest::CloseConnection));
264 headers_stream_->ProcessRawData(frame->data(), frame->size());
267 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
268 SpdySettingsIR data;
269 data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
270 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
271 EXPECT_CALL(*connection_,
272 SendConnectionCloseWithDetails(
273 QUIC_INVALID_HEADERS_STREAM_DATA,
274 "SPDY SETTINGS frame received."))
275 .WillOnce(InvokeWithoutArgs(this,
276 &QuicHeadersStreamTest::CloseConnection));
277 headers_stream_->ProcessRawData(frame->data(), frame->size());
280 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
281 SpdyPingIR data(1);
282 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
283 EXPECT_CALL(*connection_,
284 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
285 "SPDY PING frame received."))
286 .WillOnce(InvokeWithoutArgs(this,
287 &QuicHeadersStreamTest::CloseConnection));
288 headers_stream_->ProcessRawData(frame->data(), frame->size());
291 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
292 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
293 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
294 EXPECT_CALL(*connection_,
295 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
296 "SPDY GOAWAY frame received."))
297 .WillOnce(InvokeWithoutArgs(this,
298 &QuicHeadersStreamTest::CloseConnection));
299 headers_stream_->ProcessRawData(frame->data(), frame->size());
302 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
303 SpdyHeadersIR data(1);
304 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
305 EXPECT_CALL(*connection_,
306 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
307 "SPDY HEADERS frame received."))
308 .WillOnce(InvokeWithoutArgs(this,
309 &QuicHeadersStreamTest::CloseConnection));
310 headers_stream_->ProcessRawData(frame->data(), frame->size());
313 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
314 SpdyWindowUpdateIR data(1, 1);
315 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
316 EXPECT_CALL(*connection_,
317 SendConnectionCloseWithDetails(
318 QUIC_INVALID_HEADERS_STREAM_DATA,
319 "SPDY WINDOW_UPDATE frame received."))
320 .WillOnce(InvokeWithoutArgs(this,
321 &QuicHeadersStreamTest::CloseConnection));
322 headers_stream_->ProcessRawData(frame->data(), frame->size());
325 TEST_P(QuicHeadersStreamTest, NoFlowControl) {
326 ValueRestore<bool> old_flag(&FLAGS_enable_quic_stream_flow_control_2, true);
327 EXPECT_FALSE(headers_stream_->flow_controller()->IsEnabled());
330 } // namespace
331 } // namespace test
332 } // namespace net