blob: cfccc9226880abbd865c4c3a9771e1937faa7322 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/core/http/quic_headers_stream.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
7#include <cstdint>
8#include <ostream>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <tuple>
11#include <utility>
12#include <vector>
13
vasilvva163b382020-12-04 11:47:46 -080014#include "absl/strings/str_cat.h"
vasilvve2707e32020-10-08 12:27:46 -070015#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050016#include "quic/core/crypto/null_encrypter.h"
17#include "quic/core/http/spdy_utils.h"
18#include "quic/core/quic_data_writer.h"
19#include "quic/core/quic_utils.h"
20#include "quic/platform/api/quic_bug_tracker.h"
21#include "quic/platform/api/quic_expect_bug.h"
22#include "quic/platform/api/quic_flags.h"
23#include "quic/platform/api/quic_logging.h"
24#include "quic/platform/api/quic_test.h"
25#include "quic/test_tools/quic_connection_peer.h"
26#include "quic/test_tools/quic_spdy_session_peer.h"
27#include "quic/test_tools/quic_stream_peer.h"
28#include "quic/test_tools/quic_test_utils.h"
29#include "common/quiche_endian.h"
30#include "spdy/core/http2_frame_decoder_adapter.h"
31#include "spdy/core/recording_headers_handler.h"
32#include "spdy/core/spdy_alt_svc_wire_format.h"
33#include "spdy/core/spdy_protocol.h"
34#include "spdy/core/spdy_test_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050035
36using spdy::ERROR_CODE_PROTOCOL_ERROR;
QUICHE team6169e492020-11-10 14:05:30 -080037using spdy::RecordingHeadersHandler;
QUICHE teama6ef0a62019-03-07 20:34:33 -050038using spdy::SETTINGS_ENABLE_PUSH;
39using spdy::SETTINGS_HEADER_TABLE_SIZE;
40using spdy::SETTINGS_INITIAL_WINDOW_SIZE;
41using spdy::SETTINGS_MAX_CONCURRENT_STREAMS;
42using spdy::SETTINGS_MAX_FRAME_SIZE;
QUICHE teama6ef0a62019-03-07 20:34:33 -050043using spdy::Spdy3PriorityToHttp2Weight;
44using spdy::SpdyAltSvcWireFormat;
45using spdy::SpdyDataIR;
46using spdy::SpdyErrorCode;
47using spdy::SpdyFramer;
48using spdy::SpdyFramerVisitorInterface;
49using spdy::SpdyGoAwayIR;
50using spdy::SpdyHeaderBlock;
51using spdy::SpdyHeadersHandlerInterface;
52using spdy::SpdyHeadersIR;
53using spdy::SpdyKnownSettingsId;
54using spdy::SpdyPingId;
55using spdy::SpdyPingIR;
56using spdy::SpdyPriority;
57using spdy::SpdyPriorityIR;
58using spdy::SpdyPushPromiseIR;
59using spdy::SpdyRstStreamIR;
60using spdy::SpdySerializedFrame;
61using spdy::SpdySettingsId;
62using spdy::SpdySettingsIR;
63using spdy::SpdyStreamId;
64using spdy::SpdyWindowUpdateIR;
QUICHE teama6ef0a62019-03-07 20:34:33 -050065using testing::_;
wub8eea9192020-08-13 12:05:40 -070066using testing::AnyNumber;
QUICHE teama6ef0a62019-03-07 20:34:33 -050067using testing::AtLeast;
68using testing::InSequence;
69using testing::Invoke;
70using testing::Return;
71using testing::StrictMock;
72using testing::WithArgs;
73
74namespace quic {
75namespace test {
76
77class MockQuicHpackDebugVisitor : public QuicHpackDebugVisitor {
78 public:
79 MockQuicHpackDebugVisitor() : QuicHpackDebugVisitor() {}
80 MockQuicHpackDebugVisitor(const MockQuicHpackDebugVisitor&) = delete;
81 MockQuicHpackDebugVisitor& operator=(const MockQuicHpackDebugVisitor&) =
82 delete;
83
wub713afae2020-04-27 07:48:31 -070084 MOCK_METHOD(void, OnUseEntry, (QuicTime::Delta elapsed), (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -050085};
86
87namespace {
88
89class MockVisitor : public SpdyFramerVisitorInterface {
90 public:
wub713afae2020-04-27 07:48:31 -070091 MOCK_METHOD(void,
92 OnError,
fayang80366682020-07-24 09:19:11 -070093 (http2::Http2DecoderAdapter::SpdyFramerError error,
94 std::string detailed_error),
wub713afae2020-04-27 07:48:31 -070095 (override));
96 MOCK_METHOD(void,
97 OnDataFrameHeader,
98 (SpdyStreamId stream_id, size_t length, bool fin),
99 (override));
100 MOCK_METHOD(void,
101 OnStreamFrameData,
102 (SpdyStreamId stream_id, const char*, size_t len),
103 (override));
104 MOCK_METHOD(void, OnStreamEnd, (SpdyStreamId stream_id), (override));
105 MOCK_METHOD(void,
106 OnStreamPadding,
107 (SpdyStreamId stream_id, size_t len),
108 (override));
109 MOCK_METHOD(SpdyHeadersHandlerInterface*,
110 OnHeaderFrameStart,
111 (SpdyStreamId stream_id),
112 (override));
113 MOCK_METHOD(void, OnHeaderFrameEnd, (SpdyStreamId stream_id), (override));
114 MOCK_METHOD(void,
115 OnRstStream,
116 (SpdyStreamId stream_id, SpdyErrorCode error_code),
117 (override));
118 MOCK_METHOD(void, OnSettings, (), (override));
119 MOCK_METHOD(void, OnSetting, (SpdySettingsId id, uint32_t value), (override));
120 MOCK_METHOD(void, OnSettingsAck, (), (override));
121 MOCK_METHOD(void, OnSettingsEnd, (), (override));
122 MOCK_METHOD(void, OnPing, (SpdyPingId unique_id, bool is_ack), (override));
123 MOCK_METHOD(void,
124 OnGoAway,
125 (SpdyStreamId last_accepted_stream_id, SpdyErrorCode error_code),
126 (override));
127 MOCK_METHOD(void,
128 OnHeaders,
129 (SpdyStreamId stream_id,
130 bool has_priority,
131 int weight,
132 SpdyStreamId parent_stream_id,
133 bool exclusive,
134 bool fin,
135 bool end),
136 (override));
137 MOCK_METHOD(void,
138 OnWindowUpdate,
139 (SpdyStreamId stream_id, int delta_window_size),
140 (override));
141 MOCK_METHOD(void,
142 OnPushPromise,
143 (SpdyStreamId stream_id,
144 SpdyStreamId promised_stream_id,
145 bool end),
146 (override));
147 MOCK_METHOD(void,
148 OnContinuation,
149 (SpdyStreamId stream_id, bool end),
150 (override));
151 MOCK_METHOD(
152 void,
153 OnAltSvc,
154 (SpdyStreamId stream_id,
vasilvve2707e32020-10-08 12:27:46 -0700155 absl::string_view origin,
wub713afae2020-04-27 07:48:31 -0700156 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector),
157 (override));
158 MOCK_METHOD(void,
159 OnPriority,
160 (SpdyStreamId stream_id,
161 SpdyStreamId parent_stream_id,
162 int weight,
163 bool exclusive),
164 (override));
bnca5a30132020-12-17 13:50:27 -0800165 MOCK_METHOD(void,
166 OnPriorityUpdate,
167 (SpdyStreamId prioritized_stream_id,
168 absl::string_view priority_field_value),
169 (override));
wub713afae2020-04-27 07:48:31 -0700170 MOCK_METHOD(bool,
171 OnUnknownFrame,
172 (SpdyStreamId stream_id, uint8_t frame_type),
173 (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500174};
175
176struct TestParams {
177 TestParams(const ParsedQuicVersion& version, Perspective perspective)
178 : version(version), perspective(perspective) {
dschinazi552accc2019-06-17 17:07:34 -0700179 QUIC_LOG(INFO) << "TestParams: " << *this;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500180 }
181
182 TestParams(const TestParams& other)
183 : version(other.version), perspective(other.perspective) {}
184
dschinazi552accc2019-06-17 17:07:34 -0700185 friend std::ostream& operator<<(std::ostream& os, const TestParams& tp) {
186 os << "{ version: " << ParsedQuicVersionToString(tp.version)
187 << ", perspective: "
188 << (tp.perspective == Perspective::IS_CLIENT ? "client" : "server")
189 << "}";
190 return os;
191 }
192
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 ParsedQuicVersion version;
194 Perspective perspective;
195};
196
dschinazi142051a2019-09-18 18:17:29 -0700197// Used by ::testing::PrintToStringParamName().
198std::string PrintToString(const TestParams& tp) {
vasilvva163b382020-12-04 11:47:46 -0800199 return absl::StrCat(
dschinazi142051a2019-09-18 18:17:29 -0700200 ParsedQuicVersionToString(tp.version), "_",
201 (tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
202}
203
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204std::vector<TestParams> GetTestParams() {
205 std::vector<TestParams> params;
206 ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
207 for (size_t i = 0; i < all_supported_versions.size(); ++i) {
renjietanga29a96a2019-10-10 12:47:50 -0700208 if (VersionUsesHttp3(all_supported_versions[i].transport_version)) {
renjietang3c3dfb72019-07-26 11:55:52 -0700209 continue;
210 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500211 for (Perspective p : {Perspective::IS_SERVER, Perspective::IS_CLIENT}) {
212 params.emplace_back(all_supported_versions[i], p);
213 }
214 }
215 return params;
216}
217
218class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
219 public:
220 QuicHeadersStreamTest()
221 : connection_(new StrictMock<MockQuicConnection>(&helper_,
222 &alarm_factory_,
223 perspective(),
224 GetVersion())),
225 session_(connection_),
226 body_("hello world"),
227 stream_frame_(
228 QuicUtils::GetHeadersStreamId(connection_->transport_version()),
229 /*fin=*/false,
230 /*offset=*/0,
231 ""),
232 next_promised_stream_id_(2) {
bnc30d610c2019-07-08 18:39:59 -0700233 QuicSpdySessionPeer::SetMaxInboundHeaderListSize(&session_, 256 * 1024);
wub8eea9192020-08-13 12:05:40 -0700234 EXPECT_CALL(session_, OnCongestionWindowChange(_)).Times(AnyNumber());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 session_.Initialize();
fayang9c41f8b2020-10-30 13:13:06 -0700236 connection_->SetEncrypter(
237 quic::ENCRYPTION_FORWARD_SECURE,
238 std::make_unique<quic::NullEncrypter>(connection_->perspective()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500239 headers_stream_ = QuicSpdySessionPeer::GetHeadersStream(&session_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 headers_[":status"] = "200 Ok";
241 headers_["content-length"] = "11";
242 framer_ = std::unique_ptr<SpdyFramer>(
243 new SpdyFramer(SpdyFramer::ENABLE_COMPRESSION));
244 deframer_ = std::unique_ptr<http2::Http2DecoderAdapter>(
245 new http2::Http2DecoderAdapter());
246 deframer_->set_visitor(&visitor_);
renjietangd1d00852019-09-06 10:43:12 -0700247 EXPECT_EQ(transport_version(), session_.transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500248 EXPECT_TRUE(headers_stream_ != nullptr);
249 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
250 client_id_1_ = GetNthClientInitiatedBidirectionalStreamId(
251 connection_->transport_version(), 0);
252 client_id_2_ = GetNthClientInitiatedBidirectionalStreamId(
253 connection_->transport_version(), 1);
254 client_id_3_ = GetNthClientInitiatedBidirectionalStreamId(
255 connection_->transport_version(), 2);
256 next_stream_id_ =
257 QuicUtils::StreamIdDelta(connection_->transport_version());
258 }
259
260 QuicStreamId GetNthClientInitiatedId(int n) {
261 return GetNthClientInitiatedBidirectionalStreamId(
262 connection_->transport_version(), n);
263 }
264
265 QuicConsumedData SaveIov(size_t write_length) {
266 char* buf = new char[write_length];
QUICHE team173c48f2019-11-19 16:34:44 -0800267 QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 headers_stream_->WriteStreamData(headers_stream_->stream_bytes_written(),
269 write_length, &writer);
270 saved_data_.append(buf, write_length);
271 delete[] buf;
272 return QuicConsumedData(write_length, false);
273 }
274
275 void SavePayload(const char* data, size_t len) {
276 saved_payloads_.append(data, len);
277 }
278
279 bool SaveHeaderData(const char* data, int len) {
280 saved_header_data_.append(data, len);
281 return true;
282 }
283
vasilvve2707e32020-10-08 12:27:46 -0700284 void SaveHeaderDataStringPiece(absl::string_view data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285 saved_header_data_.append(data.data(), data.length());
286 }
287
288 void SavePromiseHeaderList(QuicStreamId /* stream_id */,
289 QuicStreamId /* promised_stream_id */,
290 size_t size,
291 const QuicHeaderList& header_list) {
292 SaveToHandler(size, header_list);
293 }
294
295 void SaveHeaderList(QuicStreamId /* stream_id */,
296 bool /* fin */,
297 size_t size,
298 const QuicHeaderList& header_list) {
299 SaveToHandler(size, header_list);
300 }
301
302 void SaveToHandler(size_t size, const QuicHeaderList& header_list) {
QUICHE team6169e492020-11-10 14:05:30 -0800303 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 headers_handler_->OnHeaderBlockStart();
305 for (const auto& p : header_list) {
306 headers_handler_->OnHeader(p.first, p.second);
307 }
308 headers_handler_->OnHeaderBlockEnd(size, size);
309 }
310
311 void WriteAndExpectRequestHeaders(QuicStreamId stream_id,
312 bool fin,
313 SpdyPriority priority) {
314 WriteHeadersAndCheckData(stream_id, fin, priority, true /*is_request*/);
315 }
316
317 void WriteAndExpectResponseHeaders(QuicStreamId stream_id, bool fin) {
318 WriteHeadersAndCheckData(stream_id, fin, 0, false /*is_request*/);
319 }
320
321 void WriteHeadersAndCheckData(QuicStreamId stream_id,
322 bool fin,
323 SpdyPriority priority,
324 bool is_request) {
325 // Write the headers and capture the outgoing data
renjietang7c239172020-02-21 13:50:39 -0800326 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800328 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800329 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500330 QuicSpdySessionPeer::WriteHeadersOnHeadersStream(
fayang476683a2019-07-25 12:42:16 -0700331 &session_, stream_id, headers_.Clone(), fin,
332 spdy::SpdyStreamPrecedence(priority), nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333
334 // Parse the outgoing data and check that it matches was was written.
335 if (is_request) {
336 EXPECT_CALL(visitor_,
337 OnHeaders(stream_id, kHasPriority,
338 Spdy3PriorityToHttp2Weight(priority),
339 /*parent_stream_id=*/0,
340 /*exclusive=*/false, fin, kFrameComplete));
341 } else {
342 EXPECT_CALL(visitor_,
343 OnHeaders(stream_id, !kHasPriority,
wub0b2ae542019-10-24 08:32:06 -0700344 /*weight=*/0,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500345 /*parent_stream_id=*/0,
346 /*exclusive=*/false, fin, kFrameComplete));
347 }
QUICHE team6169e492020-11-10 14:05:30 -0800348 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500349 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
350 .WillOnce(Return(headers_handler_.get()));
351 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id)).Times(1);
352 if (fin) {
353 EXPECT_CALL(visitor_, OnStreamEnd(stream_id));
354 }
355 deframer_->ProcessInput(saved_data_.data(), saved_data_.length());
356 EXPECT_FALSE(deframer_->HasError())
357 << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
358 deframer_->spdy_framer_error());
359
360 CheckHeaders();
361 saved_data_.clear();
362 }
363
364 void CheckHeaders() {
rchb0451852019-09-11 21:17:01 -0700365 ASSERT_TRUE(headers_handler_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500366 EXPECT_EQ(headers_, headers_handler_->decoded_block());
367 headers_handler_.reset();
368 }
369
370 Perspective perspective() const { return GetParam().perspective; }
371
372 QuicTransportVersion transport_version() const {
373 return GetParam().version.transport_version;
374 }
375
376 ParsedQuicVersionVector GetVersion() {
377 ParsedQuicVersionVector versions;
378 versions.push_back(GetParam().version);
379 return versions;
380 }
381
382 void TearDownLocalConnectionState() {
383 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
384 }
385
386 QuicStreamId NextPromisedStreamId() {
387 return next_promised_stream_id_ += next_stream_id_;
388 }
389
QUICHE team897763c2020-04-14 08:15:58 -0700390 static constexpr bool kFrameComplete = true;
391 static constexpr bool kHasPriority = true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500392
393 MockQuicConnectionHelper helper_;
394 MockAlarmFactory alarm_factory_;
395 StrictMock<MockQuicConnection>* connection_;
396 StrictMock<MockQuicSpdySession> session_;
397 QuicHeadersStream* headers_stream_;
398 SpdyHeaderBlock headers_;
QUICHE team6169e492020-11-10 14:05:30 -0800399 std::unique_ptr<RecordingHeadersHandler> headers_handler_;
vasilvvc48c8712019-03-11 13:38:16 -0700400 std::string body_;
401 std::string saved_data_;
402 std::string saved_header_data_;
403 std::string saved_payloads_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500404 std::unique_ptr<SpdyFramer> framer_;
405 std::unique_ptr<http2::Http2DecoderAdapter> deframer_;
406 StrictMock<MockVisitor> visitor_;
407 QuicStreamFrame stream_frame_;
408 QuicStreamId next_promised_stream_id_;
409 QuicStreamId client_id_1_;
410 QuicStreamId client_id_2_;
411 QuicStreamId client_id_3_;
412 QuicStreamId next_stream_id_;
413};
414
415// Run all tests with each version and perspective (client or server).
vasilvvc48c8712019-03-11 13:38:16 -0700416INSTANTIATE_TEST_SUITE_P(Tests,
417 QuicHeadersStreamTest,
dschinazi142051a2019-09-18 18:17:29 -0700418 ::testing::ValuesIn(GetTestParams()),
419 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500420
421TEST_P(QuicHeadersStreamTest, StreamId) {
422 EXPECT_EQ(QuicUtils::GetHeadersStreamId(connection_->transport_version()),
423 headers_stream_->id());
424}
425
426TEST_P(QuicHeadersStreamTest, WriteHeaders) {
427 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
428 stream_id += next_stream_id_) {
429 for (bool fin : {false, true}) {
430 if (perspective() == Perspective::IS_SERVER) {
431 WriteAndExpectResponseHeaders(stream_id, fin);
432 } else {
433 for (SpdyPriority priority = 0; priority < 7; ++priority) {
434 // TODO(rch): implement priorities correctly.
435 WriteAndExpectRequestHeaders(stream_id, fin, 0);
436 }
437 }
438 }
439 }
440}
441
442TEST_P(QuicHeadersStreamTest, WritePushPromises) {
443 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
444 stream_id += next_stream_id_) {
445 QuicStreamId promised_stream_id = NextPromisedStreamId();
446 if (perspective() == Perspective::IS_SERVER) {
447 // Write the headers and capture the outgoing data
renjietang7c239172020-02-21 13:50:39 -0800448 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500449 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800450 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800451 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500452 session_.WritePushPromise(stream_id, promised_stream_id,
453 headers_.Clone());
454
455 // Parse the outgoing data and check that it matches was was written.
456 EXPECT_CALL(visitor_,
457 OnPushPromise(stream_id, promised_stream_id, kFrameComplete));
QUICHE team6169e492020-11-10 14:05:30 -0800458 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500459 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
460 .WillOnce(Return(headers_handler_.get()));
461 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id)).Times(1);
462 deframer_->ProcessInput(saved_data_.data(), saved_data_.length());
463 EXPECT_FALSE(deframer_->HasError())
464 << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
465 deframer_->spdy_framer_error());
466 CheckHeaders();
467 saved_data_.clear();
468 } else {
469 EXPECT_QUIC_BUG(session_.WritePushPromise(stream_id, promised_stream_id,
470 headers_.Clone()),
471 "Client shouldn't send PUSH_PROMISE");
472 }
473 }
474}
475
476TEST_P(QuicHeadersStreamTest, ProcessRawData) {
477 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
478 stream_id += next_stream_id_) {
479 for (bool fin : {false, true}) {
480 for (SpdyPriority priority = 0; priority < 7; ++priority) {
481 // Replace with "WriteHeadersAndSaveData"
482 SpdySerializedFrame frame;
483 if (perspective() == Perspective::IS_SERVER) {
484 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
485 headers_frame.set_fin(fin);
486 headers_frame.set_has_priority(true);
487 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
488 frame = framer_->SerializeFrame(headers_frame);
fayang476683a2019-07-25 12:42:16 -0700489 EXPECT_CALL(session_, OnStreamHeadersPriority(
490 stream_id, spdy::SpdyStreamPrecedence(0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500491 } else {
492 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
493 headers_frame.set_fin(fin);
494 frame = framer_->SerializeFrame(headers_frame);
495 }
496 EXPECT_CALL(session_,
497 OnStreamHeaderList(stream_id, fin, frame.size(), _))
498 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
499 stream_frame_.data_buffer = frame.data();
500 stream_frame_.data_length = frame.size();
501 headers_stream_->OnStreamFrame(stream_frame_);
502 stream_frame_.offset += frame.size();
503 CheckHeaders();
504 }
505 }
506 }
507}
508
509TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
510 if (perspective() == Perspective::IS_SERVER) {
511 return;
512 }
513 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
514 stream_id += next_stream_id_) {
515 QuicStreamId promised_stream_id = NextPromisedStreamId();
516 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id,
517 headers_.Clone());
518 SpdySerializedFrame frame(framer_->SerializeFrame(push_promise));
dschinazi552accc2019-06-17 17:07:34 -0700519 bool connection_closed = false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500520 if (perspective() == Perspective::IS_SERVER) {
521 EXPECT_CALL(*connection_,
522 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
523 "PUSH_PROMISE not supported.", _))
524 .WillRepeatedly(InvokeWithoutArgs(
525 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
526 } else {
dschinazi552accc2019-06-17 17:07:34 -0700527 ON_CALL(*connection_, CloseConnection(_, _, _))
528 .WillByDefault(testing::Assign(&connection_closed, true));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500529 EXPECT_CALL(session_, OnPromiseHeaderList(stream_id, promised_stream_id,
530 frame.size(), _))
531 .WillOnce(
532 Invoke(this, &QuicHeadersStreamTest::SavePromiseHeaderList));
533 }
534 stream_frame_.data_buffer = frame.data();
535 stream_frame_.data_length = frame.size();
536 headers_stream_->OnStreamFrame(stream_frame_);
537 if (perspective() == Perspective::IS_CLIENT) {
538 stream_frame_.offset += frame.size();
dschinazi552accc2019-06-17 17:07:34 -0700539 // CheckHeaders crashes if the connection is closed so this ensures we
540 // fail the test instead of crashing.
541 ASSERT_FALSE(connection_closed);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542 CheckHeaders();
543 }
544 }
545}
546
547TEST_P(QuicHeadersStreamTest, ProcessPriorityFrame) {
548 QuicStreamId parent_stream_id = 0;
549 for (SpdyPriority priority = 0; priority < 7; ++priority) {
550 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
551 stream_id += next_stream_id_) {
552 int weight = Spdy3PriorityToHttp2Weight(priority);
553 SpdyPriorityIR priority_frame(stream_id, parent_stream_id, weight, true);
554 SpdySerializedFrame frame(framer_->SerializeFrame(priority_frame));
555 parent_stream_id = stream_id;
fayang8265a2a2019-10-16 11:23:51 -0700556 if (perspective() == Perspective::IS_CLIENT) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500557 EXPECT_CALL(*connection_,
558 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
559 "Server must not send PRIORITY frames.", _))
560 .WillRepeatedly(InvokeWithoutArgs(
561 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
562 } else {
fayang476683a2019-07-25 12:42:16 -0700563 EXPECT_CALL(
564 session_,
565 OnPriorityFrame(stream_id, spdy::SpdyStreamPrecedence(priority)))
566 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500567 }
568 stream_frame_.data_buffer = frame.data();
569 stream_frame_.data_length = frame.size();
570 headers_stream_->OnStreamFrame(stream_frame_);
571 stream_frame_.offset += frame.size();
572 }
573 }
574}
575
576TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
577 session_.OnConfigNegotiated();
578 SpdySettingsIR data;
579 // Respect supported settings frames SETTINGS_ENABLE_PUSH.
580 data.AddSetting(SETTINGS_ENABLE_PUSH, 0);
581 SpdySerializedFrame frame(framer_->SerializeFrame(data));
582 stream_frame_.data_buffer = frame.data();
583 stream_frame_.data_length = frame.size();
584 if (perspective() == Perspective::IS_CLIENT) {
585 EXPECT_CALL(
586 *connection_,
587 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
588 "Unsupported field of HTTP/2 SETTINGS frame: 2", _));
589 }
590 headers_stream_->OnStreamFrame(stream_frame_);
591 EXPECT_EQ(session_.server_push_enabled(),
592 perspective() == Perspective::IS_CLIENT);
593}
594
595TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500596 // We want to create a frame that is more than the SPDY Framer's max control
597 // frame size, which is 16K, but less than the HPACK decoders max decode
598 // buffer size, which is 32K.
vasilvvc48c8712019-03-11 13:38:16 -0700599 headers_["key0"] = std::string(1 << 13, '.');
600 headers_["key1"] = std::string(1 << 13, '.');
601 headers_["key2"] = std::string(1 << 13, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500602 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
603 stream_id += next_stream_id_) {
604 for (bool fin : {false, true}) {
605 for (SpdyPriority priority = 0; priority < 7; ++priority) {
606 // Replace with "WriteHeadersAndSaveData"
607 SpdySerializedFrame frame;
608 if (perspective() == Perspective::IS_SERVER) {
609 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
610 headers_frame.set_fin(fin);
611 headers_frame.set_has_priority(true);
612 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
613 frame = framer_->SerializeFrame(headers_frame);
fayang476683a2019-07-25 12:42:16 -0700614 EXPECT_CALL(session_, OnStreamHeadersPriority(
615 stream_id, spdy::SpdyStreamPrecedence(0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500616 } else {
617 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
618 headers_frame.set_fin(fin);
619 frame = framer_->SerializeFrame(headers_frame);
620 }
621 EXPECT_CALL(session_,
622 OnStreamHeaderList(stream_id, fin, frame.size(), _))
623 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
624 stream_frame_.data_buffer = frame.data();
625 stream_frame_.data_length = frame.size();
626 headers_stream_->OnStreamFrame(stream_frame_);
627 stream_frame_.offset += frame.size();
628 CheckHeaders();
629 }
630 }
631 }
632}
633
634TEST_P(QuicHeadersStreamTest, ProcessBadData) {
635 const char kBadData[] = "blah blah blah";
636 EXPECT_CALL(*connection_,
637 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
638 .Times(::testing::AnyNumber());
639 stream_frame_.data_buffer = kBadData;
640 stream_frame_.data_length = strlen(kBadData);
641 headers_stream_->OnStreamFrame(stream_frame_);
642}
643
644TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
645 SpdyDataIR data(/* stream_id = */ 2, "ping");
646 SpdySerializedFrame frame(framer_->SerializeFrame(data));
647
648 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
649 "SPDY DATA frame received.", _))
650 .WillOnce(InvokeWithoutArgs(
651 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
652 stream_frame_.data_buffer = frame.data();
653 stream_frame_.data_length = frame.size();
654 headers_stream_->OnStreamFrame(stream_frame_);
655}
656
657TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
658 SpdyRstStreamIR data(/* stream_id = */ 2, ERROR_CODE_PROTOCOL_ERROR);
659 SpdySerializedFrame frame(framer_->SerializeFrame(data));
660 EXPECT_CALL(*connection_,
661 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
662 "SPDY RST_STREAM frame received.", _))
663 .WillOnce(InvokeWithoutArgs(
664 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
665 stream_frame_.data_buffer = frame.data();
666 stream_frame_.data_length = frame.size();
667 headers_stream_->OnStreamFrame(stream_frame_);
668}
669
670TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
671 const uint32_t kTestHeaderTableSize = 1000;
672 SpdySettingsIR data;
673 // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE,
674 // SETTINGS_MAX_HEADER_LIST_SIZE.
675 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, kTestHeaderTableSize);
renjietang4e9714d2020-09-21 15:25:23 -0700676 data.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE, 2000);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500677 SpdySerializedFrame frame(framer_->SerializeFrame(data));
678 stream_frame_.data_buffer = frame.data();
679 stream_frame_.data_length = frame.size();
680 headers_stream_->OnStreamFrame(stream_frame_);
681 EXPECT_EQ(kTestHeaderTableSize, QuicSpdySessionPeer::GetSpdyFramer(&session_)
bnc92fa63a2020-02-04 05:13:43 -0800682 ->header_encoder_table_size());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500683}
684
685TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
686 SpdySettingsIR data;
687 // Does not support SETTINGS_MAX_CONCURRENT_STREAMS,
688 // SETTINGS_INITIAL_WINDOW_SIZE, SETTINGS_ENABLE_PUSH and
689 // SETTINGS_MAX_FRAME_SIZE.
690 data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 100);
691 data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 100);
692 data.AddSetting(SETTINGS_ENABLE_PUSH, 1);
693 data.AddSetting(SETTINGS_MAX_FRAME_SIZE, 1250);
694 SpdySerializedFrame frame(framer_->SerializeFrame(data));
vasilvva163b382020-12-04 11:47:46 -0800695 EXPECT_CALL(*connection_,
696 CloseConnection(
697 QUIC_INVALID_HEADERS_STREAM_DATA,
698 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800699 SETTINGS_MAX_CONCURRENT_STREAMS),
vasilvva163b382020-12-04 11:47:46 -0800700 _));
701 EXPECT_CALL(*connection_,
702 CloseConnection(
703 QUIC_INVALID_HEADERS_STREAM_DATA,
704 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800705 SETTINGS_INITIAL_WINDOW_SIZE),
vasilvva163b382020-12-04 11:47:46 -0800706 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500707 if (session_.perspective() == Perspective::IS_CLIENT) {
vasilvva163b382020-12-04 11:47:46 -0800708 EXPECT_CALL(*connection_,
709 CloseConnection(
710 QUIC_INVALID_HEADERS_STREAM_DATA,
711 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800712 SETTINGS_ENABLE_PUSH),
vasilvva163b382020-12-04 11:47:46 -0800713 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500714 }
vasilvva163b382020-12-04 11:47:46 -0800715 EXPECT_CALL(*connection_,
716 CloseConnection(
717 QUIC_INVALID_HEADERS_STREAM_DATA,
718 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800719 SETTINGS_MAX_FRAME_SIZE),
vasilvva163b382020-12-04 11:47:46 -0800720 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500721 stream_frame_.data_buffer = frame.data();
722 stream_frame_.data_length = frame.size();
723 headers_stream_->OnStreamFrame(stream_frame_);
724}
725
726TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
727 SpdyPingIR data(1);
728 SpdySerializedFrame frame(framer_->SerializeFrame(data));
729 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
730 "SPDY PING frame received.", _))
731 .WillOnce(InvokeWithoutArgs(
732 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
733 stream_frame_.data_buffer = frame.data();
734 stream_frame_.data_length = frame.size();
735 headers_stream_->OnStreamFrame(stream_frame_);
736}
737
738TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
739 SpdyGoAwayIR data(/* last_good_stream_id = */ 1, ERROR_CODE_PROTOCOL_ERROR,
740 "go away");
741 SpdySerializedFrame frame(framer_->SerializeFrame(data));
742 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
743 "SPDY GOAWAY frame received.", _))
744 .WillOnce(InvokeWithoutArgs(
745 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
746 stream_frame_.data_buffer = frame.data();
747 stream_frame_.data_length = frame.size();
748 headers_stream_->OnStreamFrame(stream_frame_);
749}
750
751TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
752 SpdyWindowUpdateIR data(/* stream_id = */ 1, /* delta = */ 1);
753 SpdySerializedFrame frame(framer_->SerializeFrame(data));
754 EXPECT_CALL(*connection_,
755 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
756 "SPDY WINDOW_UPDATE frame received.", _))
757 .WillOnce(InvokeWithoutArgs(
758 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
759 stream_frame_.data_buffer = frame.data();
760 stream_frame_.data_length = frame.size();
761 headers_stream_->OnStreamFrame(stream_frame_);
762}
763
764TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
765 EXPECT_FALSE(QuicStreamPeer::StreamContributesToConnectionFlowControl(
766 headers_stream_));
767}
768
769TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
770 auto hpack_decoder_visitor =
vasilvv0fc587f2019-09-06 13:33:08 -0700771 std::make_unique<StrictMock<MockQuicHpackDebugVisitor>>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500772 {
773 InSequence seq;
774 // Number of indexed representations generated in headers below.
775 for (int i = 1; i < 28; i++) {
776 EXPECT_CALL(*hpack_decoder_visitor,
777 OnUseEntry(QuicTime::Delta::FromMilliseconds(i)))
778 .Times(4);
779 }
780 }
781 QuicSpdySessionPeer::SetHpackDecoderDebugVisitor(
782 &session_, std::move(hpack_decoder_visitor));
783
784 // Create some headers we expect to generate entries in HPACK's
785 // dynamic table, in addition to content-length.
vasilvvc48c8712019-03-11 13:38:16 -0700786 headers_["key0"] = std::string(1 << 1, '.');
787 headers_["key1"] = std::string(1 << 2, '.');
788 headers_["key2"] = std::string(1 << 3, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500789 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
790 stream_id += next_stream_id_) {
791 for (bool fin : {false, true}) {
792 for (SpdyPriority priority = 0; priority < 7; ++priority) {
793 // Replace with "WriteHeadersAndSaveData"
794 SpdySerializedFrame frame;
795 if (perspective() == Perspective::IS_SERVER) {
796 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
797 headers_frame.set_fin(fin);
798 headers_frame.set_has_priority(true);
799 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
800 frame = framer_->SerializeFrame(headers_frame);
fayang476683a2019-07-25 12:42:16 -0700801 EXPECT_CALL(session_, OnStreamHeadersPriority(
802 stream_id, spdy::SpdyStreamPrecedence(0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500803 } else {
804 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
805 headers_frame.set_fin(fin);
806 frame = framer_->SerializeFrame(headers_frame);
807 }
808 EXPECT_CALL(session_,
809 OnStreamHeaderList(stream_id, fin, frame.size(), _))
810 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
811 stream_frame_.data_buffer = frame.data();
812 stream_frame_.data_length = frame.size();
813 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
814 headers_stream_->OnStreamFrame(stream_frame_);
815 stream_frame_.offset += frame.size();
816 CheckHeaders();
817 }
818 }
819 }
820}
821
822TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500823 auto hpack_encoder_visitor =
vasilvv0fc587f2019-09-06 13:33:08 -0700824 std::make_unique<StrictMock<MockQuicHpackDebugVisitor>>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500825 if (perspective() == Perspective::IS_SERVER) {
826 InSequence seq;
827 for (int i = 1; i < 4; i++) {
828 EXPECT_CALL(*hpack_encoder_visitor,
829 OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
830 }
831 } else {
832 InSequence seq;
833 for (int i = 1; i < 28; i++) {
834 EXPECT_CALL(*hpack_encoder_visitor,
835 OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
836 }
837 }
838 QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
839 &session_, std::move(hpack_encoder_visitor));
840
841 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
842 stream_id += next_stream_id_) {
843 for (bool fin : {false, true}) {
844 if (perspective() == Perspective::IS_SERVER) {
845 WriteAndExpectResponseHeaders(stream_id, fin);
846 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
847 } else {
848 for (SpdyPriority priority = 0; priority < 7; ++priority) {
849 // TODO(rch): implement priorities correctly.
850 WriteAndExpectRequestHeaders(stream_id, fin, 0);
851 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
852 }
853 }
854 }
855 }
856}
857
858TEST_P(QuicHeadersStreamTest, AckSentData) {
renjietang7c239172020-02-21 13:50:39 -0800859 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500860 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800861 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800862 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500863 InSequence s;
864 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
865 new MockAckListener());
866 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
867 new MockAckListener());
868 QuicReferenceCountedPointer<MockAckListener> ack_listener3(
869 new MockAckListener());
870
871 // Packet 1.
872 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
873 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
874 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
875
876 // Packet 2.
877 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
878 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
879
880 // Packet 3.
881 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
882
883 // Packet 2 gets retransmitted.
884 EXPECT_CALL(*ack_listener3, OnPacketRetransmitted(7)).Times(1);
885 EXPECT_CALL(*ack_listener2, OnPacketRetransmitted(7)).Times(1);
886 headers_stream_->OnStreamFrameRetransmitted(21, 7, false);
887 headers_stream_->OnStreamFrameRetransmitted(28, 7, false);
888
889 // Packets are acked in order: 2, 3, 1.
890 QuicByteCount newly_acked_length = 0;
891 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
892 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
893 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800894 21, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
895 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500896 EXPECT_EQ(7u, newly_acked_length);
897 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800898 28, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
899 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500900 EXPECT_EQ(7u, newly_acked_length);
901
902 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
903 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800904 35, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
905 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500906 EXPECT_EQ(7u, newly_acked_length);
907
908 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
909 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
910 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800911 0, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
912 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500913 EXPECT_EQ(7u, newly_acked_length);
914 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800915 7, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
916 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500917 EXPECT_EQ(7u, newly_acked_length);
918 // Unsent data is acked.
919 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
920 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800921 14, 10, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
922 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500923 EXPECT_EQ(7u, newly_acked_length);
924}
925
926TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
927 // In this test, a stream frame can contain multiple headers.
renjietang7c239172020-02-21 13:50:39 -0800928 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500929 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800930 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800931 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500932 InSequence s;
933 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
934 new MockAckListener());
935 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
936 new MockAckListener());
937 QuicReferenceCountedPointer<MockAckListener> ack_listener3(
938 new MockAckListener());
939
940 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
941 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
942 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
943 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
944 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
945 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
946
947 // Frame 1 is retransmitted.
948 EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(14));
949 EXPECT_CALL(*ack_listener2, OnPacketRetransmitted(3));
950 headers_stream_->OnStreamFrameRetransmitted(0, 17, false);
951
952 // Frames are acked in order: 2, 3, 1.
953 QuicByteCount newly_acked_length = 0;
954 EXPECT_CALL(*ack_listener2, OnPacketAcked(4, _));
955 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
956 EXPECT_CALL(*ack_listener2, OnPacketAcked(2, _));
957 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800958 17, 13, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
959 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500960 EXPECT_EQ(13u, newly_acked_length);
961
962 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
963 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
964 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800965 30, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
966 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500967 EXPECT_EQ(12u, newly_acked_length);
968
969 EXPECT_CALL(*ack_listener1, OnPacketAcked(14, _));
970 EXPECT_CALL(*ack_listener2, OnPacketAcked(3, _));
971 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800972 0, 17, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
973 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500974 EXPECT_EQ(17u, newly_acked_length);
975}
976
977TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
renjietang7c239172020-02-21 13:50:39 -0800978 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500979 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800980 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800981 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500982 InSequence s;
983 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
984 new MockAckListener());
985 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
986 new MockAckListener());
987 QuicReferenceCountedPointer<MockAckListener> ack_listener3(
988 new MockAckListener());
989
990 // Send [0, 42).
991 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
992 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
993 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
994 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
995 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
996 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
997
998 // Ack [15, 20), [5, 25), [10, 17), [0, 12) and [22, 42).
999 QuicByteCount newly_acked_length = 0;
1000 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
1001 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -08001002 15, 5, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
1003 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001004 EXPECT_EQ(5u, newly_acked_length);
1005
1006 EXPECT_CALL(*ack_listener1, OnPacketAcked(9, _));
1007 EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
1008 EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
1009 EXPECT_CALL(*ack_listener3, OnPacketAcked(4, _));
1010 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -08001011 5, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
1012 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001013 EXPECT_EQ(15u, newly_acked_length);
1014
1015 // Duplicate ack.
1016 EXPECT_FALSE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -08001017 10, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
1018 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001019 EXPECT_EQ(0u, newly_acked_length);
1020
1021 EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
1022 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -08001023 0, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
1024 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001025 EXPECT_EQ(5u, newly_acked_length);
1026
1027 EXPECT_CALL(*ack_listener3, OnPacketAcked(3, _));
1028 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
1029 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
1030 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -08001031 22, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
1032 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001033 EXPECT_EQ(17u, newly_acked_length);
1034}
1035
QUICHE team690a1872019-06-25 16:49:56 -07001036TEST_P(QuicHeadersStreamTest, CloseOnPushPromiseToServer) {
1037 if (perspective() == Perspective::IS_CLIENT) {
1038 return;
1039 }
1040 QuicStreamId promised_id = 1;
1041 SpdyPushPromiseIR push_promise(client_id_1_, promised_id, headers_.Clone());
1042 SpdySerializedFrame frame = framer_->SerializeFrame(push_promise);
1043 stream_frame_.data_buffer = frame.data();
1044 stream_frame_.data_length = frame.size();
1045 EXPECT_CALL(session_, OnStreamHeaderList(_, _, _, _));
1046 // TODO(lassey): Check for HTTP_WRONG_STREAM error code.
1047 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
1048 "PUSH_PROMISE not supported.", _));
1049 headers_stream_->OnStreamFrame(stream_frame_);
1050}
1051
QUICHE teama6ef0a62019-03-07 20:34:33 -05001052} // namespace
1053} // namespace test
1054} // namespace quic