chromium/net/quic/quic_network_transaction_unittest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include <algorithm>
#include <ostream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/completion_once_callback.h"
#include "net/base/features.h"
#include "net/base/ip_endpoint.h"
#include "net/base/mock_network_change_notifier.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/proxy_chain.h"
#include "net/base/proxy_server.h"
#include "net/base/proxy_string_util.h"
#include "net/base/schemeful_site.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_proxy_delegate.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_connection_info.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_transaction.h"
#include "net/http/http_proxy_connect_job.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_stream.h"
#include "net/http/http_stream_factory.h"
#include "net/http/http_transaction_test_util.h"
#include "net/http/test_upload_data_stream_not_allow_http1.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/proxy_resolution/proxy_config_service_fixed.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/mock_crypto_client_stream_factory.h"
#include "net/quic/mock_quic_context.h"
#include "net/quic/mock_quic_data.h"
#include "net/quic/quic_chromium_alarm_factory.h"
#include "net/quic/quic_context.h"
#include "net/quic/quic_http_stream.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_session_pool_peer.h"
#include "net/quic/quic_socket_data_provider.h"
#include "net/quic/quic_test_packet_maker.h"
#include "net/quic/test_task_runner.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/mock_client_socket_pool_manager.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_performance_watcher.h"
#include "net/socket/socket_performance_watcher_factory.h"
#include "net/socket/socket_tag.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/spdy_test_util_common.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h"
#include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_test_util.h"
#include "net/websockets/websocket_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "url/gurl.h"

ElementsAre;
Key;

namespace net::test {

namespace {

enum DestinationType {};

const char kDefaultServerHostName[] =;
const char kDifferentHostname[] =;

constexpr std::string_view kQuic200RespStatusLine =;

// Response data used for QUIC requests in multiple tests.
constexpr std::string_view kQuicRespData =;
// Response data used for HTTP requests in multiple tests.
// TODO(crbug.com/41496581): Once MockReadWrite accepts a
// std::string_view parameter, we can use "constexpr std::string_view" for this.
const char kHttpRespData[] =;

struct TestParams {};

// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {}

// Run QuicNetworkTransactionWithDestinationTest instances with all value
// combinations of version and destination_type.
struct PoolingTestParams {};

// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const PoolingTestParams& p) {}

std::string GenerateQuicAltSvcHeaderValue(
    const quic::ParsedQuicVersionVector& versions,
    std::string host,
    uint16_t port) {}

std::string GenerateQuicAltSvcHeaderValue(
    const quic::ParsedQuicVersionVector& versions,
    uint16_t port) {}

std::string GenerateQuicAltSvcHeader(
    const quic::ParsedQuicVersionVector& versions) {}

std::vector<TestParams> GetTestParams() {}

std::vector<PoolingTestParams> GetPoolingTestParams() {}

std::string ConstructDataFrameForVersion(std::string_view body,
                                         quic::ParsedQuicVersion version) {}

}  // namespace

class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {};

class TestSocketPerformanceWatcherFactory
    : public SocketPerformanceWatcherFactory {};

class QuicNetworkTransactionTest
    : public PlatformTest,
      public ::testing::WithParamInterface<TestParams>,
      public WithTaskEnvironment {};

INSTANTIATE_TEST_SUITE_P();

TEST_P(QuicNetworkTransactionTest, BasicRequestAndResponse) {}

TEST_P(QuicNetworkTransactionTest, HeaderDecodingDelayHistogram) {}

TEST_P(QuicNetworkTransactionTest, BasicRequestAndResponseWithAsycWrites) {}

TEST_P(QuicNetworkTransactionTest, BasicRequestAndResponseWithTrailers) {}

// Regression test for crbug.com/332587381
TEST_P(QuicNetworkTransactionTest, BasicRequestAndResponseWithEmptyTrailers) {}

TEST_P(QuicNetworkTransactionTest, WriteErrorHandshakeConfirmed) {}

TEST_P(QuicNetworkTransactionTest, WriteErrorHandshakeConfirmedAsync) {}

TEST_P(QuicNetworkTransactionTest, SocketWatcherEnabled) {}

TEST_P(QuicNetworkTransactionTest, SocketWatcherDisabled) {}

TEST_P(QuicNetworkTransactionTest, ForceQuic) {}

// Regression test for https://crbug.com/1043531.
TEST_P(QuicNetworkTransactionTest, ResetOnEmptyResponseHeaders) {}

TEST_P(QuicNetworkTransactionTest, LargeResponseHeaders) {}

TEST_P(QuicNetworkTransactionTest, TooLargeResponseHeaders) {}

TEST_P(QuicNetworkTransactionTest, RedirectMultipleLocations) {}

TEST_P(QuicNetworkTransactionTest, ForceQuicForAll) {}

// Regression test for https://crbug.com/695225
TEST_P(QuicNetworkTransactionTest, 408Response) {}

TEST_P(QuicNetworkTransactionTest, QuicProxy) {}

// Regression test for https://crbug.com/492458.  Test that for an HTTP
// connection through a QUIC proxy, the certificate exhibited by the proxy is
// checked against the proxy hostname, not the origin hostname.
TEST_P(QuicNetworkTransactionTest, QuicProxyWithCert) {}

TEST_P(QuicNetworkTransactionTest, AlternativeServicesDifferentHost) {}

TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) {}

