blob: 7a1e3a2ff0dbdfa0c3da5bb73f549796522cb4c9 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_QUIC_QUIC_SESSION_POOL_TEST_BASE_H_
#define NET_QUIC_QUIC_SESSION_POOL_TEST_BASE_H_
#include <sys/types.h>
#include <memory>
#include <ostream>
#include <set>
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/test/scoped_feature_list.h"
#include "net/base/features.h"
#include "net/base/mock_network_change_notifier.h"
#include "net/base/net_error_details.h"
#include "net/base/session_usage.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_stream.h"
#include "net/http/transport_security_state.h"
#include "net/http/transport_security_state_test_util.h"
#include "net/log/net_log.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/platform/impl/quic_test_flags_utils.h"
#include "net/quic/quic_session_pool.h"
#include "net/quic/quic_test_packet_maker.h"
#include "net/quic/quic_test_packet_printer.h"
#include "net/quic/test_task_runner.h"
#include "net/socket/datagram_client_socket.h"
#include "net/socket/socket_test_util.h"
#include "net/ssl/test_ssl_config_service.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_session.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/static_http_user_agent_settings.h"
namespace net::test {
class QuicSessionPoolTestBase : public WithTaskEnvironment {
public:
static constexpr char kDefaultServerHostName[] = "www.example.org";
static constexpr char kServer2HostName[] = "mail.example.org";
static constexpr char kServer3HostName[] = "docs.example.org";
static constexpr char kServer4HostName[] = "images.example.org";
static constexpr char kServer5HostName[] = "accounts.example.org";
static constexpr char kProxy1HostName[] = "proxy1.example.org";
static constexpr char kProxy2HostName[] = "proxy2.example.org";
static constexpr char kDifferentHostname[] = "different.example.com";
static constexpr int kDefaultServerPort = 443;
static constexpr char kDefaultUrl[] = "https://www.example.org/";
static constexpr char kServer2Url[] = "https://mail.example.org/";
static constexpr char kServer3Url[] = "https://docs.example.org/";
static constexpr char kServer4Url[] = "https://images.example.org/";
static constexpr char kServer5Url[] = "https://images.example.org/";
static constexpr char kProxy1Url[] = "https://proxy1.example.org/";
static constexpr char kProxy2Url[] = "https://proxy2.example.org/";
static constexpr size_t kMinRetryTimeForDefaultNetworkSecs = 1;
static constexpr size_t kWaitTimeForNewNetworkSecs = 10;
static constexpr uint64_t kConnectUdpContextId = 0;
protected:
explicit QuicSessionPoolTestBase(
quic::ParsedQuicVersion version,
std::vector<base::test::FeatureRef> enabled_features = {},
std::vector<base::test::FeatureRef> disabled_features = {});
~QuicSessionPoolTestBase();
void Initialize();
// Make a NEW_CONNECTION_ID frame available for client such that connection
// migration can begin with a new connection ID. A side effect of calling
// this function is that ACK_FRAME that should have been sent for the first
// packet read might be skipped in the unit test. If the order of ACKing is
// important for a test, use QuicTestPacketMaker::MakeNewConnectionIdPacket
// instead.
void MaybeMakeNewConnectionIdAvailableToSession(
const quic::QuicConnectionId& new_cid,
quic::QuicSession* session,
uint64_t sequence_number = 1u);
// Helper for building requests and invoking `QuicSessionRequest::Request`.
// This `Request` method has lots of arguments, most of which are always at
// their default values, so this helper supports specifying only the
// non-default arguments relevant to a specific test.
struct RequestBuilder {
RequestBuilder(QuicSessionPoolTestBase* test, QuicSessionPool* pool);
explicit RequestBuilder(QuicSessionPoolTestBase* test);
~RequestBuilder();
RequestBuilder(const RequestBuilder&) = delete;
RequestBuilder& operator=(const RequestBuilder&) = delete;
// Call the request's `Request` method with the parameters in the builder.
// The builder becomes invalid after this call.
int CallRequest();
// Arguments to request.Request().
url::SchemeHostPort destination{url::kHttpsScheme, kDefaultServerHostName,
kDefaultServerPort};
quic::ParsedQuicVersion quic_version;
ProxyChain proxy_chain = ProxyChain::Direct();
std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag =
TRAFFIC_ANNOTATION_FOR_TESTS;
raw_ptr<HttpUserAgentSettings> http_user_agent_settings = nullptr;
SessionUsage session_usage = SessionUsage::kDestination;
PrivacyMode privacy_mode = PRIVACY_MODE_DISABLED;
RequestPriority priority = DEFAULT_PRIORITY;
SocketTag socket_tag;
NetworkAnonymizationKey network_anonymization_key;
SecureDnsPolicy secure_dns_policy = SecureDnsPolicy::kAllow;
bool require_dns_https_alpn = false;
int cert_verify_flags = 0;
GURL url = GURL(kDefaultUrl);
NetLogWithSource net_log;
NetErrorDetails net_error_details;
CompletionOnceCallback failed_on_default_network_callback;
CompletionOnceCallback callback;
// The resulting request.
QuicSessionRequest request;
};
std::unique_ptr<HttpStream> CreateStream(QuicSessionRequest* request);
bool HasActiveSession(
const url::SchemeHostPort& scheme_host_port,
const NetworkAnonymizationKey& network_anonymization_key =
NetworkAnonymizationKey(),
const ProxyChain& proxy_chain = ProxyChain::Direct(),
SessionUsage session_usage = SessionUsage::kDestination,
bool require_dns_https_alpn = false);
bool HasActiveJob(const url::SchemeHostPort& scheme_host_port,
const PrivacyMode privacy_mode,
bool require_dns_https_alpn = false);
// Get the pending, not activated session, if there is only one session alive.
QuicChromiumClientSession* GetPendingSession(
const url::SchemeHostPort& scheme_host_port);
QuicChromiumClientSession* GetActiveSession(
const url::SchemeHostPort& scheme_host_port,
const NetworkAnonymizationKey& network_anonymization_key =
NetworkAnonymizationKey(),
const ProxyChain& proxy_chain = ProxyChain::Direct(),
SessionUsage session_usage = SessionUsage::kDestination,
bool require_dns_https_alpn = false);
int GetSourcePortForNewSessionAndGoAway(
const url::SchemeHostPort& destination);
int GetSourcePortForNewSessionInner(const url::SchemeHostPort& destination,
bool goaway_received);
static ProofVerifyDetailsChromium DefaultProofVerifyDetails();
void NotifyIPAddressChanged();
std::unique_ptr<quic::QuicEncryptedPacket>
ConstructServerConnectionClosePacket(uint64_t num);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructClientRstPacket(
uint64_t packet_number,
quic::QuicRstStreamErrorCode error_code);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructGetRequestPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool fin);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructConnectUdpRequestPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
std::string authority,
std::string path,
bool fin);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructClientH3DatagramPacket(
uint64_t packet_number,
uint64_t quarter_stream_id,
uint64_t context_id,
std::unique_ptr<quic::QuicEncryptedPacket> inner);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructOkResponsePacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool fin);
std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket();
std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
uint64_t packet_number);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerSettingsPacket(
uint64_t packet_number);
std::string ConstructDataHeader(size_t body_len);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerDataPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool fin,
std::string_view data);
quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) const;
quic::QuicStreamId GetQpackDecoderStreamId() const;
std::string StreamCancellationQpackDecoderInstruction(int n) const;
std::string StreamCancellationQpackDecoderInstruction(
int n,
bool create_stream) const;
quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n);
void OnFailedOnDefaultNetwork(int rv);
const quic::QuicConnectionId kNewCID = quic::test::TestConnectionId(12345678);
const url::SchemeHostPort kDefaultDestination{
url::kHttpsScheme, kDefaultServerHostName, kDefaultServerPort};
quic::test::QuicFlagSaver flags_; // Save/restore all QUIC flag values.
std::unique_ptr<MockHostResolverBase> host_resolver_;
TestSSLConfigService ssl_config_service_{SSLContextConfig()};
std::unique_ptr<MockClientSocketFactory> socket_factory_;
MockCryptoClientStreamFactory crypto_client_stream_factory_;
MockQuicContext context_;
const quic::ParsedQuicVersion version_;
QuicTestPacketMaker client_maker_;
QuicTestPacketMaker server_maker_;
std::unique_ptr<HttpServerProperties> http_server_properties_;
std::unique_ptr<MockCertVerifier> cert_verifier_;
TransportSecurityState transport_security_state_;
std::unique_ptr<TestProxyDelegate> proxy_delegate_;
std::unique_ptr<ScopedMockNetworkChangeNotifier>
scoped_mock_network_change_notifier_;
std::unique_ptr<QuicSessionPool> factory_;
NetLogWithSource net_log_;
TestCompletionCallback callback_;
const CompletionRepeatingCallback failed_on_default_network_callback_;
bool failed_on_default_network_ = false;
NetErrorDetails net_error_details_;
StaticHttpUserAgentSettings http_user_agent_settings_ = {"test-lang",
"test-ua"};
raw_ptr<QuicParams> quic_params_;
base::test::ScopedFeatureList scoped_feature_list_;
};
} // namespace net::test
#endif // NET_QUIC_QUIC_SESSION_POOL_TEST_BASE_H_