blob: 880d3aae08981380d1a892c67fc088b0fa9ad75c [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 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 "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
6
7#include <list>
8#include <memory>
9#include <utility>
10
bnc46942722019-10-29 11:56:21 -070011#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
13#include "net/third_party/quiche/src/quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
18#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
renjietangbb2e22a2019-09-12 15:46:39 -070019#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050020#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
21#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
22#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
23#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
24#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
25#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
26#include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h"
bnc4e9283d2019-12-17 07:08:57 -080027#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
QUICHE team5015e2e2019-12-11 09:38:06 -080028#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050029
30using testing::_;
31using testing::AnyNumber;
32using testing::InSequence;
33using testing::Invoke;
QUICHE teama6ef0a62019-03-07 20:34:33 -050034using testing::StrictMock;
QUICHE teama6ef0a62019-03-07 20:34:33 -050035
36namespace quic {
37namespace test {
38
39const size_t kFakeFrameLen = 60;
40const size_t kErrorLength = strlen(QuicSimpleServerStream::kErrorResponseBody);
41const size_t kDataFrameHeaderLength = 2;
42
43class TestStream : public QuicSimpleServerStream {
44 public:
45 TestStream(QuicStreamId stream_id,
46 QuicSpdySession* session,
47 StreamType type,
48 QuicSimpleServerBackend* quic_simple_server_backend)
49 : QuicSimpleServerStream(stream_id,
50 session,
51 type,
52 quic_simple_server_backend) {}
53
54 ~TestStream() override = default;
55
56 MOCK_METHOD1(WriteHeadersMock, void(bool fin));
57
dschinazi17d42422019-06-18 16:35:07 -070058 size_t WriteHeaders(spdy::SpdyHeaderBlock /*header_block*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -050059 bool fin,
60 QuicReferenceCountedPointer<QuicAckListenerInterface>
dschinazi17d42422019-06-18 16:35:07 -070061 /*ack_listener*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 WriteHeadersMock(fin);
63 return 0;
64 }
65
66 // Expose protected QuicSimpleServerStream methods.
67 void DoSendResponse() { SendResponse(); }
68 void DoSendErrorResponse() { SendErrorResponse(); }
69
70 spdy::SpdyHeaderBlock* mutable_headers() { return &request_headers_; }
vasilvvc48c8712019-03-11 13:38:16 -070071 void set_body(std::string body) { body_ = std::move(body); }
72 const std::string& body() const { return body_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 int content_length() const { return content_length_; }
74
QUICHE team5015e2e2019-12-11 09:38:06 -080075 quiche::QuicheStringPiece GetHeader(quiche::QuicheStringPiece key) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 auto it = request_headers_.find(key);
77 DCHECK(it != request_headers_.end());
78 return it->second;
79 }
80};
81
82namespace {
83
84class MockQuicSimpleServerSession : public QuicSimpleServerSession {
85 public:
86 const size_t kMaxStreamsForTest = 100;
87
88 MockQuicSimpleServerSession(
89 QuicConnection* connection,
90 MockQuicSessionVisitor* owner,
91 MockQuicCryptoServerStreamHelper* helper,
92 QuicCryptoServerConfig* crypto_config,
93 QuicCompressedCertsCache* compressed_certs_cache,
94 QuicSimpleServerBackend* quic_simple_server_backend)
95 : QuicSimpleServerSession(DefaultQuicConfig(),
96 CurrentSupportedVersions(),
97 connection,
98 owner,
99 helper,
100 crypto_config,
101 compressed_certs_cache,
102 quic_simple_server_backend) {
fkastenholz305e1732019-06-18 05:01:22 -0700103 if (VersionHasIetfQuicFrames(connection->transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700104 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
105 this, kMaxStreamsForTest);
106 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
107 this, kMaxStreamsForTest);
108 } else {
109 QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
110 QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
111 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500112 ON_CALL(*this, WritevData(_, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800113 .WillByDefault(Invoke(this, &MockQuicSimpleServerSession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 }
115
116 MockQuicSimpleServerSession(const MockQuicSimpleServerSession&) = delete;
117 MockQuicSimpleServerSession& operator=(const MockQuicSimpleServerSession&) =
118 delete;
119 ~MockQuicSimpleServerSession() override = default;
120
fkastenholz5d880a92019-06-21 09:01:56 -0700121 MOCK_METHOD2(OnConnectionClosed,
122 void(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 ConnectionCloseSource source));
124 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
125 MOCK_METHOD5(WritevData,
renjietang7c239172020-02-21 13:50:39 -0800126 QuicConsumedData(QuicStreamId id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500127 size_t write_length,
128 QuicStreamOffset offset,
renjietang7c239172020-02-21 13:50:39 -0800129 StreamSendingState state,
130 bool is_retransmission));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 MOCK_METHOD4(OnStreamHeaderList,
132 void(QuicStreamId stream_id,
133 bool fin,
134 size_t frame_len,
135 const QuicHeaderList& header_list));
136 MOCK_METHOD2(OnStreamHeadersPriority,
fayang476683a2019-07-25 12:42:16 -0700137 void(QuicStreamId stream_id,
138 const spdy::SpdyStreamPrecedence& precedence));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 MOCK_METHOD3(SendRstStream,
140 void(QuicStreamId stream_id,
141 QuicRstStreamErrorCode error,
142 QuicStreamOffset bytes_written));
143 MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta));
144 // Matchers cannot be used on non-copyable types like SpdyHeaderBlock.
145 void PromisePushResources(
vasilvvc48c8712019-03-11 13:38:16 -0700146 const std::string& request_url,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 const std::list<QuicBackendResponse::ServerPushInfo>& resources,
148 QuicStreamId original_stream_id,
fayang9a423762019-07-31 08:12:58 -0700149 const spdy::SpdyStreamPrecedence& original_precedence,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150 const spdy::SpdyHeaderBlock& original_request_headers) override {
151 original_request_headers_ = original_request_headers.Clone();
152 PromisePushResourcesMock(request_url, resources, original_stream_id,
fayang9a423762019-07-31 08:12:58 -0700153 original_precedence, original_request_headers);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154 }
fayang9a423762019-07-31 08:12:58 -0700155 MOCK_METHOD5(PromisePushResourcesMock,
vasilvvc48c8712019-03-11 13:38:16 -0700156 void(const std::string&,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 const std::list<QuicBackendResponse::ServerPushInfo>&,
158 QuicStreamId,
fayang9a423762019-07-31 08:12:58 -0700159 const spdy::SpdyStreamPrecedence&,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 const spdy::SpdyHeaderBlock&));
161
162 using QuicSession::ActivateStream;
163
164 MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame));
165
renjietang7c239172020-02-21 13:50:39 -0800166 QuicConsumedData ConsumeData(QuicStreamId id,
167 size_t write_length,
168 QuicStreamOffset offset,
169 StreamSendingState state,
170 bool /*is_retransmission*/) {
171 if (write_length > 0) {
172 auto buf = std::make_unique<char[]>(write_length);
173 QuicStream* stream = GetOrCreateStream(id);
174 DCHECK(stream);
175 QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
176 stream->WriteStreamData(offset, write_length, &writer);
177 } else {
178 DCHECK(state != NO_FIN);
179 }
180 return QuicConsumedData(write_length, state != NO_FIN);
181 }
182
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183 spdy::SpdyHeaderBlock original_request_headers_;
184};
185
186class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
187 public:
188 QuicSimpleServerStreamTest()
189 : connection_(
190 new StrictMock<MockQuicConnection>(&helper_,
191 &alarm_factory_,
192 Perspective::IS_SERVER,
193 SupportedVersions(GetParam()))),
194 crypto_config_(new QuicCryptoServerConfig(
195 QuicCryptoServerConfig::TESTING,
196 QuicRandom::GetInstance(),
197 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -0700198 KeyExchangeSource::Default())),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 compressed_certs_cache_(
200 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
201 session_(connection_,
202 &session_owner_,
203 &session_helper_,
204 crypto_config_.get(),
205 &compressed_certs_cache_,
206 &memory_cache_backend_),
207 quic_response_(new QuicBackendResponse),
208 body_("hello world") {
209 connection_->set_visitor(&session_);
210 header_list_.OnHeaderBlockStart();
211 header_list_.OnHeader(":authority", "www.google.com");
212 header_list_.OnHeader(":path", "/");
213 header_list_.OnHeader(":method", "POST");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500214 header_list_.OnHeader("content-length", "11");
215
216 header_list_.OnHeaderBlockEnd(128, 128);
217
218 // New streams rely on having the peer's flow control receive window
219 // negotiated in the config.
220 session_.config()->SetInitialStreamFlowControlWindowToSend(
221 kInitialStreamFlowControlWindowForTest);
222 session_.config()->SetInitialSessionFlowControlWindowToSend(
223 kInitialSessionFlowControlWindowForTest);
renjietang8513ffe2019-08-12 10:08:57 -0700224 session_.Initialize();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225 stream_ = new StrictMock<TestStream>(
226 GetNthClientInitiatedBidirectionalStreamId(
227 connection_->transport_version(), 0),
228 &session_, BIDIRECTIONAL, &memory_cache_backend_);
229 // Register stream_ in dynamic_stream_map_ and pass ownership to session_.
230 session_.ActivateStream(QuicWrapUnique(stream_));
renjietangbb2e22a2019-09-12 15:46:39 -0700231 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
232 session_.config(), kMinimumFlowControlSendWindow);
dschinazi18cdf132019-10-09 16:08:18 -0700233 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
234 session_.config(), kMinimumFlowControlSendWindow);
235 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
236 session_.config(), kMinimumFlowControlSendWindow);
237 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
238 session_.config(), kMinimumFlowControlSendWindow);
renjietange6d94672020-01-07 10:30:10 -0800239 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 10);
renjietangbb2e22a2019-09-12 15:46:39 -0700240 session_.OnConfigNegotiated();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
242 }
243
vasilvvc48c8712019-03-11 13:38:16 -0700244 const std::string& StreamBody() { return stream_->body(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245
vasilvvc48c8712019-03-11 13:38:16 -0700246 std::string StreamHeadersValue(const std::string& key) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247 return (*stream_->mutable_headers())[key].as_string();
248 }
249
renjietanga29a96a2019-10-10 12:47:50 -0700250 bool UsesHttp3() const {
251 return VersionUsesHttp3(connection_->transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 }
253
254 spdy::SpdyHeaderBlock response_headers_;
255 MockQuicConnectionHelper helper_;
256 MockAlarmFactory alarm_factory_;
257 StrictMock<MockQuicConnection>* connection_;
258 StrictMock<MockQuicSessionVisitor> session_owner_;
259 StrictMock<MockQuicCryptoServerStreamHelper> session_helper_;
260 std::unique_ptr<QuicCryptoServerConfig> crypto_config_;
261 QuicCompressedCertsCache compressed_certs_cache_;
262 QuicMemoryCacheBackend memory_cache_backend_;
263 StrictMock<MockQuicSimpleServerSession> session_;
264 StrictMock<TestStream>* stream_; // Owned by session_.
265 std::unique_ptr<QuicBackendResponse> quic_response_;
vasilvvc48c8712019-03-11 13:38:16 -0700266 std::string body_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 QuicHeaderList header_list_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268};
269
270INSTANTIATE_TEST_SUITE_P(Tests,
271 QuicSimpleServerStreamTest,
dschinazi88bd5b02019-10-10 00:52:20 -0700272 ::testing::ValuesIn(AllSupportedVersions()),
273 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274
275TEST_P(QuicSimpleServerStreamTest, TestFraming) {
276 EXPECT_CALL(session_, WritevData(_, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800277 .WillRepeatedly(
278 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500279 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
280 std::unique_ptr<char[]> buffer;
281 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700282 HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700283 std::string header = std::string(buffer.get(), header_length);
renjietanga29a96a2019-10-10 12:47:50 -0700284 std::string data = UsesHttp3() ? header + body_ : body_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285 stream_->OnStreamFrame(
286 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
287 EXPECT_EQ("11", StreamHeadersValue("content-length"));
288 EXPECT_EQ("/", StreamHeadersValue(":path"));
289 EXPECT_EQ("POST", StreamHeadersValue(":method"));
290 EXPECT_EQ(body_, StreamBody());
291}
292
293TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
294 EXPECT_CALL(session_, WritevData(_, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800295 .WillRepeatedly(
296 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500297
298 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
299 std::unique_ptr<char[]> buffer;
300 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700301 HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700302 std::string header = std::string(buffer.get(), header_length);
renjietanga29a96a2019-10-10 12:47:50 -0700303 std::string data = UsesHttp3() ? header + body_ : body_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 stream_->OnStreamFrame(
305 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
306 EXPECT_EQ("11", StreamHeadersValue("content-length"));
307 EXPECT_EQ("/", StreamHeadersValue(":path"));
308 EXPECT_EQ("POST", StreamHeadersValue(":method"));
309 EXPECT_EQ(body_, StreamBody());
310}
311
312TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) {
313 EXPECT_CALL(session_, WritevData(_, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800314 .WillRepeatedly(
315 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316
317 EXPECT_FALSE(stream_->fin_received());
318 EXPECT_FALSE(stream_->rst_received());
319
320 stream_->set_fin_sent(true);
321 stream_->CloseWriteSide();
322
323 EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(1);
324 stream_->StopReading();
325}
326
327TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
328 InSequence seq;
vasilvvc48c8712019-03-11 13:38:16 -0700329 std::string large_body = "hello world!!!!!!";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500330
331 // We'll automatically write out an error (headers + body)
332 EXPECT_CALL(*stream_, WriteHeadersMock(false));
renjietanga29a96a2019-10-10 12:47:50 -0700333 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800334 EXPECT_CALL(session_, WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500335 }
renjietang7c239172020-02-21 13:50:39 -0800336 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500337
338 EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
339
340 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
341 std::unique_ptr<char[]> buffer;
342 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700343 HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700344 std::string header = std::string(buffer.get(), header_length);
renjietanga29a96a2019-10-10 12:47:50 -0700345 std::string data = UsesHttp3() ? header + body_ : body_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500346
347 stream_->OnStreamFrame(
348 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
349 // Content length is still 11. This will register as an error and we won't
350 // accept the bytes.
351 header_length =
bnc46942722019-10-29 11:56:21 -0700352 HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
vasilvvc48c8712019-03-11 13:38:16 -0700353 header = std::string(buffer.get(), header_length);
renjietanga29a96a2019-10-10 12:47:50 -0700354 std::string data2 = UsesHttp3() ? header + large_body : large_body;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500355 stream_->OnStreamFrame(
356 QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2));
357 EXPECT_EQ("11", StreamHeadersValue("content-length"));
358 EXPECT_EQ("/", StreamHeadersValue(":path"));
359 EXPECT_EQ("POST", StreamHeadersValue(":method"));
360}
361
362TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
363 // Send an illegal response with response status not supported by HTTP/2.
364 spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
365 (*request_headers)[":path"] = "/bar";
366 (*request_headers)[":authority"] = "www.google.com";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500367 (*request_headers)[":method"] = "GET";
368
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369 // HTTP/2 only supports integer responsecode, so "200 OK" is illegal.
370 response_headers_[":status"] = "200 OK";
371 response_headers_["content-length"] = "5";
vasilvvc48c8712019-03-11 13:38:16 -0700372 std::string body = "Yummm";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500373 std::unique_ptr<char[]> buffer;
374 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700375 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500376
377 memory_cache_backend_.AddResponse("www.google.com", "/bar",
378 std::move(response_headers_), body);
379
380 stream_->set_fin_received(true);
381
382 InSequence s;
383 EXPECT_CALL(*stream_, WriteHeadersMock(false));
renjietanga29a96a2019-10-10 12:47:50 -0700384 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800385 EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500386 }
renjietang7c239172020-02-21 13:50:39 -0800387 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500388
389 stream_->DoSendResponse();
390 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
391 EXPECT_TRUE(stream_->write_side_closed());
392}
393
394TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
395 // Send an illegal response with response status not supported by HTTP/2.
396 spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
397 (*request_headers)[":path"] = "/bar";
398 (*request_headers)[":authority"] = "www.google.com";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500399 (*request_headers)[":method"] = "GET";
400
QUICHE teama6ef0a62019-03-07 20:34:33 -0500401 // HTTP/2 only supports 3-digit-integer, so "+200" is illegal.
402 response_headers_[":status"] = "+200";
403 response_headers_["content-length"] = "5";
vasilvvc48c8712019-03-11 13:38:16 -0700404 std::string body = "Yummm";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500405
406 std::unique_ptr<char[]> buffer;
407 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700408 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409
410 memory_cache_backend_.AddResponse("www.google.com", "/bar",
411 std::move(response_headers_), body);
412
413 stream_->set_fin_received(true);
414
415 InSequence s;
416 EXPECT_CALL(*stream_, WriteHeadersMock(false));
renjietanga29a96a2019-10-10 12:47:50 -0700417 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800418 EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 }
renjietang7c239172020-02-21 13:50:39 -0800420 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500421
422 stream_->DoSendResponse();
423 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
424 EXPECT_TRUE(stream_->write_side_closed());
425}
426
427TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
428 // Create a new promised stream with even id().
429 auto promised_stream = new StrictMock<TestStream>(
430 GetNthServerInitiatedUnidirectionalStreamId(
renjietang87cd7de2019-08-16 08:35:10 -0700431 connection_->transport_version(), 3),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500432 &session_, WRITE_UNIDIRECTIONAL, &memory_cache_backend_);
433 session_.ActivateStream(QuicWrapUnique(promised_stream));
434
435 // Send a push response with response status 404, which will be regarded as
436 // invalid server push response.
437 spdy::SpdyHeaderBlock* request_headers = promised_stream->mutable_headers();
438 (*request_headers)[":path"] = "/bar";
439 (*request_headers)[":authority"] = "www.google.com";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500440 (*request_headers)[":method"] = "GET";
441
QUICHE teama6ef0a62019-03-07 20:34:33 -0500442 response_headers_[":status"] = "404";
443 response_headers_["content-length"] = "8";
vasilvvc48c8712019-03-11 13:38:16 -0700444 std::string body = "NotFound";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500445
446 memory_cache_backend_.AddResponse("www.google.com", "/bar",
447 std::move(response_headers_), body);
448
449 InSequence s;
450 EXPECT_CALL(session_,
451 SendRstStream(promised_stream->id(), QUIC_STREAM_CANCELLED, 0));
452
453 promised_stream->DoSendResponse();
454}
455
456TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
457 // Add a request and response with valid headers.
458 spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
459 (*request_headers)[":path"] = "/bar";
460 (*request_headers)[":authority"] = "www.google.com";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500461 (*request_headers)[":method"] = "GET";
462
QUICHE teama6ef0a62019-03-07 20:34:33 -0500463 response_headers_[":status"] = "200";
464 response_headers_["content-length"] = "5";
vasilvvc48c8712019-03-11 13:38:16 -0700465 std::string body = "Yummm";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500466
467 std::unique_ptr<char[]> buffer;
468 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700469 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500470
471 memory_cache_backend_.AddResponse("www.google.com", "/bar",
472 std::move(response_headers_), body);
473 stream_->set_fin_received(true);
474
475 InSequence s;
476 EXPECT_CALL(*stream_, WriteHeadersMock(false));
renjietanga29a96a2019-10-10 12:47:50 -0700477 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800478 EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500479 }
renjietang7c239172020-02-21 13:50:39 -0800480 EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500481
482 stream_->DoSendResponse();
483 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
484 EXPECT_TRUE(stream_->write_side_closed());
485}
486
487TEST_P(QuicSimpleServerStreamTest, SendResponseWithPushResources) {
488 // Tests that if a response has push resources to be send, SendResponse() will
489 // call PromisePushResources() to handle these resources.
490
491 // Add a request and response with valid headers into cache.
vasilvvc48c8712019-03-11 13:38:16 -0700492 std::string host = "www.google.com";
493 std::string request_path = "/foo";
494 std::string body = "Yummm";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500495 std::unique_ptr<char[]> buffer;
496 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700497 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500498 QuicBackendResponse::ServerPushInfo push_info(
499 QuicUrl(host, "/bar"), spdy::SpdyHeaderBlock(),
500 QuicStream::kDefaultPriority, "Push body");
501 std::list<QuicBackendResponse::ServerPushInfo> push_resources;
502 push_resources.push_back(push_info);
503 memory_cache_backend_.AddSimpleResponseWithServerPushResources(
504 host, request_path, 200, body, push_resources);
505
506 spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
507 (*request_headers)[":path"] = request_path;
508 (*request_headers)[":authority"] = host;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500509 (*request_headers)[":method"] = "GET";
510
511 stream_->set_fin_received(true);
512 InSequence s;
513 EXPECT_CALL(session_, PromisePushResourcesMock(
514 host + request_path, _,
515 GetNthClientInitiatedBidirectionalStreamId(
516 connection_->transport_version(), 0),
fayang9a423762019-07-31 08:12:58 -0700517 _, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518 EXPECT_CALL(*stream_, WriteHeadersMock(false));
renjietanga29a96a2019-10-10 12:47:50 -0700519 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800520 EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521 }
renjietang7c239172020-02-21 13:50:39 -0800522 EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500523 stream_->DoSendResponse();
524 EXPECT_EQ(*request_headers, session_.original_request_headers_);
525}
526
527TEST_P(QuicSimpleServerStreamTest, PushResponseOnClientInitiatedStream) {
528 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
529 if (GetParam() != AllSupportedVersions()[0]) {
530 return;
531 }
532
533 // Calling PushResponse() on a client initialted stream is never supposed to
534 // happen.
535 EXPECT_QUIC_BUG(stream_->PushResponse(spdy::SpdyHeaderBlock()),
536 "Client initiated stream"
537 " shouldn't be used as promised stream.");
538}
539
540TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
541 // Tests that PushResponse() should take the given headers as request headers
542 // and fetch response from cache, and send it out.
543
544 // Create a stream with even stream id and test against this stream.
545 const QuicStreamId kServerInitiatedStreamId =
546 GetNthServerInitiatedUnidirectionalStreamId(
renjietang87cd7de2019-08-16 08:35:10 -0700547 connection_->transport_version(), 3);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500548 // Create a server initiated stream and pass it to session_.
549 auto server_initiated_stream =
550 new StrictMock<TestStream>(kServerInitiatedStreamId, &session_,
551 WRITE_UNIDIRECTIONAL, &memory_cache_backend_);
552 session_.ActivateStream(QuicWrapUnique(server_initiated_stream));
553
vasilvvc48c8712019-03-11 13:38:16 -0700554 const std::string kHost = "www.foo.com";
555 const std::string kPath = "/bar";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500556 spdy::SpdyHeaderBlock headers;
557 headers[":path"] = kPath;
558 headers[":authority"] = kHost;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500559 headers[":method"] = "GET";
560
QUICHE teama6ef0a62019-03-07 20:34:33 -0500561 response_headers_[":status"] = "200";
562 response_headers_["content-length"] = "5";
vasilvvc48c8712019-03-11 13:38:16 -0700563 const std::string kBody = "Hello";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500564 std::unique_ptr<char[]> buffer;
565 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700566 HttpEncoder::SerializeDataFrameHeader(kBody.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500567 memory_cache_backend_.AddResponse(kHost, kPath, std::move(response_headers_),
568 kBody);
569
570 // Call PushResponse() should trigger stream to fetch response from cache
571 // and send it back.
572 InSequence s;
573 EXPECT_CALL(*server_initiated_stream, WriteHeadersMock(false));
574
renjietanga29a96a2019-10-10 12:47:50 -0700575 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800576 EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header_length, _,
577 NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500578 }
579 EXPECT_CALL(session_,
renjietang7c239172020-02-21 13:50:39 -0800580 WritevData(kServerInitiatedStreamId, kBody.size(), _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500581 server_initiated_stream->PushResponse(std::move(headers));
582 EXPECT_EQ(kPath, server_initiated_stream->GetHeader(":path"));
583 EXPECT_EQ("GET", server_initiated_stream->GetHeader(":method"));
584}
585
586TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) {
587 EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
588
589 stream_->set_fin_received(true);
590
591 InSequence s;
592 EXPECT_CALL(*stream_, WriteHeadersMock(false));
renjietanga29a96a2019-10-10 12:47:50 -0700593 if (UsesHttp3()) {
renjietang7c239172020-02-21 13:50:39 -0800594 EXPECT_CALL(session_, WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500595 }
renjietang7c239172020-02-21 13:50:39 -0800596 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500597
598 stream_->DoSendErrorResponse();
599 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
600 EXPECT_TRUE(stream_->write_side_closed());
601}
602
603TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) {
604 EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
605
606 spdy::SpdyHeaderBlock request_headers;
607 // \000 is a way to write the null byte when followed by a literal digit.
QUICHE team5015e2e2019-12-11 09:38:06 -0800608 header_list_.OnHeader("content-length",
609 quiche::QuicheStringPiece("11\00012", 5));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500610
611 EXPECT_CALL(*stream_, WriteHeadersMock(false));
612 EXPECT_CALL(session_, WritevData(_, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800613 .WillRepeatedly(
614 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500615 stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
616
617 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
618 EXPECT_TRUE(stream_->reading_stopped());
619 EXPECT_TRUE(stream_->write_side_closed());
620}
621
622TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500623 EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
624
625 spdy::SpdyHeaderBlock request_headers;
626 // \000 is a way to write the null byte when followed by a literal digit.
QUICHE team5015e2e2019-12-11 09:38:06 -0800627 header_list_.OnHeader("content-length",
628 quiche::QuicheStringPiece("\00012", 3));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500629
630 EXPECT_CALL(*stream_, WriteHeadersMock(false));
631 EXPECT_CALL(session_, WritevData(_, _, _, _, _))
renjietang7c239172020-02-21 13:50:39 -0800632 .WillRepeatedly(
633 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500634 stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
635
636 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
637 EXPECT_TRUE(stream_->reading_stopped());
638 EXPECT_TRUE(stream_->write_side_closed());
639}
640
641TEST_P(QuicSimpleServerStreamTest, ValidMultipleContentLength) {
642 spdy::SpdyHeaderBlock request_headers;
643 // \000 is a way to write the null byte when followed by a literal digit.
QUICHE team5015e2e2019-12-11 09:38:06 -0800644 header_list_.OnHeader("content-length",
645 quiche::QuicheStringPiece("11\00011", 5));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500646
647 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
648
649 EXPECT_EQ(11, stream_->content_length());
650 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
651 EXPECT_FALSE(stream_->reading_stopped());
652 EXPECT_FALSE(stream_->write_side_closed());
653}
654
655TEST_P(QuicSimpleServerStreamTest,
656 DoNotSendQuicRstStreamNoErrorWithRstReceived) {
657 InSequence s;
658 EXPECT_FALSE(stream_->reading_stopped());
659
660 EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
bnc6f18a822019-11-27 17:50:38 -0800661 if (VersionUsesHttp3(connection_->transport_version())) {
662 // Unidirectional stream type and then a Stream Cancellation instruction is
663 // sent on the QPACK decoder stream. Ignore these writes without any
664 // assumption on their number or size.
665 auto* qpack_decoder_stream =
666 QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
renjietang7c239172020-02-21 13:50:39 -0800667 EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _))
bnc6f18a822019-11-27 17:50:38 -0800668 .Times(AnyNumber());
669 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500670 EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);
671 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
672 QUIC_STREAM_CANCELLED, 1234);
673 stream_->OnStreamReset(rst_frame);
fkastenholz305e1732019-06-18 05:01:22 -0700674 if (VersionHasIetfQuicFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500675 // For V99 receiving a RST_STREAM causes a 1-way close; the test requires
676 // a full close. A CloseWriteSide closes the other half of the stream.
677 // Everything should then work properly.
678 stream_->CloseWriteSide();
679 }
680 EXPECT_TRUE(stream_->reading_stopped());
681 EXPECT_TRUE(stream_->write_side_closed());
682}
683
684TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) {
685 char arr[] = {
686 0x3a, 0x68, 0x6f, 0x73, // :hos
687 0x74, 0x00, 0x00, 0x00, // t...
688 0x00, 0x00, 0x00, 0x00, // ....
689 0x07, 0x3a, 0x6d, 0x65, // .:me
690 0x74, 0x68, 0x6f, 0x64, // thod
691 0x00, 0x00, 0x00, 0x03, // ....
692 0x47, 0x45, 0x54, 0x00, // GET.
693 0x00, 0x00, 0x05, 0x3a, // ...:
694 0x70, 0x61, 0x74, 0x68, // path
695 0x00, 0x00, 0x00, 0x04, // ....
696 0x2f, 0x66, 0x6f, 0x6f, // /foo
697 0x00, 0x00, 0x00, 0x07, // ....
698 0x3a, 0x73, 0x63, 0x68, // :sch
699 0x65, 0x6d, 0x65, 0x00, // eme.
700 0x00, 0x00, 0x00, 0x00, // ....
701 0x00, 0x00, 0x08, 0x3a, // ...:
702 0x76, 0x65, 0x72, 0x73, // vers
703 0x96, 0x6f, 0x6e, 0x00, // <i(69)>on.
704 0x00, 0x00, 0x08, 0x48, // ...H
705 0x54, 0x54, 0x50, 0x2f, // TTP/
706 0x31, 0x2e, 0x31, // 1.1
707 };
bnc4e9283d2019-12-17 07:08:57 -0800708 quiche::QuicheStringPiece data(arr, QUICHE_ARRAYSIZE(arr));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500709 QuicStreamFrame frame(stream_->id(), true, 0, data);
710 // Verify that we don't crash when we get a invalid headers in stream frame.
711 stream_->OnStreamFrame(frame);
712}
713
714} // namespace
715} // namespace test
716} // namespace quic