// Regression test for https://crbug.com/546991.
// The server might not be able to serve a request on an alternative connection,
// and might send a 421 Misdirected Request response status to indicate this.
// HttpNetworkTransaction should reset the request and retry without using
// alternative services.
TEST_P(QuicNetworkTransactionTest, RetryMisdirectedRequest) {}

TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {}

TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {}

TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuic) {}

TEST_P(QuicNetworkTransactionTest, UseIetfAlternativeServiceForQuic) {}

// Much like above, but makes sure NetworkAnonymizationKey is respected.
TEST_P(QuicNetworkTransactionTest,
       UseAlternativeServiceForQuicWithNetworkAnonymizationKey) {}

TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceWithVersionForQuic1) {}

TEST_P(QuicNetworkTransactionTest,
       PickQuicVersionWhenMultipleVersionsAreSupported) {}

TEST_P(QuicNetworkTransactionTest, SetAlternativeServiceWithScheme) {}

TEST_P(QuicNetworkTransactionTest, DoNotGetAltSvcForDifferentOrigin) {}

TEST_P(QuicNetworkTransactionTest,
       StoreMutuallySupportedVersionsWhenProcessAltSvc) {}

TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceAllSupportedVersion) {}

// Verify that if a QUIC connection times out, the QuicHttpStream will
// return QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) {}

// TODO(fayang): Add time driven TOO_MANY_RTOS test.

// Verify that if a QUIC protocol error occurs after the handshake is confirmed
// the request fails with QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, ProtocolErrorAfterHandshakeConfirmed) {}

// Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC
// connection times out, then QUIC will be marked as broken and the request
// retried over TCP.
TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken2) {}

// Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC
// protocol error occurs after the handshake is confirmed, the request
// retried over TCP and the QUIC will be marked as broken.
TEST_P(QuicNetworkTransactionTest,
       ProtocolErrorAfterHandshakeConfirmedThenBroken) {}

// Much like above test, but verifies that NetworkAnonymizationKey is respected.
TEST_P(QuicNetworkTransactionTest,
       ProtocolErrorAfterHandshakeConfirmedThenBrokenWithNetworkIsolationKey) {}

TEST_P(QuicNetworkTransactionTest,
       ProtocolErrorAfterHandshakeConfirmedThenBrokenWithUseDnsHttpsSvcbAlpn) {}

// Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC
// request is reset from, then QUIC will be marked as broken and the request
// retried over TCP.
TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) {}

// Verify that when an origin has two alt-svc advertisements, one local and one
// remote, that when the local is broken the request will go over QUIC via
// the remote Alt-Svc.
// This is a regression test for crbug/825646.
TEST_P(QuicNetworkTransactionTest, RemoteAltSvcWorkingWhileLocalAltSvcBroken) {}

// Verify that when multiple alternatives are broken,
// ALTERNATE_PROTOCOL_USAGE_BROKEN is only logged once.
// This is a regression test for crbug/1024613.
TEST_P(QuicNetworkTransactionTest, BrokenAlternativeOnlyRecordedOnce) {}

// Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC
// request is reset from, then QUIC will be marked as broken and the request
// retried over TCP. Then, subsequent requests will go over a new TCP
// connection instead of going back to the broken QUIC connection.
// This is a regression tests for crbug/731303.
TEST_P(QuicNetworkTransactionTest,
       ResetPooledAfterHandshakeConfirmedThenBroken) {}

TEST_P(QuicNetworkTransactionTest,
       DoNotUseAlternativeServiceQuicUnsupportedVersion) {}

// When multiple alternative services are advertised, HttpStreamFactory should
// select the alternative service which uses existing QUIC session if available.
// If no existing QUIC session can be used, use the first alternative service
// from the list.
TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {}

