1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
|
// 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/privacy_mode.h"
#include "net/base/reconnect_notifier.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 TestConnectionChangeObserver : public ConnectionChangeNotifier::Observer {
public:
void OnSessionClosed() override;
void OnConnectionFailed() override;
void OnNetworkEvent(NetworkChangeEvent event) override;
int session_closed() const { return session_closed_; }
int connection_failed() const { return connection_failed_; }
int network_event() const { return network_event_; }
std::optional<NetworkChangeEvent> last_network_event() const {
return last_network_event_;
}
private:
int session_closed_ = 0;
int connection_failed_ = 0;
int network_event_ = 0;
std::optional<NetworkChangeEvent> last_network_event_;
};
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;
std::optional<ConnectionManagementConfig> connection_management_config;
// The resulting request.
QuicSessionRequest request;
};
std::unique_ptr<HttpStream> CreateStream(QuicSessionRequest* request);
bool HasActiveSession(
const url::SchemeHostPort& scheme_host_port,
PrivacyMode privacy_mode = PRIVACY_MODE_DISABLED,
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,
PrivacyMode privacy_mode = PRIVACY_MODE_DISABLED,
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> ConstructConnectUdpRequestPacket(
QuicTestPacketMaker& packet_maker,
uint64_t packet_number,
quic::QuicStreamId stream_id,
std::string authority,
std::string path,
bool fin);
std::string ConstructClientH3DatagramFrame(
uint64_t quarter_stream_id,
uint64_t context_id,
std::unique_ptr<quic::QuicEncryptedPacket> inner);
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(
QuicTestPacketMaker& packet_maker,
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool fin);
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::QuicReceivedPacket> ConstructInitialSettingsPacket(
QuicTestPacketMaker& packet_maker,
uint64_t packet_number);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerSettingsPacket(
uint64_t packet_number);
std::unique_ptr<quic::QuicEncryptedPacket> ConstructAckPacket(
test::QuicTestPacketMaker& packet_maker,
uint64_t packet_number,
uint64_t packet_num_received,
uint64_t smallest_received,
uint64_t largest_received);
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);
std::string ConstructH3Datagram(
uint64_t stream_id,
uint64_t context_id,
std::unique_ptr<quic::QuicEncryptedPacket> packet);
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"};
std::unique_ptr<TestConnectionChangeObserver> connection_change_observer_;
raw_ptr<QuicParams> quic_params_;
base::test::ScopedFeatureList scoped_feature_list_;
};
} // namespace net::test
#endif // NET_QUIC_QUIC_SESSION_POOL_TEST_BASE_H_
|