blob: 42fef63c9780f8cf159cf41eafbad39fa4ea35af [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 {
QUICHE teama6ef0a62019-03-07 20:34:33 -050076namespace {
77
78class MockVisitor : public SpdyFramerVisitorInterface {
79 public:
wub713afae2020-04-27 07:48:31 -070080 MOCK_METHOD(void,
81 OnError,
fayang80366682020-07-24 09:19:11 -070082 (http2::Http2DecoderAdapter::SpdyFramerError error,
83 std::string detailed_error),
wub713afae2020-04-27 07:48:31 -070084 (override));
85 MOCK_METHOD(void,
86 OnDataFrameHeader,
87 (SpdyStreamId stream_id, size_t length, bool fin),
88 (override));
89 MOCK_METHOD(void,
90 OnStreamFrameData,
91 (SpdyStreamId stream_id, const char*, size_t len),
92 (override));
93 MOCK_METHOD(void, OnStreamEnd, (SpdyStreamId stream_id), (override));
94 MOCK_METHOD(void,
95 OnStreamPadding,
96 (SpdyStreamId stream_id, size_t len),
97 (override));
98 MOCK_METHOD(SpdyHeadersHandlerInterface*,
99 OnHeaderFrameStart,
100 (SpdyStreamId stream_id),
101 (override));
102 MOCK_METHOD(void, OnHeaderFrameEnd, (SpdyStreamId stream_id), (override));
103 MOCK_METHOD(void,
104 OnRstStream,
105 (SpdyStreamId stream_id, SpdyErrorCode error_code),
106 (override));
107 MOCK_METHOD(void, OnSettings, (), (override));
108 MOCK_METHOD(void, OnSetting, (SpdySettingsId id, uint32_t value), (override));
109 MOCK_METHOD(void, OnSettingsAck, (), (override));
110 MOCK_METHOD(void, OnSettingsEnd, (), (override));
111 MOCK_METHOD(void, OnPing, (SpdyPingId unique_id, bool is_ack), (override));
112 MOCK_METHOD(void,
113 OnGoAway,
114 (SpdyStreamId last_accepted_stream_id, SpdyErrorCode error_code),
115 (override));
116 MOCK_METHOD(void,
117 OnHeaders,
118 (SpdyStreamId stream_id,
119 bool has_priority,
120 int weight,
121 SpdyStreamId parent_stream_id,
122 bool exclusive,
123 bool fin,
124 bool end),
125 (override));
126 MOCK_METHOD(void,
127 OnWindowUpdate,
128 (SpdyStreamId stream_id, int delta_window_size),
129 (override));
130 MOCK_METHOD(void,
131 OnPushPromise,
132 (SpdyStreamId stream_id,
133 SpdyStreamId promised_stream_id,
134 bool end),
135 (override));
136 MOCK_METHOD(void,
137 OnContinuation,
138 (SpdyStreamId stream_id, bool end),
139 (override));
140 MOCK_METHOD(
141 void,
142 OnAltSvc,
143 (SpdyStreamId stream_id,
vasilvve2707e32020-10-08 12:27:46 -0700144 absl::string_view origin,
wub713afae2020-04-27 07:48:31 -0700145 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector),
146 (override));
147 MOCK_METHOD(void,
148 OnPriority,
149 (SpdyStreamId stream_id,
150 SpdyStreamId parent_stream_id,
151 int weight,
152 bool exclusive),
153 (override));
bnca5a30132020-12-17 13:50:27 -0800154 MOCK_METHOD(void,
155 OnPriorityUpdate,
156 (SpdyStreamId prioritized_stream_id,
157 absl::string_view priority_field_value),
158 (override));
wub713afae2020-04-27 07:48:31 -0700159 MOCK_METHOD(bool,
160 OnUnknownFrame,
161 (SpdyStreamId stream_id, uint8_t frame_type),
162 (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163};
164
165struct TestParams {
166 TestParams(const ParsedQuicVersion& version, Perspective perspective)
167 : version(version), perspective(perspective) {
dschinazi552accc2019-06-17 17:07:34 -0700168 QUIC_LOG(INFO) << "TestParams: " << *this;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500169 }
170
171 TestParams(const TestParams& other)
172 : version(other.version), perspective(other.perspective) {}
173
dschinazi552accc2019-06-17 17:07:34 -0700174 friend std::ostream& operator<<(std::ostream& os, const TestParams& tp) {
175 os << "{ version: " << ParsedQuicVersionToString(tp.version)
176 << ", perspective: "
177 << (tp.perspective == Perspective::IS_CLIENT ? "client" : "server")
178 << "}";
179 return os;
180 }
181
QUICHE teama6ef0a62019-03-07 20:34:33 -0500182 ParsedQuicVersion version;
183 Perspective perspective;
184};
185
dschinazi142051a2019-09-18 18:17:29 -0700186// Used by ::testing::PrintToStringParamName().
187std::string PrintToString(const TestParams& tp) {
vasilvva163b382020-12-04 11:47:46 -0800188 return absl::StrCat(
dschinazi142051a2019-09-18 18:17:29 -0700189 ParsedQuicVersionToString(tp.version), "_",
190 (tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
191}
192
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193std::vector<TestParams> GetTestParams() {
194 std::vector<TestParams> params;
195 ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
196 for (size_t i = 0; i < all_supported_versions.size(); ++i) {
renjietanga29a96a2019-10-10 12:47:50 -0700197 if (VersionUsesHttp3(all_supported_versions[i].transport_version)) {
renjietang3c3dfb72019-07-26 11:55:52 -0700198 continue;
199 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500200 for (Perspective p : {Perspective::IS_SERVER, Perspective::IS_CLIENT}) {
201 params.emplace_back(all_supported_versions[i], p);
202 }
203 }
204 return params;
205}
206
207class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
208 public:
209 QuicHeadersStreamTest()
210 : connection_(new StrictMock<MockQuicConnection>(&helper_,
211 &alarm_factory_,
212 perspective(),
213 GetVersion())),
214 session_(connection_),
215 body_("hello world"),
216 stream_frame_(
217 QuicUtils::GetHeadersStreamId(connection_->transport_version()),
218 /*fin=*/false,
219 /*offset=*/0,
220 ""),
221 next_promised_stream_id_(2) {
bnc30d610c2019-07-08 18:39:59 -0700222 QuicSpdySessionPeer::SetMaxInboundHeaderListSize(&session_, 256 * 1024);
wub8eea9192020-08-13 12:05:40 -0700223 EXPECT_CALL(session_, OnCongestionWindowChange(_)).Times(AnyNumber());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224 session_.Initialize();
fayang9c41f8b2020-10-30 13:13:06 -0700225 connection_->SetEncrypter(
226 quic::ENCRYPTION_FORWARD_SECURE,
227 std::make_unique<quic::NullEncrypter>(connection_->perspective()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500228 headers_stream_ = QuicSpdySessionPeer::GetHeadersStream(&session_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229 headers_[":status"] = "200 Ok";
230 headers_["content-length"] = "11";
231 framer_ = std::unique_ptr<SpdyFramer>(
232 new SpdyFramer(SpdyFramer::ENABLE_COMPRESSION));
233 deframer_ = std::unique_ptr<http2::Http2DecoderAdapter>(
234 new http2::Http2DecoderAdapter());
235 deframer_->set_visitor(&visitor_);
renjietangd1d00852019-09-06 10:43:12 -0700236 EXPECT_EQ(transport_version(), session_.transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 EXPECT_TRUE(headers_stream_ != nullptr);
238 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
239 client_id_1_ = GetNthClientInitiatedBidirectionalStreamId(
240 connection_->transport_version(), 0);
241 client_id_2_ = GetNthClientInitiatedBidirectionalStreamId(
242 connection_->transport_version(), 1);
243 client_id_3_ = GetNthClientInitiatedBidirectionalStreamId(
244 connection_->transport_version(), 2);
245 next_stream_id_ =
246 QuicUtils::StreamIdDelta(connection_->transport_version());
247 }
248
249 QuicStreamId GetNthClientInitiatedId(int n) {
250 return GetNthClientInitiatedBidirectionalStreamId(
251 connection_->transport_version(), n);
252 }
253
254 QuicConsumedData SaveIov(size_t write_length) {
255 char* buf = new char[write_length];
QUICHE team173c48f2019-11-19 16:34:44 -0800256 QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500257 headers_stream_->WriteStreamData(headers_stream_->stream_bytes_written(),
258 write_length, &writer);
259 saved_data_.append(buf, write_length);
260 delete[] buf;
261 return QuicConsumedData(write_length, false);
262 }
263
264 void SavePayload(const char* data, size_t len) {
265 saved_payloads_.append(data, len);
266 }
267
268 bool SaveHeaderData(const char* data, int len) {
269 saved_header_data_.append(data, len);
270 return true;
271 }
272
vasilvve2707e32020-10-08 12:27:46 -0700273 void SaveHeaderDataStringPiece(absl::string_view data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274 saved_header_data_.append(data.data(), data.length());
275 }
276
277 void SavePromiseHeaderList(QuicStreamId /* stream_id */,
278 QuicStreamId /* promised_stream_id */,
279 size_t size,
280 const QuicHeaderList& header_list) {
281 SaveToHandler(size, header_list);
282 }
283
284 void SaveHeaderList(QuicStreamId /* stream_id */,
285 bool /* fin */,
286 size_t size,
287 const QuicHeaderList& header_list) {
288 SaveToHandler(size, header_list);
289 }
290
291 void SaveToHandler(size_t size, const QuicHeaderList& header_list) {
QUICHE team6169e492020-11-10 14:05:30 -0800292 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500293 headers_handler_->OnHeaderBlockStart();
294 for (const auto& p : header_list) {
295 headers_handler_->OnHeader(p.first, p.second);
296 }
297 headers_handler_->OnHeaderBlockEnd(size, size);
298 }
299
300 void WriteAndExpectRequestHeaders(QuicStreamId stream_id,
301 bool fin,
302 SpdyPriority priority) {
303 WriteHeadersAndCheckData(stream_id, fin, priority, true /*is_request*/);
304 }
305
306 void WriteAndExpectResponseHeaders(QuicStreamId stream_id, bool fin) {
307 WriteHeadersAndCheckData(stream_id, fin, 0, false /*is_request*/);
308 }
309
310 void WriteHeadersAndCheckData(QuicStreamId stream_id,
311 bool fin,
312 SpdyPriority priority,
313 bool is_request) {
314 // Write the headers and capture the outgoing data
renjietang7c239172020-02-21 13:50:39 -0800315 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800317 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800318 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500319 QuicSpdySessionPeer::WriteHeadersOnHeadersStream(
fayang476683a2019-07-25 12:42:16 -0700320 &session_, stream_id, headers_.Clone(), fin,
321 spdy::SpdyStreamPrecedence(priority), nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500322
323 // Parse the outgoing data and check that it matches was was written.
324 if (is_request) {
325 EXPECT_CALL(visitor_,
326 OnHeaders(stream_id, kHasPriority,
327 Spdy3PriorityToHttp2Weight(priority),
328 /*parent_stream_id=*/0,
329 /*exclusive=*/false, fin, kFrameComplete));
330 } else {
331 EXPECT_CALL(visitor_,
332 OnHeaders(stream_id, !kHasPriority,
wub0b2ae542019-10-24 08:32:06 -0700333 /*weight=*/0,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500334 /*parent_stream_id=*/0,
335 /*exclusive=*/false, fin, kFrameComplete));
336 }
QUICHE team6169e492020-11-10 14:05:30 -0800337 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500338 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
339 .WillOnce(Return(headers_handler_.get()));
340 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id)).Times(1);
341 if (fin) {
342 EXPECT_CALL(visitor_, OnStreamEnd(stream_id));
343 }
344 deframer_->ProcessInput(saved_data_.data(), saved_data_.length());
345 EXPECT_FALSE(deframer_->HasError())
346 << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
347 deframer_->spdy_framer_error());
348
349 CheckHeaders();
350 saved_data_.clear();
351 }
352
353 void CheckHeaders() {
rchb0451852019-09-11 21:17:01 -0700354 ASSERT_TRUE(headers_handler_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500355 EXPECT_EQ(headers_, headers_handler_->decoded_block());
356 headers_handler_.reset();
357 }
358
359 Perspective perspective() const { return GetParam().perspective; }
360
361 QuicTransportVersion transport_version() const {
362 return GetParam().version.transport_version;
363 }
364
365 ParsedQuicVersionVector GetVersion() {
366 ParsedQuicVersionVector versions;
367 versions.push_back(GetParam().version);
368 return versions;
369 }
370
371 void TearDownLocalConnectionState() {
372 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
373 }
374
375 QuicStreamId NextPromisedStreamId() {
376 return next_promised_stream_id_ += next_stream_id_;
377 }
378
QUICHE team897763c2020-04-14 08:15:58 -0700379 static constexpr bool kFrameComplete = true;
380 static constexpr bool kHasPriority = true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500381
382 MockQuicConnectionHelper helper_;
383 MockAlarmFactory alarm_factory_;
384 StrictMock<MockQuicConnection>* connection_;
385 StrictMock<MockQuicSpdySession> session_;
386 QuicHeadersStream* headers_stream_;
387 SpdyHeaderBlock headers_;
QUICHE team6169e492020-11-10 14:05:30 -0800388 std::unique_ptr<RecordingHeadersHandler> headers_handler_;
vasilvvc48c8712019-03-11 13:38:16 -0700389 std::string body_;
390 std::string saved_data_;
391 std::string saved_header_data_;
392 std::string saved_payloads_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500393 std::unique_ptr<SpdyFramer> framer_;
394 std::unique_ptr<http2::Http2DecoderAdapter> deframer_;
395 StrictMock<MockVisitor> visitor_;
396 QuicStreamFrame stream_frame_;
397 QuicStreamId next_promised_stream_id_;
398 QuicStreamId client_id_1_;
399 QuicStreamId client_id_2_;
400 QuicStreamId client_id_3_;
401 QuicStreamId next_stream_id_;
402};
403
404// Run all tests with each version and perspective (client or server).
vasilvvc48c8712019-03-11 13:38:16 -0700405INSTANTIATE_TEST_SUITE_P(Tests,
406 QuicHeadersStreamTest,
dschinazi142051a2019-09-18 18:17:29 -0700407 ::testing::ValuesIn(GetTestParams()),
408 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409
410TEST_P(QuicHeadersStreamTest, StreamId) {
411 EXPECT_EQ(QuicUtils::GetHeadersStreamId(connection_->transport_version()),
412 headers_stream_->id());
413}
414
415TEST_P(QuicHeadersStreamTest, WriteHeaders) {
416 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
417 stream_id += next_stream_id_) {
418 for (bool fin : {false, true}) {
419 if (perspective() == Perspective::IS_SERVER) {
420 WriteAndExpectResponseHeaders(stream_id, fin);
421 } else {
422 for (SpdyPriority priority = 0; priority < 7; ++priority) {
423 // TODO(rch): implement priorities correctly.
424 WriteAndExpectRequestHeaders(stream_id, fin, 0);
425 }
426 }
427 }
428 }
429}
430
431TEST_P(QuicHeadersStreamTest, WritePushPromises) {
432 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
433 stream_id += next_stream_id_) {
434 QuicStreamId promised_stream_id = NextPromisedStreamId();
435 if (perspective() == Perspective::IS_SERVER) {
436 // Write the headers and capture the outgoing data
renjietang7c239172020-02-21 13:50:39 -0800437 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500438 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800439 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800440 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500441 session_.WritePushPromise(stream_id, promised_stream_id,
442 headers_.Clone());
443
444 // Parse the outgoing data and check that it matches was was written.
445 EXPECT_CALL(visitor_,
446 OnPushPromise(stream_id, promised_stream_id, kFrameComplete));
QUICHE team6169e492020-11-10 14:05:30 -0800447 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500448 EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
449 .WillOnce(Return(headers_handler_.get()));
450 EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id)).Times(1);
451 deframer_->ProcessInput(saved_data_.data(), saved_data_.length());
452 EXPECT_FALSE(deframer_->HasError())
453 << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
454 deframer_->spdy_framer_error());
455 CheckHeaders();
456 saved_data_.clear();
457 } else {
458 EXPECT_QUIC_BUG(session_.WritePushPromise(stream_id, promised_stream_id,
459 headers_.Clone()),
460 "Client shouldn't send PUSH_PROMISE");
461 }
462 }
463}
464
465TEST_P(QuicHeadersStreamTest, ProcessRawData) {
466 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
467 stream_id += next_stream_id_) {
468 for (bool fin : {false, true}) {
469 for (SpdyPriority priority = 0; priority < 7; ++priority) {
470 // Replace with "WriteHeadersAndSaveData"
471 SpdySerializedFrame frame;
472 if (perspective() == Perspective::IS_SERVER) {
473 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
474 headers_frame.set_fin(fin);
475 headers_frame.set_has_priority(true);
476 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
477 frame = framer_->SerializeFrame(headers_frame);
fayang476683a2019-07-25 12:42:16 -0700478 EXPECT_CALL(session_, OnStreamHeadersPriority(
479 stream_id, spdy::SpdyStreamPrecedence(0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500480 } else {
481 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
482 headers_frame.set_fin(fin);
483 frame = framer_->SerializeFrame(headers_frame);
484 }
485 EXPECT_CALL(session_,
486 OnStreamHeaderList(stream_id, fin, frame.size(), _))
487 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
488 stream_frame_.data_buffer = frame.data();
489 stream_frame_.data_length = frame.size();
490 headers_stream_->OnStreamFrame(stream_frame_);
491 stream_frame_.offset += frame.size();
492 CheckHeaders();
493 }
494 }
495 }
496}
497
498TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
499 if (perspective() == Perspective::IS_SERVER) {
500 return;
501 }
502 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
503 stream_id += next_stream_id_) {
504 QuicStreamId promised_stream_id = NextPromisedStreamId();
505 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id,
506 headers_.Clone());
507 SpdySerializedFrame frame(framer_->SerializeFrame(push_promise));
dschinazi552accc2019-06-17 17:07:34 -0700508 bool connection_closed = false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500509 if (perspective() == Perspective::IS_SERVER) {
510 EXPECT_CALL(*connection_,
511 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
512 "PUSH_PROMISE not supported.", _))
513 .WillRepeatedly(InvokeWithoutArgs(
514 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
515 } else {
dschinazi552accc2019-06-17 17:07:34 -0700516 ON_CALL(*connection_, CloseConnection(_, _, _))
517 .WillByDefault(testing::Assign(&connection_closed, true));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518 EXPECT_CALL(session_, OnPromiseHeaderList(stream_id, promised_stream_id,
519 frame.size(), _))
520 .WillOnce(
521 Invoke(this, &QuicHeadersStreamTest::SavePromiseHeaderList));
522 }
523 stream_frame_.data_buffer = frame.data();
524 stream_frame_.data_length = frame.size();
525 headers_stream_->OnStreamFrame(stream_frame_);
526 if (perspective() == Perspective::IS_CLIENT) {
527 stream_frame_.offset += frame.size();
dschinazi552accc2019-06-17 17:07:34 -0700528 // CheckHeaders crashes if the connection is closed so this ensures we
529 // fail the test instead of crashing.
530 ASSERT_FALSE(connection_closed);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500531 CheckHeaders();
532 }
533 }
534}
535
536TEST_P(QuicHeadersStreamTest, ProcessPriorityFrame) {
537 QuicStreamId parent_stream_id = 0;
538 for (SpdyPriority priority = 0; priority < 7; ++priority) {
539 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
540 stream_id += next_stream_id_) {
541 int weight = Spdy3PriorityToHttp2Weight(priority);
542 SpdyPriorityIR priority_frame(stream_id, parent_stream_id, weight, true);
543 SpdySerializedFrame frame(framer_->SerializeFrame(priority_frame));
544 parent_stream_id = stream_id;
fayang8265a2a2019-10-16 11:23:51 -0700545 if (perspective() == Perspective::IS_CLIENT) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500546 EXPECT_CALL(*connection_,
547 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
548 "Server must not send PRIORITY frames.", _))
549 .WillRepeatedly(InvokeWithoutArgs(
550 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
551 } else {
fayang476683a2019-07-25 12:42:16 -0700552 EXPECT_CALL(
553 session_,
554 OnPriorityFrame(stream_id, spdy::SpdyStreamPrecedence(priority)))
555 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500556 }
557 stream_frame_.data_buffer = frame.data();
558 stream_frame_.data_length = frame.size();
559 headers_stream_->OnStreamFrame(stream_frame_);
560 stream_frame_.offset += frame.size();
561 }
562 }
563}
564
565TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
bnc0142a092021-04-27 12:13:52 -0700566 if (perspective() != Perspective::IS_CLIENT) {
567 return;
568 }
569
QUICHE teama6ef0a62019-03-07 20:34:33 -0500570 session_.OnConfigNegotiated();
571 SpdySettingsIR data;
572 // Respect supported settings frames SETTINGS_ENABLE_PUSH.
573 data.AddSetting(SETTINGS_ENABLE_PUSH, 0);
574 SpdySerializedFrame frame(framer_->SerializeFrame(data));
575 stream_frame_.data_buffer = frame.data();
576 stream_frame_.data_length = frame.size();
bnc0142a092021-04-27 12:13:52 -0700577 EXPECT_CALL(
578 *connection_,
579 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
580 "Unsupported field of HTTP/2 SETTINGS frame: 2", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500581 headers_stream_->OnStreamFrame(stream_frame_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500582}
583
584TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500585 // We want to create a frame that is more than the SPDY Framer's max control
586 // frame size, which is 16K, but less than the HPACK decoders max decode
587 // buffer size, which is 32K.
vasilvvc48c8712019-03-11 13:38:16 -0700588 headers_["key0"] = std::string(1 << 13, '.');
589 headers_["key1"] = std::string(1 << 13, '.');
590 headers_["key2"] = std::string(1 << 13, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500591 for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
592 stream_id += next_stream_id_) {
593 for (bool fin : {false, true}) {
594 for (SpdyPriority priority = 0; priority < 7; ++priority) {
595 // Replace with "WriteHeadersAndSaveData"
596 SpdySerializedFrame frame;
597 if (perspective() == Perspective::IS_SERVER) {
598 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
599 headers_frame.set_fin(fin);
600 headers_frame.set_has_priority(true);
601 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
602 frame = framer_->SerializeFrame(headers_frame);
fayang476683a2019-07-25 12:42:16 -0700603 EXPECT_CALL(session_, OnStreamHeadersPriority(
604 stream_id, spdy::SpdyStreamPrecedence(0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500605 } else {
606 SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
607 headers_frame.set_fin(fin);
608 frame = framer_->SerializeFrame(headers_frame);
609 }
610 EXPECT_CALL(session_,
611 OnStreamHeaderList(stream_id, fin, frame.size(), _))
612 .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
613 stream_frame_.data_buffer = frame.data();
614 stream_frame_.data_length = frame.size();
615 headers_stream_->OnStreamFrame(stream_frame_);
616 stream_frame_.offset += frame.size();
617 CheckHeaders();
618 }
619 }
620 }
621}
622
623TEST_P(QuicHeadersStreamTest, ProcessBadData) {
624 const char kBadData[] = "blah blah blah";
625 EXPECT_CALL(*connection_,
626 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
627 .Times(::testing::AnyNumber());
628 stream_frame_.data_buffer = kBadData;
629 stream_frame_.data_length = strlen(kBadData);
630 headers_stream_->OnStreamFrame(stream_frame_);
631}
632
633TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
634 SpdyDataIR data(/* stream_id = */ 2, "ping");
635 SpdySerializedFrame frame(framer_->SerializeFrame(data));
636
637 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
638 "SPDY DATA frame received.", _))
639 .WillOnce(InvokeWithoutArgs(
640 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
641 stream_frame_.data_buffer = frame.data();
642 stream_frame_.data_length = frame.size();
643 headers_stream_->OnStreamFrame(stream_frame_);
644}
645
646TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
647 SpdyRstStreamIR data(/* stream_id = */ 2, ERROR_CODE_PROTOCOL_ERROR);
648 SpdySerializedFrame frame(framer_->SerializeFrame(data));
649 EXPECT_CALL(*connection_,
650 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
651 "SPDY RST_STREAM frame received.", _))
652 .WillOnce(InvokeWithoutArgs(
653 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
654 stream_frame_.data_buffer = frame.data();
655 stream_frame_.data_length = frame.size();
656 headers_stream_->OnStreamFrame(stream_frame_);
657}
658
659TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
660 const uint32_t kTestHeaderTableSize = 1000;
661 SpdySettingsIR data;
662 // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE,
663 // SETTINGS_MAX_HEADER_LIST_SIZE.
664 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, kTestHeaderTableSize);
renjietang4e9714d2020-09-21 15:25:23 -0700665 data.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE, 2000);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500666 SpdySerializedFrame frame(framer_->SerializeFrame(data));
667 stream_frame_.data_buffer = frame.data();
668 stream_frame_.data_length = frame.size();
669 headers_stream_->OnStreamFrame(stream_frame_);
670 EXPECT_EQ(kTestHeaderTableSize, QuicSpdySessionPeer::GetSpdyFramer(&session_)
bnc92fa63a2020-02-04 05:13:43 -0800671 ->header_encoder_table_size());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500672}
673
674TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
675 SpdySettingsIR data;
676 // Does not support SETTINGS_MAX_CONCURRENT_STREAMS,
677 // SETTINGS_INITIAL_WINDOW_SIZE, SETTINGS_ENABLE_PUSH and
678 // SETTINGS_MAX_FRAME_SIZE.
679 data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 100);
680 data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 100);
681 data.AddSetting(SETTINGS_ENABLE_PUSH, 1);
682 data.AddSetting(SETTINGS_MAX_FRAME_SIZE, 1250);
683 SpdySerializedFrame frame(framer_->SerializeFrame(data));
vasilvva163b382020-12-04 11:47:46 -0800684 EXPECT_CALL(*connection_,
685 CloseConnection(
686 QUIC_INVALID_HEADERS_STREAM_DATA,
687 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800688 SETTINGS_MAX_CONCURRENT_STREAMS),
vasilvva163b382020-12-04 11:47:46 -0800689 _));
690 EXPECT_CALL(*connection_,
691 CloseConnection(
692 QUIC_INVALID_HEADERS_STREAM_DATA,
693 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800694 SETTINGS_INITIAL_WINDOW_SIZE),
vasilvva163b382020-12-04 11:47:46 -0800695 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500696 if (session_.perspective() == Perspective::IS_CLIENT) {
vasilvva163b382020-12-04 11:47:46 -0800697 EXPECT_CALL(*connection_,
698 CloseConnection(
699 QUIC_INVALID_HEADERS_STREAM_DATA,
700 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800701 SETTINGS_ENABLE_PUSH),
vasilvva163b382020-12-04 11:47:46 -0800702 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500703 }
vasilvva163b382020-12-04 11:47:46 -0800704 EXPECT_CALL(*connection_,
705 CloseConnection(
706 QUIC_INVALID_HEADERS_STREAM_DATA,
707 absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
dmcardleba2fb7e2019-12-13 07:44:34 -0800708 SETTINGS_MAX_FRAME_SIZE),
vasilvva163b382020-12-04 11:47:46 -0800709 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500710 stream_frame_.data_buffer = frame.data();
711 stream_frame_.data_length = frame.size();
712 headers_stream_->OnStreamFrame(stream_frame_);
713}
714
715TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
716 SpdyPingIR data(1);
717 SpdySerializedFrame frame(framer_->SerializeFrame(data));
718 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
719 "SPDY PING frame received.", _))
720 .WillOnce(InvokeWithoutArgs(
721 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
722 stream_frame_.data_buffer = frame.data();
723 stream_frame_.data_length = frame.size();
724 headers_stream_->OnStreamFrame(stream_frame_);
725}
726
727TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
728 SpdyGoAwayIR data(/* last_good_stream_id = */ 1, ERROR_CODE_PROTOCOL_ERROR,
729 "go away");
730 SpdySerializedFrame frame(framer_->SerializeFrame(data));
731 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
732 "SPDY GOAWAY frame received.", _))
733 .WillOnce(InvokeWithoutArgs(
734 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
735 stream_frame_.data_buffer = frame.data();
736 stream_frame_.data_length = frame.size();
737 headers_stream_->OnStreamFrame(stream_frame_);
738}
739
740TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
741 SpdyWindowUpdateIR data(/* stream_id = */ 1, /* delta = */ 1);
742 SpdySerializedFrame frame(framer_->SerializeFrame(data));
743 EXPECT_CALL(*connection_,
744 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
745 "SPDY WINDOW_UPDATE frame received.", _))
746 .WillOnce(InvokeWithoutArgs(
747 this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
748 stream_frame_.data_buffer = frame.data();
749 stream_frame_.data_length = frame.size();
750 headers_stream_->OnStreamFrame(stream_frame_);
751}
752
753TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
754 EXPECT_FALSE(QuicStreamPeer::StreamContributesToConnectionFlowControl(
755 headers_stream_));
756}
757
QUICHE teama6ef0a62019-03-07 20:34:33 -0500758TEST_P(QuicHeadersStreamTest, AckSentData) {
renjietang7c239172020-02-21 13:50:39 -0800759 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500760 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800761 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800762 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500763 InSequence s;
764 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
765 new MockAckListener());
766 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
767 new MockAckListener());
768 QuicReferenceCountedPointer<MockAckListener> ack_listener3(
769 new MockAckListener());
770
771 // Packet 1.
772 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
773 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
774 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
775
776 // Packet 2.
777 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
778 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
779
780 // Packet 3.
781 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
782
783 // Packet 2 gets retransmitted.
784 EXPECT_CALL(*ack_listener3, OnPacketRetransmitted(7)).Times(1);
785 EXPECT_CALL(*ack_listener2, OnPacketRetransmitted(7)).Times(1);
786 headers_stream_->OnStreamFrameRetransmitted(21, 7, false);
787 headers_stream_->OnStreamFrameRetransmitted(28, 7, false);
788
789 // Packets are acked in order: 2, 3, 1.
790 QuicByteCount newly_acked_length = 0;
791 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
792 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
793 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800794 21, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
795 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500796 EXPECT_EQ(7u, newly_acked_length);
797 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800798 28, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
799 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500800 EXPECT_EQ(7u, newly_acked_length);
801
802 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
803 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800804 35, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
805 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500806 EXPECT_EQ(7u, newly_acked_length);
807
808 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
809 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
810 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800811 0, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
812 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500813 EXPECT_EQ(7u, newly_acked_length);
814 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800815 7, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
816 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500817 EXPECT_EQ(7u, newly_acked_length);
818 // Unsent data is acked.
819 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
820 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800821 14, 10, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
822 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500823 EXPECT_EQ(7u, newly_acked_length);
824}
825
826TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
827 // In this test, a stream frame can contain multiple headers.
renjietang7c239172020-02-21 13:50:39 -0800828 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500829 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800830 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800831 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500832 InSequence s;
833 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
834 new MockAckListener());
835 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
836 new MockAckListener());
837 QuicReferenceCountedPointer<MockAckListener> ack_listener3(
838 new MockAckListener());
839
840 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
841 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
842 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
843 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
844 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
845 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
846
847 // Frame 1 is retransmitted.
848 EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(14));
849 EXPECT_CALL(*ack_listener2, OnPacketRetransmitted(3));
850 headers_stream_->OnStreamFrameRetransmitted(0, 17, false);
851
852 // Frames are acked in order: 2, 3, 1.
853 QuicByteCount newly_acked_length = 0;
854 EXPECT_CALL(*ack_listener2, OnPacketAcked(4, _));
855 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
856 EXPECT_CALL(*ack_listener2, OnPacketAcked(2, _));
857 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800858 17, 13, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
859 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500860 EXPECT_EQ(13u, newly_acked_length);
861
862 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
863 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
864 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800865 30, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
866 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500867 EXPECT_EQ(12u, newly_acked_length);
868
869 EXPECT_CALL(*ack_listener1, OnPacketAcked(14, _));
870 EXPECT_CALL(*ack_listener2, OnPacketAcked(3, _));
871 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800872 0, 17, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
873 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500874 EXPECT_EQ(17u, newly_acked_length);
875}
876
877TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
renjietang7c239172020-02-21 13:50:39 -0800878 EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500879 connection_->transport_version()),
renjietang41a1b412020-02-27 15:05:14 -0800880 _, _, NO_FIN, _, _))
renjietang7c239172020-02-21 13:50:39 -0800881 .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500882 InSequence s;
883 QuicReferenceCountedPointer<MockAckListener> ack_listener1(
884 new MockAckListener());
885 QuicReferenceCountedPointer<MockAckListener> ack_listener2(
886 new MockAckListener());
887 QuicReferenceCountedPointer<MockAckListener> ack_listener3(
888 new MockAckListener());
889
890 // Send [0, 42).
891 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
892 headers_stream_->WriteOrBufferData("Header5", false, ack_listener1);
893 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
894 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
895 headers_stream_->WriteOrBufferData("Header7", false, ack_listener2);
896 headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
897
898 // Ack [15, 20), [5, 25), [10, 17), [0, 12) and [22, 42).
899 QuicByteCount newly_acked_length = 0;
900 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
901 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800902 15, 5, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
903 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500904 EXPECT_EQ(5u, newly_acked_length);
905
906 EXPECT_CALL(*ack_listener1, OnPacketAcked(9, _));
907 EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
908 EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
909 EXPECT_CALL(*ack_listener3, OnPacketAcked(4, _));
910 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800911 5, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
912 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500913 EXPECT_EQ(15u, newly_acked_length);
914
915 // Duplicate ack.
916 EXPECT_FALSE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800917 10, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
918 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500919 EXPECT_EQ(0u, newly_acked_length);
920
921 EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
922 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800923 0, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
924 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500925 EXPECT_EQ(5u, newly_acked_length);
926
927 EXPECT_CALL(*ack_listener3, OnPacketAcked(3, _));
928 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
929 EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
930 EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800931 22, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
932 &newly_acked_length));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500933 EXPECT_EQ(17u, newly_acked_length);
934}
935
QUICHE team690a1872019-06-25 16:49:56 -0700936TEST_P(QuicHeadersStreamTest, CloseOnPushPromiseToServer) {
937 if (perspective() == Perspective::IS_CLIENT) {
938 return;
939 }
940 QuicStreamId promised_id = 1;
941 SpdyPushPromiseIR push_promise(client_id_1_, promised_id, headers_.Clone());
942 SpdySerializedFrame frame = framer_->SerializeFrame(push_promise);
943 stream_frame_.data_buffer = frame.data();
944 stream_frame_.data_length = frame.size();
945 EXPECT_CALL(session_, OnStreamHeaderList(_, _, _, _));
946 // TODO(lassey): Check for HTTP_WRONG_STREAM error code.
947 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
948 "PUSH_PROMISE not supported.", _));
949 headers_stream_->OnStreamFrame(stream_frame_);
950}
951
QUICHE teama6ef0a62019-03-07 20:34:33 -0500952} // namespace
953} // namespace test
954} // namespace quic