// Pool to existing session with matching quic::QuicServerId
// even if alternative service destination is different.
TEST_P(QuicNetworkTransactionTest, PoolByOrigin) {}

// Pool to existing session with matching destination and matching certificate
// even if origin is different, and even if the alternative service with
// matching destination is not the first one on the list.
TEST_P(QuicNetworkTransactionTest, PoolByDestination) {}

// Multiple origins have listed the same alternative services. When there's a
// existing QUIC session opened by a request to other origin,
// if the cert is valid, should select this QUIC session to make the request
// if this is also the first existing QUIC session.
TEST_P(QuicNetworkTransactionTest,
       UseSharedExistingAlternativeServiceForQuicWithValidCert) {}

TEST_P(QuicNetworkTransactionTest, AlternativeServiceDifferentPort) {}

TEST_P(QuicNetworkTransactionTest, ConfirmAlternativeService) {}

TEST_P(QuicNetworkTransactionTest,
       ConfirmAlternativeServiceWithNetworkIsolationKey) {}

TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {}

TEST_P(QuicNetworkTransactionTest, HungAlternativeService) {}

TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {}

TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {}

TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {}

TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {}

TEST_P(QuicNetworkTransactionTest, ZeroRTTWithTooEarlyResponse) {}

TEST_P(QuicNetworkTransactionTest, ZeroRTTWithMultipleTooEarlyResponse) {}

TEST_P(QuicNetworkTransactionTest,
       LogGranularQuicErrorCodeOnQuicProtocolErrorLocal) {}

TEST_P(QuicNetworkTransactionTest,
       LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {}

TEST_P(QuicNetworkTransactionTest, RstStreamErrorHandling) {}

TEST_P(QuicNetworkTransactionTest, RstStreamBeforeHeaders) {}

TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) {}

TEST_P(QuicNetworkTransactionTest,
       BrokenAlternateProtocolWithNetworkIsolationKey) {}

TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {}

TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) {}

TEST_P(QuicNetworkTransactionTest, DelayTCPOnStartWithQuicSupportOnSameIP) {}

TEST_P(QuicNetworkTransactionTest,
       DelayTCPOnStartWithQuicSupportOnDifferentIP) {}

TEST_P(QuicNetworkTransactionTest, NetErrorDetailsSetBeforeHandshake) {}

TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {}

TEST_P(QuicNetworkTransactionTest,
       FailedZeroRttBrokenAlternateProtocolWithNetworkIsolationKey) {}

TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) {}

TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) {}

TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnectProxy) {}

TEST_P(QuicNetworkTransactionTest, SecureResourceOverSecureQuic) {}

TEST_P(QuicNetworkTransactionTest, QuicUpload) {}

TEST_P(QuicNetworkTransactionTest, QuicUploadWriteError) {}

TEST_P(QuicNetworkTransactionTest, RetryAfterAsyncNoBufferSpace) {}

TEST_P(QuicNetworkTransactionTest, RetryAfterSynchronousNoBufferSpace) {}

TEST_P(QuicNetworkTransactionTest, MaxRetriesAfterAsyncNoBufferSpace) {}

TEST_P(QuicNetworkTransactionTest, MaxRetriesAfterSynchronousNoBufferSpace) {}

TEST_P(QuicNetworkTransactionTest, NoMigrationForMsgTooBig) {}

TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {}

TEST_P(QuicNetworkTransactionTest, HostInAllowlist) {}

TEST_P(QuicNetworkTransactionTest, HostNotInAllowlist) {}

class QuicNetworkTransactionWithDestinationTest
    : public PlatformTest,
      public ::testing::WithParamInterface<PoolingTestParams>,
      public WithTaskEnvironment {};

INSTANTIATE_TEST_SUITE_P();

// A single QUIC request fails because the certificate does not match the origin
// hostname, regardless of whether it matches the alternative service hostname.
TEST_P(QuicNetworkTransactionWithDestinationTest, InvalidCertificate) {}

// First request opens QUIC session to alternative service.  Second request
// pools to it, because destination matches and certificate is valid, even
// though quic::QuicServerId is different.
TEST_P(QuicNetworkTransactionWithDestinationTest, PoolIfCertificateValid) {}

// First request opens QUIC session to alternative service.  Second request does
// not pool to it, even though destination matches, because certificate is not
// valid.  Instead, a new QUIC session is opened to the same destination with a
// different quic::QuicServerId.
TEST_P(QuicNetworkTransactionWithDestinationTest,
       DoNotPoolIfCertificateInvalid) {}

