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.
4
5 #include "quiche/quic/core/http/quic_headers_stream.h"
6
7 #include <cstdint>
8 #include <ostream>
9 #include <string>
10 #include <tuple>
11 #include <utility>
12 #include <vector>
13
14 #include "absl/strings/str_cat.h"
15 #include "absl/strings/string_view.h"
16 #include "quiche/quic/core/crypto/null_encrypter.h"
17 #include "quiche/quic/core/http/spdy_utils.h"
18 #include "quiche/quic/core/quic_data_writer.h"
19 #include "quiche/quic/core/quic_utils.h"
20 #include "quiche/quic/platform/api/quic_bug_tracker.h"
21 #include "quiche/quic/platform/api/quic_expect_bug.h"
22 #include "quiche/quic/platform/api/quic_flags.h"
23 #include "quiche/quic/platform/api/quic_logging.h"
24 #include "quiche/quic/platform/api/quic_test.h"
25 #include "quiche/quic/test_tools/quic_connection_peer.h"
26 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
27 #include "quiche/quic/test_tools/quic_stream_peer.h"
28 #include "quiche/quic/test_tools/quic_test_utils.h"
29 #include "quiche/common/quiche_endian.h"
30 #include "quiche/spdy/core/http2_frame_decoder_adapter.h"
31 #include "quiche/spdy/core/http2_header_block.h"
32 #include "quiche/spdy/core/recording_headers_handler.h"
33 #include "quiche/spdy/core/spdy_alt_svc_wire_format.h"
34 #include "quiche/spdy/core/spdy_protocol.h"
35 #include "quiche/spdy/test_tools/spdy_test_utils.h"
36
37 using spdy::ERROR_CODE_PROTOCOL_ERROR;
38 using spdy::Http2HeaderBlock;
39 using spdy::RecordingHeadersHandler;
40 using spdy::SETTINGS_ENABLE_PUSH;
41 using spdy::SETTINGS_HEADER_TABLE_SIZE;
42 using spdy::SETTINGS_INITIAL_WINDOW_SIZE;
43 using spdy::SETTINGS_MAX_CONCURRENT_STREAMS;
44 using spdy::SETTINGS_MAX_FRAME_SIZE;
45 using spdy::Spdy3PriorityToHttp2Weight;
46 using spdy::SpdyAltSvcWireFormat;
47 using spdy::SpdyDataIR;
48 using spdy::SpdyErrorCode;
49 using spdy::SpdyFramer;
50 using spdy::SpdyFramerVisitorInterface;
51 using spdy::SpdyGoAwayIR;
52 using spdy::SpdyHeadersHandlerInterface;
53 using spdy::SpdyHeadersIR;
54 using spdy::SpdyPingId;
55 using spdy::SpdyPingIR;
56 using spdy::SpdyPriority;
57 using spdy::SpdyPriorityIR;
58 using spdy::SpdyPushPromiseIR;
59 using spdy::SpdyRstStreamIR;
60 using spdy::SpdySerializedFrame;
61 using spdy::SpdySettingsId;
62 using spdy::SpdySettingsIR;
63 using spdy::SpdyStreamId;
64 using spdy::SpdyWindowUpdateIR;
65 using testing::_;
66 using testing::AnyNumber;
67 using testing::AtLeast;
68 using testing::InSequence;
69 using testing::Invoke;
70 using testing::Return;
71 using testing::StrictMock;
72 using testing::WithArgs;
73
74 namespace quic {
75 namespace test {
76 namespace {
77
78 class MockVisitor : public SpdyFramerVisitorInterface {
79 public:
80 MOCK_METHOD(void, OnError,
81 (http2::Http2DecoderAdapter::SpdyFramerError error,
82 std::string detailed_error),
83 (override));
84 MOCK_METHOD(void, OnDataFrameHeader,
85 (SpdyStreamId stream_id, size_t length, bool fin), (override));
86 MOCK_METHOD(void, OnStreamFrameData,
87 (SpdyStreamId stream_id, const char*, size_t len), (override));
88 MOCK_METHOD(void, OnStreamEnd, (SpdyStreamId stream_id), (override));
89 MOCK_METHOD(void, OnStreamPadding, (SpdyStreamId stream_id, size_t len),
90 (override));
91 MOCK_METHOD(SpdyHeadersHandlerInterface*, OnHeaderFrameStart,
92 (SpdyStreamId stream_id), (override));
93 MOCK_METHOD(void, OnHeaderFrameEnd, (SpdyStreamId stream_id), (override));
94 MOCK_METHOD(void, OnRstStream,
95 (SpdyStreamId stream_id, SpdyErrorCode error_code), (override));
96 MOCK_METHOD(void, OnSettings, (), (override));
97 MOCK_METHOD(void, OnSetting, (SpdySettingsId id, uint32_t value), (override));
98 MOCK_METHOD(void, OnSettingsAck, (), (override));
99 MOCK_METHOD(void, OnSettingsEnd, (), (override));
100 MOCK_METHOD(void, OnPing, (SpdyPingId unique_id, bool is_ack), (override));
101 MOCK_METHOD(void, OnGoAway,
102 (SpdyStreamId last_accepted_stream_id, SpdyErrorCode error_code),
103 (override));
104 MOCK_METHOD(void, OnHeaders,
105 (SpdyStreamId stream_id, size_t payload_length, bool has_priority,
106 int weight, SpdyStreamId parent_stream_id, bool exclusive,
107 bool fin, bool end),
108 (override));
109 MOCK_METHOD(void, OnWindowUpdate,
110 (SpdyStreamId stream_id, int delta_window_size), (override));
111 MOCK_METHOD(void, OnPushPromise,
112 (SpdyStreamId stream_id, SpdyStreamId promised_stream_id,
113 bool end),
114 (override));
115 MOCK_METHOD(void, OnContinuation,
116 (SpdyStreamId stream_id, size_t payload_size, bool end),
117 (override));
118 MOCK_METHOD(
119 void, OnAltSvc,
120 (SpdyStreamId stream_id, absl::string_view origin,
121 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector),
122 (override));
123 MOCK_METHOD(void, OnPriority,
124 (SpdyStreamId stream_id, SpdyStreamId parent_stream_id,
125 int weight, bool exclusive),
126 (override));
127 MOCK_METHOD(void, OnPriorityUpdate,
128 (SpdyStreamId prioritized_stream_id,
129 absl::string_view priority_field_value),
130 (override));
131 MOCK_METHOD(bool, OnUnknownFrame,
132 (SpdyStreamId stream_id, uint8_t frame_type), (override));
133 MOCK_METHOD(void, OnUnknownFrameStart,
134 (SpdyStreamId stream_id, size_t length, uint8_t type,
135 uint8_t flags),
136 (override));
137 MOCK_METHOD(void, OnUnknownFramePayload,
138 (SpdyStreamId stream_id, absl::string_view payload), (override));
139 };
140
141 struct TestParams {
TestParamsquic::test::__anon118f3eb60111::TestParams142 TestParams(const ParsedQuicVersion& version, Perspective perspective)
143 : version(version), perspective(perspective) {
144 QUIC_LOG(INFO) << "TestParams: " << *this;
145 }
146
TestParamsquic::test::__anon118f3eb60111::TestParams147 TestParams(const TestParams& other)
148 : version(other.version), perspective(other.perspective) {}
149
operator <<(std::ostream & os,const TestParams & tp)150 friend std::ostream& operator<<(std::ostream& os, const TestParams& tp) {
151 os << "{ version: " << ParsedQuicVersionToString(tp.version)
152 << ", perspective: "
153 << (tp.perspective == Perspective::IS_CLIENT ? "client" : "server")
154 << "}";
155 return os;
156 }
157
158 ParsedQuicVersion version;
159 Perspective perspective;
160 };
161
162 // Used by ::testing::PrintToStringParamName().
PrintToString(const TestParams & tp)163 std::string PrintToString(const TestParams& tp) {
164 return absl::StrCat(
165 ParsedQuicVersionToString(tp.version), "_",
166 (tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
167 }
168
GetTestParams()169 std::vector<TestParams> GetTestParams() {
170 std::vector<TestParams> params;
171 ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
172 for (size_t i = 0; i < all_supported_versions.size(); ++i) {
173 if (VersionUsesHttp3(all_supported_versions[i].transport_version)) {
174 continue;
175 }
176 for (Perspective p : {Perspective::IS_SERVER, Perspective::IS_CLIENT}) {
177 params.emplace_back(all_supported_versions[i], p);
178 }
179 }
180 return params;
181 }
182
183 class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
184 public:
QuicHeadersStreamTest()185 QuicHeadersStreamTest()
186 : connection_(new StrictMock<MockQuicConnection>(
187 &helper_, &alarm_factory_, perspective(), GetVersion())),
188 session_(connection_),
189 body_("hello world"),
190 stream_frame_(
191 QuicUtils::GetHeadersStreamId(connection_->transport_version()),
192 /*fin=*/false,
193 /*offset=*/0, ""),
194 next_promised_stream_id_(2) {
195 QuicSpdySessionPeer::SetMaxInboundHeaderListSize(&session_, 256 * 1024);
196 EXPECT_CALL(session_, OnCongestionWindowChange(_)).Times(AnyNumber());
197 session_.Initialize();
198 connection_->SetEncrypter(
199 quic::ENCRYPTION_FORWARD_SECURE,
200 std::make_unique<quic::NullEncrypter>(connection_->perspective()));
201 headers_stream_ = QuicSpdySessionPeer::GetHeadersStream(&session_);
202 headers_[":status"] = "200 Ok";
203 headers_["content-length"] = "11";
204 framer_ = std::unique_ptr<SpdyFramer>(
205 new SpdyFramer(SpdyFramer::ENABLE_COMPRESSION));
206 deframer_ = std::unique_ptr<http2::Http2DecoderAdapter>(
207 new http2::Http2DecoderAdapter());
208 deframer_->set_visitor(&visitor_);
209 EXPECT_EQ(transport_version(), session_.transport_version());
210 EXPECT_TRUE(headers_stream_ != nullptr);
211 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
212 client_id_1_ = GetNthClientInitiatedBidirectionalStreamId(
213 connection_->transport_version(), 0);
214 client_id_2_ = GetNthClientInitiatedBidirectionalStreamId(
215 connection_->transport_version(), 1);
216 client_id_3_ = GetNthClientInitiatedBidirectionalStreamId(
217 connection_->transport_version(), 2);
218 next_stream_id_ =
219 QuicUtils::StreamIdDelta(connection_->transport_version());
220 }
221
GetNthClientInitiatedId(int n)222 QuicStreamId GetNthClientInitiatedId(int n) {
223 return GetNthClientInitiatedBidirectionalStreamId(
224 connection_->transport_version(), n);
225 }
226
SaveIov(size_t write_length)227 QuicConsumedData SaveIov(size_t write_length) {
228 char* buf = new char[write_length];
229 QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
230 headers_stream_->WriteStreamData(headers_stream_->stream_bytes_written(),
231 write_length, &writer);
232 saved_data_.append(buf, write_length);
233 delete[] buf;
234 return QuicConsumedData(write_length, false);
235 }
236
SavePayload(const char * data,size_t len)237 void SavePayload(const char* data, size_t len) {
238 saved_payloads_.append(data, len);
239 }
240
SaveHeaderData(const char * data,int len)241 bool SaveHeaderData(const char* data, int len) {
242 saved_header_data_.append(data, len);
243 return true;
244 }
245
SaveHeaderDataStringPiece(absl::string_view data)246 void SaveHeaderDataStringPiece(absl::string_view data) {
247 saved_header_data_.append(data.data(), data.length());
248 }
249
SavePromiseHeaderList(QuicStreamId,QuicStreamId,size_t size,const QuicHeaderList & header_list)250 void SavePromiseHeaderList(QuicStreamId /* stream_id */,
251 QuicStreamId /* promised_stream_id */, size_t size,
252 const QuicHeaderList& header_list) {
253 SaveToHandler(size, header_list);
254 }
255
SaveHeaderList(QuicStreamId,bool,size_t size,const QuicHeaderList & header_list)256 void SaveHeaderList(QuicStreamId /* stream_id */, bool /* fin */, size_t size,
257 const QuicHeaderList& header_list) {
258 SaveToHandler(size, header_list);
259 }
260
SaveToHandler(size_t size,const QuicHeaderList & header_list)261 void SaveToHandler(size_t size, const QuicHeaderList& header_list) {
262 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
263 headers_handler_->OnHeaderBlockStart();
264 for (const auto& p : header_list) {
265 headers_handler_->OnHeader(p.first, p.second);
266 }
267 headers_handler_->OnHeaderBlockEnd(size, size);
268 }
269
WriteAndExpectRequestHeaders(QuicStreamId stream_id,bool fin,SpdyPriority priority)270 void WriteAndExpectRequestHeaders(QuicStreamId stream_id, bool fin,
271 SpdyPriority priority) {
272 WriteHeadersAndCheckData(stream_id, fin, priority, true /*is_request*/);
273 }
274
WriteAndExpectResponseHeaders(QuicStreamId stream_id,bool fin)275 void WriteAndExpectResponseHeaders(QuicStreamId stream_id, bool fin) {
276 WriteHeadersAndCheckData(stream_id, fin, 0, false /*is_request*/);
277 }
278
WriteHeadersAndCheckData(QuicStreamId stream_id,bool fin,SpdyPriority priority,bool is_request)279 void WriteHeadersAndCheckData(QuicStreamId stream_id, bool fin,
280 SpdyPriority priority, bool is_request) {
281 // Write the headers and capture the outgoing data
282 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
283 connection_->transport_version()),
284 _, _, NO_FIN, _, _))
285 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
286 QuicSpdySessionPeer::WriteHeadersOnHeadersStream(
287 &session_, stream_id, headers_.Clone(), fin,
288 spdy::SpdyStreamPrecedence(priority), nullptr);
289
290 // Parse the outgoing data and check that it matches was was written.
291 if (is_request) {
292 EXPECT_CALL(
293 visitor_,
294 OnHeaders(stream_id, saved_data_.length() - spdy::kFrameHeaderSize,
295 kHasPriority, Spdy3PriorityToHttp2Weight(priority),
296 /*parent_stream_id=*/0,
297 /*exclusive=*/false, fin, kFrameComplete));
298 } else {
299 EXPECT_CALL(
300 visitor_,
301 OnHeaders(stream_id, saved_data_.length() - spdy::kFrameHeaderSize,
302 !kHasPriority,
303 /*weight=*/0,
304 /*parent_stream_id=*/0,
305 /*exclusive=*/false, fin, kFrameComplete));
306 }
307 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
308 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
309 .WillOnce(Return(headers_handler_.get()));
310 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id)).Times(1);
311 if (fin) {
312 EXPECT_CALL(visitor_, OnStreamEnd(stream_id));
313 }
314 deframer_->ProcessInput(saved_data_.data(), saved_data_.length());
315 EXPECT_FALSE(deframer_->HasError())
316 << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
317 deframer_->spdy_framer_error());
318
319 CheckHeaders();
320 saved_data_.clear();
321 }
322
CheckHeaders()323 void CheckHeaders() {
324 ASSERT_TRUE(headers_handler_);
325 EXPECT_EQ(headers_, headers_handler_->decoded_block());
326 headers_handler_.reset();
327 }
328
perspective() const329 Perspective perspective() const { return GetParam().perspective; }
330
transport_version() const331 QuicTransportVersion transport_version() const {
332 return GetParam().version.transport_version;
333 }
334
GetVersion()335 ParsedQuicVersionVector GetVersion() {
336 ParsedQuicVersionVector versions;
337 versions.push_back(GetParam().version);
338 return versions;
339 }
340
TearDownLocalConnectionState()341 void TearDownLocalConnectionState() {
342 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
343 }
344
NextPromisedStreamId()345 QuicStreamId NextPromisedStreamId() {
346 return next_promised_stream_id_ += next_stream_id_;
347 }
348
349 static constexpr bool kFrameComplete = true;
350 static constexpr bool kHasPriority = true;
351
352 MockQuicConnectionHelper helper_;
353 MockAlarmFactory alarm_factory_;
354 StrictMock<MockQuicConnection>* connection_;
355 StrictMock<MockQuicSpdySession> session_;
356 QuicHeadersStream* headers_stream_;
357 Http2HeaderBlock headers_;
358 std::unique_ptr<RecordingHeadersHandler> headers_handler_;
359 std::string body_;
360 std::string saved_data_;
361 std::string saved_header_data_;
362 std::string saved_payloads_;
363 std::unique_ptr<SpdyFramer> framer_;
364 std::unique_ptr<http2::Http2DecoderAdapter> deframer_;
365 StrictMock<MockVisitor> visitor_;
366 QuicStreamFrame stream_frame_;
367 QuicStreamId next_promised_stream_id_;
368 QuicStreamId client_id_1_;
369 QuicStreamId client_id_2_;
370 QuicStreamId client_id_3_;
371 QuicStreamId next_stream_id_;
372 };
373
374 // Run all tests with each version and perspective (client or server).
375 INSTANTIATE_TEST_SUITE_P(Tests, QuicHeadersStreamTest,
376 ::testing::ValuesIn(GetTestParams()),
377 ::testing::PrintToStringParamName());
378
TEST_P(QuicHeadersStreamTest,StreamId)379 TEST_P(QuicHeadersStreamTest, StreamId) {
380 EXPECT_EQ(QuicUtils::GetHeadersStreamId(connection_->transport_version()),
381 headers_stream_->id());
382 }
383
TEST_P(QuicHeadersStreamTest,WriteHeaders)384 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
385 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
386 stream_id += next_stream_id_) {
387 for (bool fin : {false, true}) {
388 if (perspective() == Perspective::IS_SERVER) {
389 WriteAndExpectResponseHeaders(stream_id, fin);
390 } else {
391 for (SpdyPriority priority = 0; priority < 7; ++priority) {
392 // TODO(rch): implement priorities correctly.
393 WriteAndExpectRequestHeaders(stream_id, fin, 0);
394 }
395 }
396 }
397 }
398 }
399
TEST_P(QuicHeadersStreamTest,ProcessRawData)400 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
401 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
402 stream_id += next_stream_id_) {
403 for (bool fin : {false, true}) {
404 for (SpdyPriority priority = 0; priority < 7; ++priority) {
405 // Replace with "WriteHeadersAndSaveData"
406 SpdySerializedFrame frame;
407 if (perspective() == Perspective::IS_SERVER) {
408 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
409 headers_frame.set_fin(fin);
410 headers_frame.set_has_priority(true);
411 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
412 frame = framer_->SerializeFrame(headers_frame);
413 EXPECT_CALL(session_, OnStreamHeadersPriority(
414 stream_id, spdy::SpdyStreamPrecedence(0)));
415 } else {
416 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
417 headers_frame.set_fin(fin);
418 frame = framer_->SerializeFrame(headers_frame);
419 }
420 EXPECT_CALL(session_,
421 OnStreamHeaderList(stream_id, fin, frame.size(), _))
422 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
423 stream_frame_.data_buffer = frame.data();
424 stream_frame_.data_length = frame.size();
425 headers_stream_->OnStreamFrame(stream_frame_);
426 stream_frame_.offset += frame.size();
427 CheckHeaders();
428 }
429 }
430 }
431 }
432
TEST_P(QuicHeadersStreamTest,ProcessPushPromise)433 TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
434 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
435 stream_id += next_stream_id_) {
436 QuicStreamId promised_stream_id = NextPromisedStreamId();
437 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id,
438 headers_.Clone());
439 SpdySerializedFrame frame(framer_->SerializeFrame(push_promise));
440 if (perspective() == Perspective::IS_SERVER) {
441 EXPECT_CALL(*connection_,
442 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
443 "PUSH_PROMISE not supported.", _))
444 .WillRepeatedly(InvokeWithoutArgs(
445 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
446 } else {
447 EXPECT_CALL(session_, MaybeSendRstStreamFrame(promised_stream_id, _, _));
448 }
449 stream_frame_.data_buffer = frame.data();
450 stream_frame_.data_length = frame.size();
451 headers_stream_->OnStreamFrame(stream_frame_);
452 stream_frame_.offset += frame.size();
453 }
454 }
455
TEST_P(QuicHeadersStreamTest,ProcessPriorityFrame)456 TEST_P(QuicHeadersStreamTest, ProcessPriorityFrame) {
457 QuicStreamId parent_stream_id = 0;
458 for (SpdyPriority priority = 0; priority < 7; ++priority) {
459 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
460 stream_id += next_stream_id_) {
461 int weight = Spdy3PriorityToHttp2Weight(priority);
462 SpdyPriorityIR priority_frame(stream_id, parent_stream_id, weight, true);
463 SpdySerializedFrame frame(framer_->SerializeFrame(priority_frame));
464 parent_stream_id = stream_id;
465 if (perspective() == Perspective::IS_CLIENT) {
466 EXPECT_CALL(*connection_,
467 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
468 "Server must not send PRIORITY frames.", _))
469 .WillRepeatedly(InvokeWithoutArgs(
470 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
471 } else {
472 EXPECT_CALL(
473 session_,
474 OnPriorityFrame(stream_id, spdy::SpdyStreamPrecedence(priority)))
475 .Times(1);
476 }
477 stream_frame_.data_buffer = frame.data();
478 stream_frame_.data_length = frame.size();
479 headers_stream_->OnStreamFrame(stream_frame_);
480 stream_frame_.offset += frame.size();
481 }
482 }
483 }
484
TEST_P(QuicHeadersStreamTest,ProcessPushPromiseDisabledSetting)485 TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
486 if (perspective() != Perspective::IS_CLIENT) {
487 return;
488 }
489
490 session_.OnConfigNegotiated();
491 SpdySettingsIR data;
492 // Respect supported settings frames SETTINGS_ENABLE_PUSH.
493 data.AddSetting(SETTINGS_ENABLE_PUSH, 0);
494 SpdySerializedFrame frame(framer_->SerializeFrame(data));
495 stream_frame_.data_buffer = frame.data();
496 stream_frame_.data_length = frame.size();
497 EXPECT_CALL(
498 *connection_,
499 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
500 "Unsupported field of HTTP/2 SETTINGS frame: 2", _));
501 headers_stream_->OnStreamFrame(stream_frame_);
502 }
503
TEST_P(QuicHeadersStreamTest,ProcessLargeRawData)504 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
505 // We want to create a frame that is more than the SPDY Framer's max control
506 // frame size, which is 16K, but less than the HPACK decoders max decode
507 // buffer size, which is 32K.
508 headers_["key0"] = std::string(1 << 13, '.');
509 headers_["key1"] = std::string(1 << 13, '.');
510 headers_["key2"] = std::string(1 << 13, '.');
511 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
512 stream_id += next_stream_id_) {
513 for (bool fin : {false, true}) {
514 for (SpdyPriority priority = 0; priority < 7; ++priority) {
515 // Replace with "WriteHeadersAndSaveData"
516 SpdySerializedFrame frame;
517 if (perspective() == Perspective::IS_SERVER) {
518 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
519 headers_frame.set_fin(fin);
520 headers_frame.set_has_priority(true);
521 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
522 frame = framer_->SerializeFrame(headers_frame);
523 EXPECT_CALL(session_, OnStreamHeadersPriority(
524 stream_id, spdy::SpdyStreamPrecedence(0)));
525 } else {
526 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
527 headers_frame.set_fin(fin);
528 frame = framer_->SerializeFrame(headers_frame);
529 }
530 EXPECT_CALL(session_,
531 OnStreamHeaderList(stream_id, fin, frame.size(), _))
532 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
533 stream_frame_.data_buffer = frame.data();
534 stream_frame_.data_length = frame.size();
535 headers_stream_->OnStreamFrame(stream_frame_);
536 stream_frame_.offset += frame.size();
537 CheckHeaders();
538 }
539 }
540 }
541 }
542
TEST_P(QuicHeadersStreamTest,ProcessBadData)543 TEST_P(QuicHeadersStreamTest, ProcessBadData) {
544 const char kBadData[] = "blah blah blah";
545 EXPECT_CALL(*connection_,
546 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
547 .Times(::testing::AnyNumber());
548 stream_frame_.data_buffer = kBadData;
549 stream_frame_.data_length = strlen(kBadData);
550 headers_stream_->OnStreamFrame(stream_frame_);
551 }
552
TEST_P(QuicHeadersStreamTest,ProcessSpdyDataFrame)553 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
554 SpdyDataIR data(/* stream_id = */ 2, "ping");
555 SpdySerializedFrame frame(framer_->SerializeFrame(data));
556
557 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
558 "SPDY DATA frame received.", _))
559 .WillOnce(InvokeWithoutArgs(
560 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
561 stream_frame_.data_buffer = frame.data();
562 stream_frame_.data_length = frame.size();
563 headers_stream_->OnStreamFrame(stream_frame_);
564 }
565
TEST_P(QuicHeadersStreamTest,ProcessSpdyRstStreamFrame)566 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
567 SpdyRstStreamIR data(/* stream_id = */ 2, ERROR_CODE_PROTOCOL_ERROR);
568 SpdySerializedFrame frame(framer_->SerializeFrame(data));
569 EXPECT_CALL(*connection_,
570 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
571 "SPDY RST_STREAM frame received.", _))
572 .WillOnce(InvokeWithoutArgs(
573 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
574 stream_frame_.data_buffer = frame.data();
575 stream_frame_.data_length = frame.size();
576 headers_stream_->OnStreamFrame(stream_frame_);
577 }
578
TEST_P(QuicHeadersStreamTest,RespectHttp2SettingsFrameSupportedFields)579 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
580 const uint32_t kTestHeaderTableSize = 1000;
581 SpdySettingsIR data;
582 // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE,
583 // SETTINGS_MAX_HEADER_LIST_SIZE.
584 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, kTestHeaderTableSize);
585 data.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE, 2000);
586 SpdySerializedFrame frame(framer_->SerializeFrame(data));
587 stream_frame_.data_buffer = frame.data();
588 stream_frame_.data_length = frame.size();
589 headers_stream_->OnStreamFrame(stream_frame_);
590 EXPECT_EQ(kTestHeaderTableSize, QuicSpdySessionPeer::GetSpdyFramer(&session_)
591 ->header_encoder_table_size());
592 }
593
594 // Regression test for b/208997000.
TEST_P(QuicHeadersStreamTest,LimitEncoderDynamicTableSize)595 TEST_P(QuicHeadersStreamTest, LimitEncoderDynamicTableSize) {
596 const uint32_t kVeryLargeTableSizeLimit = 1024 * 1024 * 1024;
597 SpdySettingsIR data;
598 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, kVeryLargeTableSizeLimit);
599 SpdySerializedFrame frame(framer_->SerializeFrame(data));
600 stream_frame_.data_buffer = frame.data();
601 stream_frame_.data_length = frame.size();
602 headers_stream_->OnStreamFrame(stream_frame_);
603 EXPECT_EQ(16384u, QuicSpdySessionPeer::GetSpdyFramer(&session_)
604 ->header_encoder_table_size());
605 }
606
TEST_P(QuicHeadersStreamTest,RespectHttp2SettingsFrameUnsupportedFields)607 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
608 SpdySettingsIR data;
609 // Does not support SETTINGS_MAX_CONCURRENT_STREAMS,
610 // SETTINGS_INITIAL_WINDOW_SIZE, SETTINGS_ENABLE_PUSH and
611 // SETTINGS_MAX_FRAME_SIZE.
612 data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 100);
613 data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 100);
614 data.AddSetting(SETTINGS_ENABLE_PUSH, 1);
615 data.AddSetting(SETTINGS_MAX_FRAME_SIZE, 1250);
616 SpdySerializedFrame frame(framer_->SerializeFrame(data));
617 EXPECT_CALL(*connection_,
618 CloseConnection(
619 QUIC_INVALID_HEADERS_STREAM_DATA,
620 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
621 SETTINGS_MAX_CONCURRENT_STREAMS),
622 _));
623 EXPECT_CALL(*connection_,
624 CloseConnection(
625 QUIC_INVALID_HEADERS_STREAM_DATA,
626 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
627 SETTINGS_INITIAL_WINDOW_SIZE),
628 _));
629 if (session_.perspective() == Perspective::IS_CLIENT) {
630 EXPECT_CALL(*connection_,
631 CloseConnection(
632 QUIC_INVALID_HEADERS_STREAM_DATA,
633 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
634 SETTINGS_ENABLE_PUSH),
635 _));
636 }
637 EXPECT_CALL(*connection_,
638 CloseConnection(
639 QUIC_INVALID_HEADERS_STREAM_DATA,
640 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
641 SETTINGS_MAX_FRAME_SIZE),
642 _));
643 stream_frame_.data_buffer = frame.data();
644 stream_frame_.data_length = frame.size();
645 headers_stream_->OnStreamFrame(stream_frame_);
646 }
647
TEST_P(QuicHeadersStreamTest,ProcessSpdyPingFrame)648 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
649 SpdyPingIR data(1);
650 SpdySerializedFrame frame(framer_->SerializeFrame(data));
651 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
652 "SPDY PING frame received.", _))
653 .WillOnce(InvokeWithoutArgs(
654 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
655 stream_frame_.data_buffer = frame.data();
656 stream_frame_.data_length = frame.size();
657 headers_stream_->OnStreamFrame(stream_frame_);
658 }
659
TEST_P(QuicHeadersStreamTest,ProcessSpdyGoAwayFrame)660 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
661 SpdyGoAwayIR data(/* last_good_stream_id = */ 1, ERROR_CODE_PROTOCOL_ERROR,
662 "go away");
663 SpdySerializedFrame frame(framer_->SerializeFrame(data));
664 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
665 "SPDY GOAWAY frame received.", _))
666 .WillOnce(InvokeWithoutArgs(
667 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
668 stream_frame_.data_buffer = frame.data();
669 stream_frame_.data_length = frame.size();
670 headers_stream_->OnStreamFrame(stream_frame_);
671 }
672
TEST_P(QuicHeadersStreamTest,ProcessSpdyWindowUpdateFrame)673 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
674 SpdyWindowUpdateIR data(/* stream_id = */ 1, /* delta = */ 1);
675 SpdySerializedFrame frame(framer_->SerializeFrame(data));
676 EXPECT_CALL(*connection_,
677 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
678 "SPDY WINDOW_UPDATE frame received.", _))
679 .WillOnce(InvokeWithoutArgs(
680 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
681 stream_frame_.data_buffer = frame.data();
682 stream_frame_.data_length = frame.size();
683 headers_stream_->OnStreamFrame(stream_frame_);
684 }
685
TEST_P(QuicHeadersStreamTest,NoConnectionLevelFlowControl)686 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
687 EXPECT_FALSE(QuicStreamPeer::StreamContributesToConnectionFlowControl(
688 headers_stream_));
689 }
690
TEST_P(QuicHeadersStreamTest,AckSentData)691 TEST_P(QuicHeadersStreamTest, AckSentData) {
692 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
693 connection_->transport_version()),
694 _, _, NO_FIN, _, _))
695 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
696 InSequence s;
697 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener1(
698 new MockAckListener());
699 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener2(
700 new MockAckListener());
701 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener3(
702 new MockAckListener());
703
704 // Packet 1.
705 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
706 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
707 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
708
709 // Packet 2.
710 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
711 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
712
713 // Packet 3.
714 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
715
716 // Packet 2 gets retransmitted.
717 EXPECT_CALL(*ack_listener3, OnPacketRetransmitted(7)).Times(1);
718 EXPECT_CALL(*ack_listener2, OnPacketRetransmitted(7)).Times(1);
719 headers_stream_->OnStreamFrameRetransmitted(21, 7, false);
720 headers_stream_->OnStreamFrameRetransmitted(28, 7, false);
721
722 // Packets are acked in order: 2, 3, 1.
723 QuicByteCount newly_acked_length = 0;
724 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
725 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
726 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
727 21, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
728 &newly_acked_length));
729 EXPECT_EQ(7u, newly_acked_length);
730 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
731 28, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
732 &newly_acked_length));
733 EXPECT_EQ(7u, newly_acked_length);
734
735 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
736 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
737 35, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
738 &newly_acked_length));
739 EXPECT_EQ(7u, newly_acked_length);
740
741 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
742 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
743 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
744 0, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
745 &newly_acked_length));
746 EXPECT_EQ(7u, newly_acked_length);
747 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
748 7, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
749 &newly_acked_length));
750 EXPECT_EQ(7u, newly_acked_length);
751 // Unsent data is acked.
752 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
753 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
754 14, 10, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
755 &newly_acked_length));
756 EXPECT_EQ(7u, newly_acked_length);
757 }
758
TEST_P(QuicHeadersStreamTest,FrameContainsMultipleHeaders)759 TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
760 // In this test, a stream frame can contain multiple headers.
761 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
762 connection_->transport_version()),
763 _, _, NO_FIN, _, _))
764 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
765 InSequence s;
766 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener1(
767 new MockAckListener());
768 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener2(
769 new MockAckListener());
770 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener3(
771 new MockAckListener());
772
773 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
774 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
775 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
776 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
777 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
778 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
779
780 // Frame 1 is retransmitted.
781 EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(14));
782 EXPECT_CALL(*ack_listener2, OnPacketRetransmitted(3));
783 headers_stream_->OnStreamFrameRetransmitted(0, 17, false);
784
785 // Frames are acked in order: 2, 3, 1.
786 QuicByteCount newly_acked_length = 0;
787 EXPECT_CALL(*ack_listener2, OnPacketAcked(4, _));
788 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
789 EXPECT_CALL(*ack_listener2, OnPacketAcked(2, _));
790 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
791 17, 13, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
792 &newly_acked_length));
793 EXPECT_EQ(13u, newly_acked_length);
794
795 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
796 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
797 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
798 30, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
799 &newly_acked_length));
800 EXPECT_EQ(12u, newly_acked_length);
801
802 EXPECT_CALL(*ack_listener1, OnPacketAcked(14, _));
803 EXPECT_CALL(*ack_listener2, OnPacketAcked(3, _));
804 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
805 0, 17, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
806 &newly_acked_length));
807 EXPECT_EQ(17u, newly_acked_length);
808 }
809
TEST_P(QuicHeadersStreamTest,HeadersGetAckedMultipleTimes)810 TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
811 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
812 connection_->transport_version()),
813 _, _, NO_FIN, _, _))
814 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
815 InSequence s;
816 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener1(
817 new MockAckListener());
818 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener2(
819 new MockAckListener());
820 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener3(
821 new MockAckListener());
822
823 // Send [0, 42).
824 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
825 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
826 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
827 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
828 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
829 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
830
831 // Ack [15, 20), [5, 25), [10, 17), [0, 12) and [22, 42).
832 QuicByteCount newly_acked_length = 0;
833 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
834 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
835 15, 5, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
836 &newly_acked_length));
837 EXPECT_EQ(5u, newly_acked_length);
838
839 EXPECT_CALL(*ack_listener1, OnPacketAcked(9, _));
840 EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
841 EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
842 EXPECT_CALL(*ack_listener3, OnPacketAcked(4, _));
843 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
844 5, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
845 &newly_acked_length));
846 EXPECT_EQ(15u, newly_acked_length);
847
848 // Duplicate ack.
849 EXPECT_FALSE(headers_stream_->OnStreamFrameAcked(
850 10, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
851 &newly_acked_length));
852 EXPECT_EQ(0u, newly_acked_length);
853
854 EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
855 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
856 0, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
857 &newly_acked_length));
858 EXPECT_EQ(5u, newly_acked_length);
859
860 EXPECT_CALL(*ack_listener3, OnPacketAcked(3, _));
861 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
862 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
863 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
864 22, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
865 &newly_acked_length));
866 EXPECT_EQ(17u, newly_acked_length);
867 }
868
TEST_P(QuicHeadersStreamTest,CloseOnPushPromiseToServer)869 TEST_P(QuicHeadersStreamTest, CloseOnPushPromiseToServer) {
870 if (perspective() == Perspective::IS_CLIENT) {
871 return;
872 }
873 QuicStreamId promised_id = 1;
874 SpdyPushPromiseIR push_promise(client_id_1_, promised_id, headers_.Clone());
875 SpdySerializedFrame frame = framer_->SerializeFrame(push_promise);
876 stream_frame_.data_buffer = frame.data();
877 stream_frame_.data_length = frame.size();
878 EXPECT_CALL(session_, OnStreamHeaderList(_, _, _, _));
879 // TODO(lassey): Check for HTTP_WRONG_STREAM error code.
880 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
881 "PUSH_PROMISE not supported.", _));
882 headers_stream_->OnStreamFrame(stream_frame_);
883 }
884
885 } // namespace
886 } // namespace test
887 } // namespace quic
888