Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob9d684ac4c76f38bf2563442e731af513a43d4092
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_utils.h"
8 #include "net/quic/spdy_utils.h"
9 #include "net/quic/test_tools/quic_connection_peer.h"
10 #include "net/quic/test_tools/quic_session_peer.h"
11 #include "net/quic/test_tools/quic_test_utils.h"
12 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
13 #include "net/spdy/spdy_protocol.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using base::StringPiece;
17 using std::ostream;
18 using std::string;
19 using std::vector;
20 using testing::Invoke;
21 using testing::StrictMock;
22 using testing::WithArgs;
23 using testing::_;
25 namespace net {
26 namespace test {
27 namespace {
29 class MockVisitor : public SpdyFramerVisitorInterface {
30 public:
31 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
32 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
33 size_t length,
34 bool fin));
35 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
36 const char* data,
37 size_t len,
38 bool fin));
39 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
40 const char* header_data,
41 size_t len));
42 MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
43 SpdyStreamId associated_stream_id,
44 SpdyPriority priority,
45 bool fin,
46 bool unidirectional));
47 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
48 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
49 SpdyRstStreamStatus status));
50 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
51 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
52 MOCK_METHOD0(OnSettingsAck, void());
53 MOCK_METHOD0(OnSettingsEnd, void());
54 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
55 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
56 SpdyGoAwayStatus status));
57 MOCK_METHOD5(OnHeaders, void(SpdyStreamId stream_id, bool has_priority,
58 SpdyPriority priority, bool fin, bool end));
59 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
60 uint32 delta_window_size));
61 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
62 size_t len));
63 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
64 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
65 SpdyStreamId promised_stream_id,
66 bool end));
67 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
68 MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id,
69 uint32 max_age,
70 uint16 port,
71 StringPiece protocol_id,
72 StringPiece host,
73 StringPiece origin));
74 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
77 // Run all tests with each version, and client or server
78 struct TestParams {
79 TestParams(QuicVersion version, bool is_server)
80 : version(version), is_server(is_server) {}
82 friend ostream& operator<<(ostream& os, const TestParams& p) {
83 os << "{ version: " << QuicVersionToString(p.version);
84 os << ", is_server: " << p.is_server << " }";
85 return os;
88 QuicVersion version;
89 bool is_server;
92 // Constructs various test permutations.
93 vector<TestParams> GetTestParams() {
94 vector<TestParams> params;
95 QuicVersionVector all_supported_versions = QuicSupportedVersions();
96 for (const QuicVersion version : all_supported_versions) {
97 params.push_back(TestParams(version, false));
98 params.push_back(TestParams(version, true));
100 return params;
103 class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
104 public:
105 QuicHeadersStreamTest()
106 : connection_(new StrictMock<MockConnection>(is_server(), GetVersion())),
107 session_(connection_),
108 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
109 body_("hello world"),
110 framer_(version() > QUIC_VERSION_23 ? SPDY4 : SPDY3) {
111 headers_[":version"] = "HTTP/1.1";
112 headers_[":status"] = "200 Ok";
113 headers_["content-length"] = "11";
114 framer_.set_visitor(&visitor_);
115 EXPECT_EQ(version(), session_.connection()->version());
116 EXPECT_TRUE(headers_stream_ != nullptr);
117 VLOG(1) << GetParam();
120 QuicConsumedData SaveIov(const IOVector& data) {
121 const iovec* iov = data.iovec();
122 int count = data.Capacity();
123 for (int i = 0 ; i < count; ++i) {
124 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
126 return QuicConsumedData(saved_data_.length(), false);
129 bool SaveHeaderData(const char* data, int len) {
130 saved_header_data_.append(data, len);
131 return true;
134 void SaveHeaderDataStringPiece(StringPiece data) {
135 saved_header_data_.append(data.data(), data.length());
138 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
139 bool fin,
140 QuicPriority priority) {
141 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
144 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
145 bool fin) {
146 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
149 void WriteHeadersAndCheckData(QuicStreamId stream_id,
150 bool fin,
151 QuicPriority priority,
152 SpdyFrameType type) {
153 // Write the headers and capture the outgoing data
154 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr))
155 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
156 headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr);
158 // Parse the outgoing data and check that it matches was was written.
159 if (type == SYN_STREAM) {
160 if (version() > QUIC_VERSION_23) {
161 EXPECT_CALL(visitor_, OnHeaders(stream_id, kHasPriority, priority, fin,
162 kFrameComplete));
163 } else {
164 EXPECT_CALL(visitor_,
165 OnSynStream(stream_id, kNoAssociatedStream,
166 /*priority=*/0, fin, kNotUnidirectional));
168 } else {
169 if (version() > QUIC_VERSION_23) {
170 EXPECT_CALL(visitor_, OnHeaders(stream_id, !kHasPriority,
171 /*priority=*/0, fin, kFrameComplete));
172 } else {
173 EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
176 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
177 .WillRepeatedly(WithArgs<1, 2>(
178 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
179 if (fin) {
180 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true));
182 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
183 EXPECT_FALSE(framer_.HasError())
184 << SpdyFramer::ErrorCodeToString(framer_.error_code());
186 CheckHeaders();
187 saved_data_.clear();
190 void CheckHeaders() {
191 SpdyHeaderBlock headers;
192 EXPECT_EQ(saved_header_data_.length(),
193 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
194 saved_header_data_.length(),
195 &headers));
196 EXPECT_EQ(headers_, headers);
197 saved_header_data_.clear();
200 bool is_server() { return GetParam().is_server; }
202 QuicVersion version() { return GetParam().version; }
204 QuicVersionVector GetVersion() {
205 QuicVersionVector versions;
206 versions.push_back(version());
207 return versions;
210 void CloseConnection() {
211 QuicConnectionPeer::CloseConnection(connection_);
214 static const bool kFrameComplete = true;
215 static const bool kHasPriority = true;
216 static const bool kNotUnidirectional = false;
217 static const bool kNoAssociatedStream = false;
219 StrictMock<MockConnection>* connection_;
220 StrictMock<MockSession> session_;
221 QuicHeadersStream* headers_stream_;
222 SpdyHeaderBlock headers_;
223 string body_;
224 string saved_data_;
225 string saved_header_data_;
226 SpdyFramer framer_;
227 StrictMock<MockVisitor> visitor_;
230 INSTANTIATE_TEST_CASE_P(Tests,
231 QuicHeadersStreamTest,
232 ::testing::ValuesIn(GetTestParams()));
234 TEST_P(QuicHeadersStreamTest, StreamId) {
235 EXPECT_EQ(3u, headers_stream_->id());
238 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
239 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
242 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
243 for (QuicStreamId stream_id = kClientDataStreamId1;
244 stream_id < kClientDataStreamId3; stream_id += 2) {
245 for (int count = 0; count < 2; ++count) {
246 bool fin = (count == 0);
247 if (is_server()) {
248 WriteHeadersAndExpectSynReply(stream_id, fin);
249 } else {
250 for (QuicPriority priority = 0; priority < 7; ++priority) {
251 // TODO(rch): implement priorities correctly.
252 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
259 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
260 for (QuicStreamId stream_id = kClientDataStreamId1;
261 stream_id < kClientDataStreamId3; stream_id += 2) {
262 for (int count = 0; count < 2; ++count) {
263 bool fin = (count == 0);
264 for (QuicPriority priority = 0; priority < 7; ++priority) {
265 // Replace with "WriteHeadersAndSaveData"
266 scoped_ptr<SpdySerializedFrame> frame;
267 if (is_server()) {
268 if (version() > QUIC_VERSION_23) {
269 SpdyHeadersIR headers_frame(stream_id);
270 headers_frame.set_name_value_block(headers_);
271 headers_frame.set_fin(fin);
272 headers_frame.set_has_priority(true);
273 frame.reset(framer_.SerializeFrame(headers_frame));
274 } else {
275 SpdySynStreamIR syn_stream(stream_id);
276 syn_stream.set_name_value_block(headers_);
277 syn_stream.set_fin(fin);
278 frame.reset(framer_.SerializeSynStream(syn_stream));
280 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
281 } else {
282 if (version() > QUIC_VERSION_23) {
283 SpdyHeadersIR headers_frame(stream_id);
284 headers_frame.set_name_value_block(headers_);
285 headers_frame.set_fin(fin);
286 frame.reset(framer_.SerializeFrame(headers_frame));
287 } else {
288 SpdySynReplyIR syn_reply(stream_id);
289 syn_reply.set_name_value_block(headers_);
290 syn_reply.set_fin(fin);
291 frame.reset(framer_.SerializeSynReply(syn_reply));
294 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
295 .WillRepeatedly(WithArgs<1>(
296 Invoke(this,
297 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
298 EXPECT_CALL(session_,
299 OnStreamHeadersComplete(stream_id, fin, frame->size()));
300 headers_stream_->ProcessRawData(frame->data(), frame->size());
301 CheckHeaders();
307 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
308 // We want to create a frame that is more than the SPDY Framer's max control
309 // frame size, which is 16K, but less than the HPACK decoders max decode
310 // buffer size, which is 32K.
311 headers_["key0"] = string(1 << 13, '.');
312 headers_["key1"] = string(1 << 13, '.');
313 headers_["key2"] = string(1 << 13, '.');
314 for (QuicStreamId stream_id = kClientDataStreamId1;
315 stream_id < kClientDataStreamId3; stream_id += 2) {
316 for (int count = 0; count < 2; ++count) {
317 bool fin = (count == 0);
318 for (QuicPriority priority = 0; priority < 7; ++priority) {
319 // Replace with "WriteHeadersAndSaveData"
320 scoped_ptr<SpdySerializedFrame> frame;
321 if (is_server()) {
322 if (version() > QUIC_VERSION_23) {
323 SpdyHeadersIR headers_frame(stream_id);
324 headers_frame.set_name_value_block(headers_);
325 headers_frame.set_fin(fin);
326 headers_frame.set_has_priority(true);
327 frame.reset(framer_.SerializeFrame(headers_frame));
328 } else {
329 SpdySynStreamIR syn_stream(stream_id);
330 syn_stream.set_name_value_block(headers_);
331 syn_stream.set_fin(fin);
332 frame.reset(framer_.SerializeSynStream(syn_stream));
334 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
335 } else {
336 if (version() > QUIC_VERSION_23) {
337 SpdyHeadersIR headers_frame(stream_id);
338 headers_frame.set_name_value_block(headers_);
339 headers_frame.set_fin(fin);
340 frame.reset(framer_.SerializeFrame(headers_frame));
341 } else {
342 SpdySynReplyIR syn_reply(stream_id);
343 syn_reply.set_name_value_block(headers_);
344 syn_reply.set_fin(fin);
345 frame.reset(framer_.SerializeSynReply(syn_reply));
348 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
349 .WillRepeatedly(WithArgs<1>(Invoke(
350 this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
351 EXPECT_CALL(session_,
352 OnStreamHeadersComplete(stream_id, fin, frame->size()));
353 headers_stream_->ProcessRawData(frame->data(), frame->size());
354 CheckHeaders();
360 TEST_P(QuicHeadersStreamTest, ProcessBadData) {
361 const char kBadData[] = "blah blah blah";
362 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
363 QUIC_INVALID_HEADERS_STREAM_DATA, _))
364 .Times(::testing::AnyNumber());
365 headers_stream_->ProcessRawData(kBadData, strlen(kBadData));
368 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
369 SpdyDataIR data(2, "");
370 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
371 EXPECT_CALL(*connection_,
372 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
373 "SPDY DATA frame received."))
374 .WillOnce(InvokeWithoutArgs(this,
375 &QuicHeadersStreamTest::CloseConnection));
376 headers_stream_->ProcessRawData(frame->data(), frame->size());
379 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
380 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
381 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
382 EXPECT_CALL(*connection_,
383 SendConnectionCloseWithDetails(
384 QUIC_INVALID_HEADERS_STREAM_DATA,
385 "SPDY RST_STREAM frame received."))
386 .WillOnce(InvokeWithoutArgs(this,
387 &QuicHeadersStreamTest::CloseConnection));
388 headers_stream_->ProcessRawData(frame->data(), frame->size());
391 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
392 SpdySettingsIR data;
393 if (version() > QUIC_VERSION_23) {
394 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
395 } else {
396 data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
398 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
399 EXPECT_CALL(*connection_,
400 SendConnectionCloseWithDetails(
401 QUIC_INVALID_HEADERS_STREAM_DATA,
402 "SPDY SETTINGS frame received."))
403 .WillOnce(InvokeWithoutArgs(this,
404 &QuicHeadersStreamTest::CloseConnection));
405 headers_stream_->ProcessRawData(frame->data(), frame->size());
408 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
409 SpdyPingIR data(1);
410 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
411 EXPECT_CALL(*connection_,
412 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
413 "SPDY PING frame received."))
414 .WillOnce(InvokeWithoutArgs(this,
415 &QuicHeadersStreamTest::CloseConnection));
416 headers_stream_->ProcessRawData(frame->data(), frame->size());
419 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
420 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
421 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
422 EXPECT_CALL(*connection_,
423 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
424 "SPDY GOAWAY frame received."))
425 .WillOnce(InvokeWithoutArgs(this,
426 &QuicHeadersStreamTest::CloseConnection));
427 headers_stream_->ProcessRawData(frame->data(), frame->size());
430 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
431 if (version() > QUIC_VERSION_23) {
432 // HEADERS frames are an error when using SPDY/3, but
433 // when using SPDY/4 they're the "normal" way of sending headers
434 // so we test their handling in the ProcessRawData test.
435 return;
437 SpdyHeadersIR data(1);
438 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
439 EXPECT_CALL(*connection_,
440 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
441 "SPDY HEADERS frame received."))
442 .WillOnce(InvokeWithoutArgs(this,
443 &QuicHeadersStreamTest::CloseConnection));
444 headers_stream_->ProcessRawData(frame->data(), frame->size());
447 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
448 SpdyWindowUpdateIR data(1, 1);
449 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
450 EXPECT_CALL(*connection_,
451 SendConnectionCloseWithDetails(
452 QUIC_INVALID_HEADERS_STREAM_DATA,
453 "SPDY WINDOW_UPDATE frame received."))
454 .WillOnce(InvokeWithoutArgs(this,
455 &QuicHeadersStreamTest::CloseConnection));
456 headers_stream_->ProcessRawData(frame->data(), frame->size());
459 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
460 EXPECT_TRUE(headers_stream_->flow_controller()->IsEnabled());
461 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
462 headers_stream_));
465 } // namespace
466 } // namespace test
467 } // namespace net