// Performs an HTTPS/1.1 request over QUIC proxy tunnel.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectHttpsServer) {}

// Performs an HTTP/2 request over QUIC proxy tunnel.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectSpdyServer) {}

// Performs an HTTP/3 request over QUIC proxy tunnel.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectQuicServer) {}

// Performs an 'http://' request over QUIC proxy tunnel, where the endpoint
// has AlternativeService info, but that is not used for HTTP
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectHttpServer) {}

// Make two HTTP/1.1 requests to the same host over a QUIC proxy tunnel and
// check that the proxy socket is reused for the second request.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseTransportSocket) {}

// Make an HTTP/1.1 request to one host and an HTTP/2 request to a different
// host over a QUIC proxy tunnel. Check that the QUIC session to the proxy
// server is reused for the second request.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseQuicSession) {}

// Make two HTTP/1.1 requests, one to a host through a QUIC proxy and another
// directly to the proxy. The proxy socket should not be reused for the second
// request.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectNoReuseDifferentChains) {}

// Sends a CONNECT request to a QUIC proxy and receive a 500 response.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectFailure) {}

// Sends a CONNECT request to a QUIC proxy and get a UDP socket read error.
TEST_P(QuicNetworkTransactionTest, QuicProxyQuicConnectionError) {}

// Sends an HTTP/1.1 request over QUIC proxy tunnel and gets a bad cert from the
// host. Retries request and succeeds.
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectBadCertificate) {}

// Checks if a request's specified "user-agent" header shows up correctly in the
// CONNECT request to a QUIC proxy.
TEST_P(QuicNetworkTransactionTest, QuicProxyUserAgent) {}

// Makes sure the CONNECT request packet for a QUIC proxy contains the correct
// HTTP/2 stream dependency and weights given the request priority.
TEST_P(QuicNetworkTransactionTest, QuicProxyRequestPriority) {}

// Makes sure the CONNECT request packet for a QUIC proxy contains the correct
// HTTP/2 stream dependency and weights given the request priority.
TEST_P(QuicNetworkTransactionTest, QuicProxyMultipleRequestsError) {}

// Test the request-challenge-retry sequence for basic auth, over a QUIC
// connection when setting up a QUIC proxy tunnel.
TEST_P(QuicNetworkTransactionTest, QuicProxyAuth) {}

// Test that NetworkAnonymizationKey is respected by QUIC connections, when
// kPartitionConnectionsByNetworkIsolationKey is enabled.
TEST_P(QuicNetworkTransactionTest, NetworkIsolation) {}

// Test that two requests to the same origin over QUIC tunnels use different
// QUIC sessions if their NetworkIsolationKeys don't match, and
// kPartitionConnectionsByNetworkIsolationKey is enabled.
TEST_P(QuicNetworkTransactionTest, NetworkIsolationTunnel) {}

TEST_P(QuicNetworkTransactionTest, AllowHTTP1FalseProhibitsH1) {}

// Confirm mock class UploadDataStreamNotAllowHTTP1 can upload content over
// QUIC.
TEST_P(QuicNetworkTransactionTest, AllowHTTP1MockTest) {}

TEST_P(QuicNetworkTransactionTest, AllowHTTP1UploadPauseAndResume) {}

TEST_P(QuicNetworkTransactionTest, AllowHTTP1UploadFailH1AndResumeQuic) {}

TEST_P(QuicNetworkTransactionTest, IncorrectHttp3GoAway) {}

TEST_P(QuicNetworkTransactionTest, RetryOnHttp3GoAway) {}

// TODO(yoichio):  Add the TCP job reuse case. See crrev.com/c/2174099.

#if BUILDFLAG(ENABLE_WEBSOCKETS)

// This test verifies that when there is an HTTP/3 connection open to a server,
// a WebSocket request does not use it, but instead opens a new connection with
// HTTP/1.
TEST_P(QuicNetworkTransactionTest, WebsocketOpensNewConnectionWithHttp1) {}

// Much like above, but for Alt-Svc QUIC.
TEST_P(QuicNetworkTransactionTest,
       WebsocketOpensNewConnectionWithHttp1AfterAltSvcQuic) {}

// Much like above, but for DnsHttpsSvcbAlpn QUIC.
TEST_P(QuicNetworkTransactionTest,
       WebsocketOpensNewConnectionWithHttp1AfterDnsHttpsSvcbAlpn) {}

#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)

}  // namespace net::test