chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_test.cc

// Copyright 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 "quiche/quic/core/http/quic_spdy_stream.h"

#include <algorithm>
#include <array>
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/null_encrypter.h"
#include "quiche/quic/core/http/http_constants.h"
#include "quiche/quic/core/http/http_encoder.h"
#include "quiche/quic/core/http/http_frames.h"
#include "quiche/quic/core/http/quic_spdy_session.h"
#include "quiche/quic/core/http/spdy_utils.h"
#include "quiche/quic/core/http/web_transport_http3.h"
#include "quiche/quic/core/qpack/value_splitting_header_list.h"
#include "quiche/quic/core/quic_connection.h"
#include "quiche/quic/core/quic_stream_sequencer_buffer.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/core/quic_write_blocked_list.h"
#include "quiche/quic/platform/api/quic_expect_bug.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/qpack/qpack_test_utils.h"
#include "quiche/quic/test_tools/quic_config_peer.h"
#include "quiche/quic/test_tools/quic_connection_peer.h"
#include "quiche/quic/test_tools/quic_flow_controller_peer.h"
#include "quiche/quic/test_tools/quic_session_peer.h"
#include "quiche/quic/test_tools/quic_spdy_session_peer.h"
#include "quiche/quic/test_tools/quic_spdy_stream_peer.h"
#include "quiche/quic/test_tools/quic_stream_peer.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
#include "quiche/common/capsule.h"
#include "quiche/common/quiche_ip_address.h"
#include "quiche/common/quiche_mem_slice_storage.h"
#include "quiche/common/simple_buffer_allocator.h"

Capsule;
HttpHeaderBlock;
IpAddressRange;
kV3HighestPriority;
kV3LowestPriority;
_;
AnyNumber;
AtLeast;
DoAll;
ElementsAre;
HasSubstr;
Invoke;
InvokeWithoutArgs;
MatchesRegex;
Optional;
Pair;
Return;
SaveArg;
StrictMock;

namespace quic {
namespace test {
namespace {

constexpr bool kShouldProcessData =;
constexpr absl::string_view kDataFramePayload =;

class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {};

class TestStream : public QuicSpdyStream {};

class TestSession : public MockQuicSpdySession {};

class TestMockUpdateStreamSession : public MockQuicSpdySession {};

class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {};

INSTANTIATE_TEST_SUITE_P();

TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {}

TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {}

TEST_P(QuicSpdyStreamTest, QpackProcessLargeHeaderListDiscountOverhead) {}

TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {}

// A valid status code should be 3-digit integer. The first digit should be in
// the range of [1, 5]. All the others are invalid.
TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {}

TEST_P(QuicSpdyStreamTest, MarkHeadersConsumed) {}

TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {}

TEST_P(QuicSpdyStreamTest, Http3FrameError) {}

TEST_P(QuicSpdyStreamTest, UnexpectedHttp3Frame) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndLargeBodySmallReadv) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndConsumeMultipleBody) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) {}

TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {}

// Tests that we send a BLOCKED frame to the peer when we attempt to write, but
// are flow control blocked.
TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {}

// The flow control receive window decreases whenever we add new bytes to the
// sequencer, whether they are consumed immediately or buffered. However we only
// send WINDOW_UPDATE frames based on increasing number of bytes consumed.
TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {}

// Tests that on receipt of data, the stream updates its receive window offset
// appropriately, and sends WINDOW_UPDATE frames when its receive window drops
// too low.
TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {}

// Tests that on receipt of data, the connection updates its receive window
// offset appropriately, and sends WINDOW_UPDATE frames when its receive window
// drops too low.
TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {}

// Tests that on if the peer sends too much data (i.e. violates the flow control
// protocol), then we terminate the connection.
TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {}

TEST_P(QuicSpdyStreamTest, TestHandlingQuicRstStreamNoError) {}

// Tests that on if the peer sends too much data (i.e. violates the flow control
// protocol), at the connection level (rather than the stream level) then we
// terminate the connection.
TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {}

// An attempt to write a FIN with no data should not be flow control blocked,
// even if the send window is 0.
TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {}

// Test that receiving trailing headers from the peer via OnStreamHeaderList()
// works, and can be read from the stream and consumed.
TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {}

// Test that when receiving trailing headers with an offset before response
// body, stream is closed at the right offset.
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {}

// Test that receiving trailers without a final offset field is an error.
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {}

// Test that received Trailers must always have the FIN set.
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {}

TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterHeadersWithFin) {}

// If body data are received with a FIN, no trailers should then arrive.
TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {}

TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {}

// Test that writing trailers will send a FIN, as Trailers are the last thing to
// be sent on a stream.
TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {}

TEST_P(QuicSpdyStreamTest, DoNotSendPriorityUpdateWithDefaultUrgency) {}

TEST_P(QuicSpdyStreamTest, ChangePriority) {}

TEST_P(QuicSpdyStreamTest, ChangePriorityBeforeWritingHeaders) {}

// Test that when writing trailers, the trailers that are actually sent to the
// peer contain the final offset field indicating last byte of data.
TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {}

// Test that if trailers are written after all other data has been written
// (headers and body), that this closes the stream for writing.
TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {}

// Test that the stream is not closed for writing when trailers are sent while
// there are still body bytes queued.
TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {}

