summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc')
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc789
1 files changed, 0 insertions, 789 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
deleted file mode 100644
index b75246f0ea5..00000000000
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
+++ /dev/null
@@ -1,789 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "quic/tools/quic_simple_server_stream.h"
-
-#include <list>
-#include <memory>
-#include <utility>
-
-#include "absl/base/macros.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
-#include "quic/core/crypto/null_encrypter.h"
-#include "quic/core/http/http_encoder.h"
-#include "quic/core/http/spdy_utils.h"
-#include "quic/core/quic_error_codes.h"
-#include "quic/core/quic_simple_buffer_allocator.h"
-#include "quic/core/quic_types.h"
-#include "quic/core/quic_utils.h"
-#include "quic/platform/api/quic_expect_bug.h"
-#include "quic/platform/api/quic_socket_address.h"
-#include "quic/platform/api/quic_test.h"
-#include "quic/test_tools/crypto_test_utils.h"
-#include "quic/test_tools/quic_config_peer.h"
-#include "quic/test_tools/quic_connection_peer.h"
-#include "quic/test_tools/quic_session_peer.h"
-#include "quic/test_tools/quic_spdy_session_peer.h"
-#include "quic/test_tools/quic_stream_peer.h"
-#include "quic/test_tools/quic_test_utils.h"
-#include "quic/tools/quic_backend_response.h"
-#include "quic/tools/quic_memory_cache_backend.h"
-#include "quic/tools/quic_simple_server_session.h"
-
-using testing::_;
-using testing::AnyNumber;
-using testing::InSequence;
-using testing::Invoke;
-using testing::StrictMock;
-
-namespace quic {
-namespace test {
-
-const size_t kFakeFrameLen = 60;
-const size_t kErrorLength = strlen(QuicSimpleServerStream::kErrorResponseBody);
-const size_t kDataFrameHeaderLength = 2;
-
-class TestStream : public QuicSimpleServerStream {
- public:
- TestStream(QuicStreamId stream_id, QuicSpdySession* session, StreamType type,
- QuicSimpleServerBackend* quic_simple_server_backend)
- : QuicSimpleServerStream(stream_id, session, type,
- quic_simple_server_backend) {}
-
- ~TestStream() override = default;
-
- MOCK_METHOD(void, WriteHeadersMock, (bool fin), ());
- MOCK_METHOD(void, WriteEarlyHintsHeadersMock, (bool fin), ());
-
- size_t WriteHeaders(spdy::Http2HeaderBlock header_block, bool fin,
- QuicReferenceCountedPointer<QuicAckListenerInterface>
- /*ack_listener*/) override {
- if (header_block[":status"] == "103") {
- WriteEarlyHintsHeadersMock(fin);
- } else {
- WriteHeadersMock(fin);
- }
- return 0;
- }
-
- // Expose protected QuicSimpleServerStream methods.
- void DoSendResponse() { SendResponse(); }
- void DoSendErrorResponse() { QuicSimpleServerStream::SendErrorResponse(); }
-
- spdy::Http2HeaderBlock* mutable_headers() { return &request_headers_; }
- void set_body(std::string body) { body_ = std::move(body); }
- const std::string& body() const { return body_; }
- int content_length() const { return content_length_; }
- bool send_response_was_called() const { return send_response_was_called_; }
- bool send_error_response_was_called() const {
- return send_error_response_was_called_;
- }
-
- absl::string_view GetHeader(absl::string_view key) const {
- auto it = request_headers_.find(key);
- QUICHE_DCHECK(it != request_headers_.end());
- return it->second;
- }
-
- protected:
- void SendResponse() override {
- send_response_was_called_ = true;
- QuicSimpleServerStream::SendResponse();
- }
-
- void SendErrorResponse(int resp_code) override {
- send_error_response_was_called_ = true;
- QuicSimpleServerStream::SendErrorResponse(resp_code);
- }
-
- private:
- bool send_response_was_called_ = false;
- bool send_error_response_was_called_ = false;
-};
-
-namespace {
-
-class MockQuicSimpleServerSession : public QuicSimpleServerSession {
- public:
- const size_t kMaxStreamsForTest = 100;
-
- MockQuicSimpleServerSession(
- QuicConnection* connection, MockQuicSessionVisitor* owner,
- MockQuicCryptoServerStreamHelper* helper,
- QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- QuicSimpleServerBackend* quic_simple_server_backend)
- : QuicSimpleServerSession(DefaultQuicConfig(), CurrentSupportedVersions(),
- connection, owner, helper, crypto_config,
- compressed_certs_cache,
- quic_simple_server_backend) {
- if (VersionHasIetfQuicFrames(connection->transport_version())) {
- QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
- this, kMaxStreamsForTest);
- QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
- this, kMaxStreamsForTest);
- } else {
- QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
- QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
- }
- ON_CALL(*this, WritevData(_, _, _, _, _, _))
- .WillByDefault(Invoke(this, &MockQuicSimpleServerSession::ConsumeData));
- }
-
- MockQuicSimpleServerSession(const MockQuicSimpleServerSession&) = delete;
- MockQuicSimpleServerSession& operator=(const MockQuicSimpleServerSession&) =
- delete;
- ~MockQuicSimpleServerSession() override = default;
-
- MOCK_METHOD(void, OnConnectionClosed,
- (const QuicConnectionCloseFrame& frame,
- ConnectionCloseSource source),
- (override));
- MOCK_METHOD(QuicSpdyStream*, CreateIncomingStream, (QuicStreamId id),
- (override));
- MOCK_METHOD(QuicConsumedData, WritevData,
- (QuicStreamId id, size_t write_length, QuicStreamOffset offset,
- StreamSendingState state, TransmissionType type,
- EncryptionLevel level),
- (override));
- MOCK_METHOD(void, OnStreamHeaderList,
- (QuicStreamId stream_id, bool fin, size_t frame_len,
- const QuicHeaderList& header_list),
- (override));
- MOCK_METHOD(void, OnStreamHeadersPriority,
- (QuicStreamId stream_id,
- const spdy::SpdyStreamPrecedence& precedence),
- (override));
- MOCK_METHOD(void, MaybeSendRstStreamFrame,
- (QuicStreamId stream_id, QuicResetStreamError error,
- QuicStreamOffset bytes_written),
- (override));
- MOCK_METHOD(void, MaybeSendStopSendingFrame,
- (QuicStreamId stream_id, QuicResetStreamError error), (override));
-
- using QuicSession::ActivateStream;
-
- QuicConsumedData ConsumeData(QuicStreamId id, size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
- TransmissionType /*type*/,
- absl::optional<EncryptionLevel> /*level*/) {
- if (write_length > 0) {
- auto buf = std::make_unique<char[]>(write_length);
- QuicStream* stream = GetOrCreateStream(id);
- QUICHE_DCHECK(stream);
- QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
- stream->WriteStreamData(offset, write_length, &writer);
- } else {
- QUICHE_DCHECK(state != NO_FIN);
- }
- return QuicConsumedData(write_length, state != NO_FIN);
- }
-
- spdy::Http2HeaderBlock original_request_headers_;
-};
-
-class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
- public:
- QuicSimpleServerStreamTest()
- : connection_(new StrictMock<MockQuicConnection>(
- &helper_, &alarm_factory_, Perspective::IS_SERVER,
- SupportedVersions(GetParam()))),
- crypto_config_(new QuicCryptoServerConfig(
- QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
- crypto_test_utils::ProofSourceForTesting(),
- KeyExchangeSource::Default())),
- compressed_certs_cache_(
- QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
- session_(connection_, &session_owner_, &session_helper_,
- crypto_config_.get(), &compressed_certs_cache_,
- &memory_cache_backend_),
- quic_response_(new QuicBackendResponse),
- body_("hello world") {
- connection_->set_visitor(&session_);
- header_list_.OnHeaderBlockStart();
- header_list_.OnHeader(":authority", "www.google.com");
- header_list_.OnHeader(":path", "/");
- header_list_.OnHeader(":method", "POST");
- header_list_.OnHeader(":scheme", "https");
- header_list_.OnHeader("content-length", "11");
-
- header_list_.OnHeaderBlockEnd(128, 128);
-
- // New streams rely on having the peer's flow control receive window
- // negotiated in the config.
- session_.config()->SetInitialStreamFlowControlWindowToSend(
- kInitialStreamFlowControlWindowForTest);
- session_.config()->SetInitialSessionFlowControlWindowToSend(
- kInitialSessionFlowControlWindowForTest);
- session_.Initialize();
- connection_->SetEncrypter(
- quic::ENCRYPTION_FORWARD_SECURE,
- std::make_unique<quic::NullEncrypter>(connection_->perspective()));
- if (connection_->version().SupportsAntiAmplificationLimit()) {
- QuicConnectionPeer::SetAddressValidated(connection_);
- }
- stream_ = new StrictMock<TestStream>(
- GetNthClientInitiatedBidirectionalStreamId(
- connection_->transport_version(), 0),
- &session_, BIDIRECTIONAL, &memory_cache_backend_);
- // Register stream_ in dynamic_stream_map_ and pass ownership to session_.
- session_.ActivateStream(absl::WrapUnique(stream_));
- QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
- session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
- session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
- session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
- session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 10);
- session_.OnConfigNegotiated();
- connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
- }
-
- const std::string& StreamBody() { return stream_->body(); }
-
- std::string StreamHeadersValue(const std::string& key) {
- return (*stream_->mutable_headers())[key].as_string();
- }
-
- bool UsesHttp3() const {
- return VersionUsesHttp3(connection_->transport_version());
- }
-
- spdy::Http2HeaderBlock response_headers_;
- MockQuicConnectionHelper helper_;
- MockAlarmFactory alarm_factory_;
- StrictMock<MockQuicConnection>* connection_;
- StrictMock<MockQuicSessionVisitor> session_owner_;
- StrictMock<MockQuicCryptoServerStreamHelper> session_helper_;
- std::unique_ptr<QuicCryptoServerConfig> crypto_config_;
- QuicCompressedCertsCache compressed_certs_cache_;
- QuicMemoryCacheBackend memory_cache_backend_;
- StrictMock<MockQuicSimpleServerSession> session_;
- StrictMock<TestStream>* stream_; // Owned by session_.
- std::unique_ptr<QuicBackendResponse> quic_response_;
- std::string body_;
- QuicHeaderList header_list_;
-};
-
-INSTANTIATE_TEST_SUITE_P(Tests, QuicSimpleServerStreamTest,
- ::testing::ValuesIn(AllSupportedVersions()),
- ::testing::PrintToStringParamName());
-
-TEST_P(QuicSimpleServerStreamTest, TestFraming) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
- stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body_.length(), SimpleBufferAllocator::Get());
- std::string data =
- UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
- stream_->OnStreamFrame(
- QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
- EXPECT_EQ("11", StreamHeadersValue("content-length"));
- EXPECT_EQ("/", StreamHeadersValue(":path"));
- EXPECT_EQ("POST", StreamHeadersValue(":method"));
- EXPECT_EQ(body_, StreamBody());
-}
-
-TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
-
- stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body_.length(), SimpleBufferAllocator::Get());
- std::string data =
- UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
- stream_->OnStreamFrame(
- QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
- EXPECT_EQ("11", StreamHeadersValue("content-length"));
- EXPECT_EQ("/", StreamHeadersValue(":path"));
- EXPECT_EQ("POST", StreamHeadersValue(":method"));
- EXPECT_EQ(body_, StreamBody());
-}
-
-TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
-
- EXPECT_FALSE(stream_->fin_received());
- EXPECT_FALSE(stream_->rst_received());
-
- QuicStreamPeer::SetFinSent(stream_);
- stream_->CloseWriteSide();
-
- if (session_.version().UsesHttp3()) {
- EXPECT_CALL(session_,
- MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
- QUIC_STREAM_NO_ERROR)))
- .Times(1);
- } else {
- EXPECT_CALL(
- session_,
- MaybeSendRstStreamFrame(
- _, QuicResetStreamError::FromInternal(QUIC_STREAM_NO_ERROR), _))
- .Times(1);
- }
- stream_->StopReading();
-}
-
-TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
- InSequence seq;
- std::string large_body = "hello world!!!!!!";
-
- // We'll automatically write out an error (headers + body)
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_,
- WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
-
- stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body_.length(), SimpleBufferAllocator::Get());
- std::string data =
- UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
-
- stream_->OnStreamFrame(
- QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
- // Content length is still 11. This will register as an error and we won't
- // accept the bytes.
- header = HttpEncoder::SerializeDataFrameHeader(large_body.length(),
- SimpleBufferAllocator::Get());
- std::string data2 = UsesHttp3()
- ? absl::StrCat(header.AsStringView(), large_body)
- : large_body;
- stream_->OnStreamFrame(
- QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2));
- EXPECT_EQ("11", StreamHeadersValue("content-length"));
- EXPECT_EQ("/", StreamHeadersValue(":path"));
- EXPECT_EQ("POST", StreamHeadersValue(":method"));
-}
-
-TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
- // Send an illegal response with response status not supported by HTTP/2.
- spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
- (*request_headers)[":path"] = "/bar";
- (*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":method"] = "GET";
-
- // HTTP/2 only supports integer responsecode, so "200 OK" is illegal.
- response_headers_[":status"] = "200 OK";
- response_headers_["content-length"] = "5";
- std::string body = "Yummm";
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body.length(), SimpleBufferAllocator::Get());
-
- memory_cache_backend_.AddResponse("www.google.com", "/bar",
- std::move(response_headers_), body);
-
- QuicStreamPeer::SetFinReceived(stream_);
-
- InSequence s;
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
-
- stream_->DoSendResponse();
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
- // Send an illegal response with response status not supported by HTTP/2.
- spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
- (*request_headers)[":path"] = "/bar";
- (*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":method"] = "GET";
-
- // HTTP/2 only supports 3-digit-integer, so "+200" is illegal.
- response_headers_[":status"] = "+200";
- response_headers_["content-length"] = "5";
- std::string body = "Yummm";
-
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body.length(), SimpleBufferAllocator::Get());
-
- memory_cache_backend_.AddResponse("www.google.com", "/bar",
- std::move(response_headers_), body);
-
- QuicStreamPeer::SetFinReceived(stream_);
-
- InSequence s;
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
-
- stream_->DoSendResponse();
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
- // Create a new promised stream with even id().
- auto promised_stream = new StrictMock<TestStream>(
- GetNthServerInitiatedUnidirectionalStreamId(
- connection_->transport_version(), 3),
- &session_, WRITE_UNIDIRECTIONAL, &memory_cache_backend_);
- session_.ActivateStream(absl::WrapUnique(promised_stream));
-
- // Send a push response with response status 404, which will be regarded as
- // invalid server push response.
- spdy::Http2HeaderBlock* request_headers = promised_stream->mutable_headers();
- (*request_headers)[":path"] = "/bar";
- (*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":method"] = "GET";
-
- response_headers_[":status"] = "404";
- response_headers_["content-length"] = "8";
- std::string body = "NotFound";
-
- memory_cache_backend_.AddResponse("www.google.com", "/bar",
- std::move(response_headers_), body);
-
- InSequence s;
- if (session_.version().UsesHttp3()) {
- EXPECT_CALL(session_,
- MaybeSendStopSendingFrame(
- promised_stream->id(),
- QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED)));
- }
- EXPECT_CALL(
- session_,
- MaybeSendRstStreamFrame(
- promised_stream->id(),
- QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), 0));
-
- promised_stream->DoSendResponse();
-}
-
-TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
- // Add a request and response with valid headers.
- spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
- (*request_headers)[":path"] = "/bar";
- (*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":method"] = "GET";
-
- response_headers_[":status"] = "200";
- response_headers_["content-length"] = "5";
- std::string body = "Yummm";
-
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body.length(), SimpleBufferAllocator::Get());
-
- memory_cache_backend_.AddResponse("www.google.com", "/bar",
- std::move(response_headers_), body);
- QuicStreamPeer::SetFinReceived(stream_);
-
- InSequence s;
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
-
- stream_->DoSendResponse();
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, SendResponseWithEarlyHints) {
- std::string host = "www.google.com";
- std::string request_path = "/foo";
- std::string body = "Yummm";
-
- // Add a request and response with early hints.
- spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
- (*request_headers)[":path"] = request_path;
- (*request_headers)[":authority"] = host;
- (*request_headers)[":method"] = "GET";
-
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body.length(), SimpleBufferAllocator::Get());
- std::vector<spdy::Http2HeaderBlock> early_hints;
- // Add two Early Hints.
- const size_t kNumEarlyHintsResponses = 2;
- for (size_t i = 0; i < kNumEarlyHintsResponses; ++i) {
- spdy::Http2HeaderBlock hints;
- hints["link"] = "</image.png>; rel=preload; as=image";
- early_hints.push_back(std::move(hints));
- }
-
- response_headers_[":status"] = "200";
- response_headers_["content-length"] = "5";
- memory_cache_backend_.AddResponseWithEarlyHints(
- host, request_path, std::move(response_headers_), body, early_hints);
- QuicStreamPeer::SetFinReceived(stream_);
-
- InSequence s;
- for (size_t i = 0; i < kNumEarlyHintsResponses; ++i) {
- EXPECT_CALL(*stream_, WriteEarlyHintsHeadersMock(false));
- }
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
-
- stream_->DoSendResponse();
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, PushResponseOnClientInitiatedStream) {
- // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
- return;
- }
-
- // Calling PushResponse() on a client initialted stream is never supposed to
- // happen.
- EXPECT_QUIC_BUG(stream_->PushResponse(spdy::Http2HeaderBlock()),
- "Client initiated stream"
- " shouldn't be used as promised stream.");
-}
-
-TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
- // Tests that PushResponse() should take the given headers as request headers
- // and fetch response from cache, and send it out.
-
- // Create a stream with even stream id and test against this stream.
- const QuicStreamId kServerInitiatedStreamId =
- GetNthServerInitiatedUnidirectionalStreamId(
- connection_->transport_version(), 3);
- // Create a server initiated stream and pass it to session_.
- auto server_initiated_stream =
- new StrictMock<TestStream>(kServerInitiatedStreamId, &session_,
- WRITE_UNIDIRECTIONAL, &memory_cache_backend_);
- session_.ActivateStream(absl::WrapUnique(server_initiated_stream));
-
- const std::string kHost = "www.foo.com";
- const std::string kPath = "/bar";
- spdy::Http2HeaderBlock headers;
- headers[":path"] = kPath;
- headers[":authority"] = kHost;
- headers[":method"] = "GET";
-
- response_headers_[":status"] = "200";
- response_headers_["content-length"] = "5";
- const std::string kBody = "Hello";
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body_.length(), SimpleBufferAllocator::Get());
- memory_cache_backend_.AddResponse(kHost, kPath, std::move(response_headers_),
- kBody);
-
- // Call PushResponse() should trigger stream to fetch response from cache
- // and send it back.
- InSequence s;
- EXPECT_CALL(*server_initiated_stream, WriteHeadersMock(false));
-
- if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header.size(), _,
- NO_FIN, _, _));
- }
- EXPECT_CALL(session_,
- WritevData(kServerInitiatedStreamId, kBody.size(), _, FIN, _, _));
- server_initiated_stream->PushResponse(std::move(headers));
- EXPECT_EQ(kPath, server_initiated_stream->GetHeader(":path"));
- EXPECT_EQ("GET", server_initiated_stream->GetHeader(":method"));
-}
-
-TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) {
- QuicStreamPeer::SetFinReceived(stream_);
-
- InSequence s;
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_,
- WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
-
- stream_->DoSendErrorResponse();
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) {
- spdy::Http2HeaderBlock request_headers;
- // \000 is a way to write the null byte when followed by a literal digit.
- header_list_.OnHeader("content-length", absl::string_view("11\00012", 5));
-
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
- stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
-
- EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->reading_stopped());
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) {
- spdy::Http2HeaderBlock request_headers;
- // \000 is a way to write the null byte when followed by a literal digit.
- header_list_.OnHeader("content-length", absl::string_view("\00012", 3));
-
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
- stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
-
- EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->reading_stopped());
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, ValidMultipleContentLength) {
- spdy::Http2HeaderBlock request_headers;
- // \000 is a way to write the null byte when followed by a literal digit.
- header_list_.OnHeader("content-length", absl::string_view("11\00011", 5));
-
- stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
-
- EXPECT_EQ(11, stream_->content_length());
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_FALSE(stream_->reading_stopped());
- EXPECT_FALSE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest,
- DoNotSendQuicRstStreamNoErrorWithRstReceived) {
- EXPECT_FALSE(stream_->reading_stopped());
-
- if (VersionUsesHttp3(connection_->transport_version())) {
- // Unidirectional stream type and then a Stream Cancellation instruction is
- // sent on the QPACK decoder stream. Ignore these writes without any
- // assumption on their number or size.
- auto* qpack_decoder_stream =
- QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
- EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _, _))
- .Times(AnyNumber());
- }
-
- EXPECT_CALL(
- session_,
- MaybeSendRstStreamFrame(
- _,
- session_.version().UsesHttp3()
- ? QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED)
- : QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT),
- _))
- .Times(1);
- QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
- QUIC_STREAM_CANCELLED, 1234);
- stream_->OnStreamReset(rst_frame);
- if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- EXPECT_CALL(session_owner_, OnStopSendingReceived(_));
- // Create and inject a STOP SENDING frame to complete the close
- // of the stream. This is only needed for version 99/IETF QUIC.
- QuicStopSendingFrame stop_sending(kInvalidControlFrameId, stream_->id(),
- QUIC_STREAM_CANCELLED);
- session_.OnStopSendingFrame(stop_sending);
- }
- EXPECT_TRUE(stream_->reading_stopped());
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) {
- char arr[] = {
- 0x3a, 0x68, 0x6f, 0x73, // :hos
- 0x74, 0x00, 0x00, 0x00, // t...
- 0x00, 0x00, 0x00, 0x00, // ....
- 0x07, 0x3a, 0x6d, 0x65, // .:me
- 0x74, 0x68, 0x6f, 0x64, // thod
- 0x00, 0x00, 0x00, 0x03, // ....
- 0x47, 0x45, 0x54, 0x00, // GET.
- 0x00, 0x00, 0x05, 0x3a, // ...:
- 0x70, 0x61, 0x74, 0x68, // path
- 0x00, 0x00, 0x00, 0x04, // ....
- 0x2f, 0x66, 0x6f, 0x6f, // /foo
- 0x00, 0x00, 0x00, 0x07, // ....
- 0x3a, 0x73, 0x63, 0x68, // :sch
- 0x65, 0x6d, 0x65, 0x00, // eme.
- 0x00, 0x00, 0x00, 0x00, // ....
- 0x00, 0x00, 0x08, 0x3a, // ...:
- 0x76, 0x65, 0x72, 0x73, // vers
- '\x96', 0x6f, 0x6e, 0x00, // <i(69)>on.
- 0x00, 0x00, 0x08, 0x48, // ...H
- 0x54, 0x54, 0x50, 0x2f, // TTP/
- 0x31, 0x2e, 0x31, // 1.1
- };
- absl::string_view data(arr, ABSL_ARRAYSIZE(arr));
- QuicStreamFrame frame(stream_->id(), true, 0, data);
- // Verify that we don't crash when we get a invalid headers in stream frame.
- stream_->OnStreamFrame(frame);
-}
-
-TEST_P(QuicSimpleServerStreamTest, ConnectSendsResponseBeforeFinReceived) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
- QuicHeaderList header_list;
- header_list.OnHeaderBlockStart();
- header_list.OnHeader(":authority", "www.google.com:4433");
- header_list.OnHeader(":method", "CONNECT");
- header_list.OnHeaderBlockEnd(128, 128);
- EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
- stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
- QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
- body_.length(), SimpleBufferAllocator::Get());
- std::string data =
- UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
- stream_->OnStreamFrame(
- QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
- EXPECT_EQ("CONNECT", StreamHeadersValue(":method"));
- EXPECT_EQ(body_, StreamBody());
- EXPECT_TRUE(stream_->send_response_was_called());
- EXPECT_FALSE(stream_->send_error_response_was_called());
-}
-
-TEST_P(QuicSimpleServerStreamTest, ConnectWithInvalidHeader) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
- .WillRepeatedly(
- Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
- QuicHeaderList header_list;
- header_list.OnHeaderBlockStart();
- header_list.OnHeader(":authority", "www.google.com:4433");
- header_list.OnHeader(":method", "CONNECT");
- // QUIC requires lower-case header names.
- header_list.OnHeader("InVaLiD-HeAdEr", "Well that's just wrong!");
- header_list.OnHeaderBlockEnd(128, 128);
-
- if (UsesHttp3()) {
- EXPECT_CALL(session_,
- MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
- QUIC_STREAM_NO_ERROR)))
- .Times(1);
- } else {
- EXPECT_CALL(
- session_,
- MaybeSendRstStreamFrame(
- _, QuicResetStreamError::FromInternal(QUIC_STREAM_NO_ERROR), _))
- .Times(1);
- }
- EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
- stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
- EXPECT_FALSE(stream_->send_response_was_called());
- EXPECT_TRUE(stream_->send_error_response_was_called());
-}
-
-} // namespace
-} // namespace test
-} // namespace quic