// Test that it is not possible to write Trailers after a FIN has been sent.
TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {}

TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {}

TEST_P(QuicSpdyStreamTest, OnPriorityFrame) {}

TEST_P(QuicSpdyStreamTest, OnPriorityFrameAfterSendingData) {}

TEST_P(QuicSpdyStreamTest, SetPriorityBeforeUpdateStreamPriority) {}

TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {}

TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {}

// HTTP/3 only.
TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {}

// HTTP/3 only.
TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteBodySlices) {}

// HTTP/3 only.
TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {}

TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {}

TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {}

// The test stream will receive a stream frame containing malformed headers and
// normal body. Make sure the http decoder stops processing body after the
// connection shuts down.
TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {}

// Regression test for https://crbug.com/1027895: a HEADERS frame triggers an
// error in QuicSpdyStream::OnHeadersFramePayload().  This closes the
// connection, freeing the buffer of QuicStreamSequencer.  Therefore
// QuicStreamSequencer::MarkConsumed() must not be called from
// QuicSpdyStream::OnHeadersFramePayload().
TEST_P(QuicSpdyStreamTest, DoNotMarkConsumedAfterQpackDecodingError) {}

TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {}

TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {}

TEST_P(QuicSpdyStreamTest, BlockedHeaderDecodingAndStopReading) {}

TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {}

// Regression test for https://crbug.com/1024263 and for
// https://crbug.com/1025209#c11.
TEST_P(QuicSpdyStreamTest, BlockedHeaderDecodingUnblockedWithBufferedError) {}

TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {}

// Regression test for b/132603592: QPACK decoding unblocked after stream is
// closed.
TEST_P(QuicSpdyStreamTest, HeaderDecodingUnblockedAfterStreamClosed) {}

TEST_P(QuicSpdyStreamTest, HeaderDecodingUnblockedAfterResetReceived) {}

class QuicSpdyStreamIncrementalConsumptionTest : public QuicSpdyStreamTest {};

INSTANTIATE_TEST_SUITE_P();

// Test that stream bytes are consumed (by calling
// sequencer()->MarkConsumed()) incrementally, as soon as possible.
TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {}

TEST_P(QuicSpdyStreamIncrementalConsumptionTest, ReceiveUnknownFrame) {}

TEST_P(QuicSpdyStreamIncrementalConsumptionTest,
       ReceiveUnsupportedMetadataFrame) {}

class MockMetadataVisitor : public QuicSpdyStream::MetadataVisitor {};

TEST_P(QuicSpdyStreamIncrementalConsumptionTest, ReceiveMetadataFrame) {}

TEST_P(QuicSpdyStreamIncrementalConsumptionTest,
       ResetDuringMultipleMetadataFrames) {}

TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {}

// Close connection if a DATA frame is received before a HEADERS frame.
TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {}

// Close connection if a HEADERS frame is received after the trailing HEADERS.
TEST_P(QuicSpdyStreamTest, TrailersAfterTrailers) {}

// Regression test for https://crbug.com/978733.
// Close connection if a DATA frame is received after the trailing HEADERS.
TEST_P(QuicSpdyStreamTest, DataAfterTrailers) {}

// SETTINGS frames are invalid on bidirectional streams.  If one is received,
// the connection is closed.  No more data should be processed.
TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {}

// Stream Cancellation instruction is sent on QPACK decoder stream
// when stream is reset.
TEST_P(QuicSpdyStreamTest, StreamCancellationWhenStreamReset) {}

// Stream Cancellation instruction is sent on QPACK decoder stream
// when RESET_STREAM frame is received.
TEST_P(QuicSpdyStreamTest, StreamCancellationOnResetReceived) {}

TEST_P(QuicSpdyStreamTest, WriteHeadersReturnValue) {}

// Regression test for https://crbug.com/1177662.
// RESET_STREAM with QUIC_STREAM_NO_ERROR should not be treated in a special
// way: it should close the read side but not the write side.
TEST_P(QuicSpdyStreamTest, TwoResetStreamFrames) {}

TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeaders) {}

TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeaders) {}

TEST_P(QuicSpdyStreamTest, IncomingWebTransportStreamWhenUnsupported) {}

TEST_P(QuicSpdyStreamTest, IncomingWebTransportStream) {}

TEST_P(QuicSpdyStreamTest, IncomingWebTransportStreamWithPaddingDraft02) {}

TEST_P(QuicSpdyStreamTest, IncomingWebTransportStreamWithPaddingDraft07) {}

TEST_P(QuicSpdyStreamTest, ReceiveHttpDatagram) {}

TEST_P(QuicSpdyStreamTest, SendHttpDatagram) {}

TEST_P(QuicSpdyStreamTest, GetMaxDatagramSize) {}

TEST_P(QuicSpdyStreamTest, Capsules) {}

TEST_P(QuicSpdyStreamTest,
       QUIC_TEST_DISABLED_IN_CHROME(HeadersAccumulatorNullptr)) {}

// Regression test for https://crbug.com/1465224.
TEST_P(QuicSpdyStreamTest, ReadAfterReset) {}

TEST_P(QuicSpdyStreamTest, ColonDisallowedInHeaderName) {}

}  // namespace
}  // namespace test
}  // namespace quic