xref: /aosp_15_r20/external/cronet/net/spdy/spdy_test_util_common.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
6 #define NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <map>
12 #include <memory>
13 #include <string>
14 #include <string_view>
15 #include <vector>
16 
17 #include "base/containers/span.h"
18 #include "base/memory/raw_ptr.h"
19 #include "crypto/ec_private_key.h"
20 #include "net/base/completion_once_callback.h"
21 #include "net/base/host_mapping_rules.h"
22 #include "net/base/proxy_server.h"
23 #include "net/base/request_priority.h"
24 #include "net/base/test_completion_callback.h"
25 #include "net/cert/mock_cert_verifier.h"
26 #include "net/dns/mock_host_resolver.h"
27 #include "net/http/http_auth_handler_factory.h"
28 #include "net/http/http_network_session.h"
29 #include "net/http/http_response_info.h"
30 #include "net/http/http_server_properties.h"
31 #include "net/http/transport_security_state.h"
32 #include "net/proxy_resolution/proxy_resolution_service.h"
33 #include "net/quic/quic_crypto_client_stream_factory.h"
34 #include "net/socket/socket_test_util.h"
35 #include "net/spdy/spdy_session.h"
36 #include "net/spdy/spdy_session_pool.h"
37 #include "net/ssl/ssl_config_service_defaults.h"
38 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40 
41 #if BUILDFLAG(ENABLE_REPORTING)
42 #include "net/network_error_logging/network_error_logging_service.h"
43 #include "net/reporting/reporting_service.h"
44 #endif
45 
46 class GURL;
47 
48 namespace net {
49 
50 class ClientSocketFactory;
51 class HashValue;
52 class HostPortPair;
53 class HostResolver;
54 class QuicContext;
55 class HttpUserAgentSettings;
56 class NetLogWithSource;
57 class SpdySessionKey;
58 class SpdyStream;
59 class SpdyStreamRequest;
60 class TransportSecurityState;
61 class URLRequestContextBuilder;
62 class ProxyDelegate;
63 
64 // Default upload data used by both, mock objects and framer when creating
65 // data frames.
66 const char kDefaultUrl[] = "https://www.example.org/";
67 const char kUploadData[] = "hello!";
68 const int kUploadDataSize = std::size(kUploadData) - 1;
69 
70 // While HTTP/2 protocol defines default SETTINGS_MAX_HEADER_LIST_SIZE_FOR_TEST
71 // to be unlimited, BufferedSpdyFramer constructor requires a value.
72 const uint32_t kMaxHeaderListSizeForTest = 1024;
73 
74 // Chop a spdy::SpdySerializedFrame into an array of MockWrites.
75 // |frame| is the frame to chop.
76 // |num_chunks| is the number of chunks to create.
77 std::unique_ptr<MockWrite[]> ChopWriteFrame(
78     const spdy::SpdySerializedFrame& frame,
79     int num_chunks);
80 
81 // Adds headers and values to a map.
82 // |extra_headers| is an array of { name, value } pairs, arranged as strings
83 // where the even entries are the header names, and the odd entries are the
84 // header values.
85 // |headers| gets filled in from |extra_headers|.
86 void AppendToHeaderBlock(const char* const extra_headers[],
87                          int extra_header_count,
88                          spdy::Http2HeaderBlock* headers);
89 
90 // Create an async MockWrite from the given spdy::SpdySerializedFrame.
91 MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req);
92 
93 // Create an async MockWrite from the given spdy::SpdySerializedFrame and
94 // sequence number.
95 MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req, int seq);
96 
97 MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req,
98                           int seq,
99                           IoMode mode);
100 
101 // Create a MockRead from the given spdy::SpdySerializedFrame.
102 MockRead CreateMockRead(const spdy::SpdySerializedFrame& resp);
103 
104 // Create a MockRead from the given spdy::SpdySerializedFrame and sequence
105 // number.
106 MockRead CreateMockRead(const spdy::SpdySerializedFrame& resp, int seq);
107 
108 MockRead CreateMockRead(const spdy::SpdySerializedFrame& resp,
109                         int seq,
110                         IoMode mode);
111 
112 // Combines the given vector of spdy::SpdySerializedFrame into a single frame.
113 spdy::SpdySerializedFrame CombineFrames(
114     std::vector<const spdy::SpdySerializedFrame*> frames);
115 
116 // Returns the spdy::SpdyPriority embedded in the given frame.  Returns true
117 // and fills in |priority| on success.
118 bool GetSpdyPriority(const spdy::SpdySerializedFrame& frame,
119                      spdy::SpdyPriority* priority);
120 
121 // Tries to create a stream in |session| synchronously. Returns NULL
122 // on failure.
123 base::WeakPtr<SpdyStream> CreateStreamSynchronously(
124     SpdyStreamType type,
125     const base::WeakPtr<SpdySession>& session,
126     const GURL& url,
127     RequestPriority priority,
128     const NetLogWithSource& net_log,
129     bool detect_broken_connection = false,
130     base::TimeDelta heartbeat_interval = base::Seconds(0));
131 
132 // Helper class used by some tests to release a stream as soon as it's
133 // created.
134 class StreamReleaserCallback : public TestCompletionCallbackBase {
135  public:
136   StreamReleaserCallback();
137 
138   ~StreamReleaserCallback() override;
139 
140   // Returns a callback that releases |request|'s stream.
141   CompletionOnceCallback MakeCallback(SpdyStreamRequest* request);
142 
143  private:
144   void OnComplete(SpdyStreamRequest* request, int result);
145 };
146 
147 // Helper to manage the lifetimes of the dependencies for a
148 // HttpNetworkTransaction.
149 struct SpdySessionDependencies {
150   // Default set of dependencies -- "null" proxy service.
151   SpdySessionDependencies();
152 
153   // Custom proxy service dependency.
154   explicit SpdySessionDependencies(
155       std::unique_ptr<ProxyResolutionService> proxy_resolution_service);
156 
157   SpdySessionDependencies(SpdySessionDependencies&&);
158 
159   ~SpdySessionDependencies();
160 
161   SpdySessionDependencies& operator=(SpdySessionDependencies&&);
162 
GetHostResolverSpdySessionDependencies163   HostResolver* GetHostResolver() {
164     return alternate_host_resolver ? alternate_host_resolver.get()
165                                    : host_resolver.get();
166   }
167 
168   static std::unique_ptr<HttpNetworkSession> SpdyCreateSession(
169       SpdySessionDependencies* session_deps);
170 
171   // Variant that ignores session_deps->socket_factory, and uses the passed in
172   // |factory| instead.
173   static std::unique_ptr<HttpNetworkSession> SpdyCreateSessionWithSocketFactory(
174       SpdySessionDependencies* session_deps,
175       ClientSocketFactory* factory);
176   static HttpNetworkSessionParams CreateSessionParams(
177       SpdySessionDependencies* session_deps);
178   static HttpNetworkSessionContext CreateSessionContext(
179       SpdySessionDependencies* session_deps);
180 
181   // NOTE: host_resolver must be ordered before http_auth_handler_factory.
182   std::unique_ptr<MockHostResolverBase> host_resolver;
183   // For using a HostResolver not derived from MockHostResolverBase.
184   std::unique_ptr<HostResolver> alternate_host_resolver;
185   std::unique_ptr<MockCertVerifier> cert_verifier;
186   std::unique_ptr<TransportSecurityState> transport_security_state;
187   // NOTE: `proxy_delegate` must be ordered before `proxy_resolution_service`.
188   std::unique_ptr<ProxyDelegate> proxy_delegate;
189   std::unique_ptr<ProxyResolutionService> proxy_resolution_service;
190   std::unique_ptr<HttpUserAgentSettings> http_user_agent_settings;
191   std::unique_ptr<SSLConfigService> ssl_config_service;
192   std::unique_ptr<MockClientSocketFactory> socket_factory;
193   std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
194   std::unique_ptr<HttpServerProperties> http_server_properties;
195   std::unique_ptr<QuicContext> quic_context;
196   std::unique_ptr<QuicCryptoClientStreamFactory>
197       quic_crypto_client_stream_factory;
198 #if BUILDFLAG(ENABLE_REPORTING)
199   std::unique_ptr<ReportingService> reporting_service;
200   std::unique_ptr<NetworkErrorLoggingService> network_error_logging_service;
201 #endif
202   HostMappingRules host_mapping_rules;
203   bool enable_ip_pooling = true;
204   bool enable_ping = false;
205   bool enable_user_alternate_protocol_ports = false;
206   bool enable_quic = false;
207   bool enable_server_push_cancellation = false;
208   size_t session_max_recv_window_size = kDefaultInitialWindowSize;
209   int session_max_queued_capped_frames = kSpdySessionMaxQueuedCappedFrames;
210   spdy::SettingsMap http2_settings;
211   SpdySession::TimeFunc time_func;
212   bool enable_http2_alternative_service = false;
213   bool enable_http2_settings_grease = false;
214   std::optional<SpdySessionPool::GreasedHttp2Frame> greased_http2_frame;
215   bool http2_end_stream_with_data_frame = false;
216   raw_ptr<NetLog> net_log = nullptr;
217   bool disable_idle_sockets_close_on_memory_pressure = false;
218   bool enable_early_data = false;
219   bool key_auth_cache_server_entries_by_network_anonymization_key = false;
220   bool enable_priority_update = false;
221 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
222   bool go_away_on_ip_change = true;
223 #else
224   bool go_away_on_ip_change = false;
225 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
226   bool ignore_ip_address_changes = false;
227 };
228 
229 std::unique_ptr<URLRequestContextBuilder>
230 CreateSpdyTestURLRequestContextBuilder(
231     ClientSocketFactory* client_socket_factory);
232 
233 // Equivalent to pool->GetIfExists(spdy_session_key, NetLogWithSource()) !=
234 // NULL.
235 bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key);
236 
237 // Creates a SPDY session for the given key and puts it in the SPDY
238 // session pool in |http_session|. A SPDY session for |key| must not
239 // already exist.
240 base::WeakPtr<SpdySession> CreateSpdySession(HttpNetworkSession* http_session,
241                                              const SpdySessionKey& key,
242                                              const NetLogWithSource& net_log);
243 
244 // Like CreateSpdySession(), but does not fail if there is already an IP
245 // pooled session for |key|.
246 base::WeakPtr<SpdySession> CreateSpdySessionWithIpBasedPoolingDisabled(
247     HttpNetworkSession* http_session,
248     const SpdySessionKey& key,
249     const NetLogWithSource& net_log);
250 
251 // Creates a SPDY session for the given key and puts it in |pool|.
252 // The returned session will neither receive nor send any data.
253 // A SPDY session for |key| must not already exist.
254 base::WeakPtr<SpdySession> CreateFakeSpdySession(SpdySessionPool* pool,
255                                                  const SpdySessionKey& key);
256 
257 class SpdySessionPoolPeer {
258  public:
259   explicit SpdySessionPoolPeer(SpdySessionPool* pool);
260 
261   SpdySessionPoolPeer(const SpdySessionPoolPeer&) = delete;
262   SpdySessionPoolPeer& operator=(const SpdySessionPoolPeer&) = delete;
263 
264   void RemoveAliases(const SpdySessionKey& key);
265   void SetEnableSendingInitialData(bool enabled);
266 
267  private:
268   const raw_ptr<SpdySessionPool> pool_;
269 };
270 
271 class SpdyTestUtil {
272  public:
273   explicit SpdyTestUtil(bool use_priority_header = false);
274   ~SpdyTestUtil();
275 
276   // Add the appropriate headers to put |url| into |block|.
277   void AddUrlToHeaderBlock(std::string_view url,
278                            spdy::Http2HeaderBlock* headers) const;
279 
280   // Add the appropriate priority header if PriorityHeaders is enabled.
281   void AddPriorityToHeaderBlock(RequestPriority request_priority,
282                                 bool priority_incremental,
283                                 spdy::Http2HeaderBlock* headers) const;
284 
285   static spdy::Http2HeaderBlock ConstructGetHeaderBlock(std::string_view url);
286   static spdy::Http2HeaderBlock ConstructGetHeaderBlockForProxy(
287       std::string_view url);
288   static spdy::Http2HeaderBlock ConstructHeadHeaderBlock(
289       std::string_view url,
290       int64_t content_length);
291   static spdy::Http2HeaderBlock ConstructPostHeaderBlock(
292       std::string_view url,
293       int64_t content_length);
294   static spdy::Http2HeaderBlock ConstructPutHeaderBlock(std::string_view url,
295                                                         int64_t content_length);
296 
297   // Construct an expected SPDY reply string from the given headers.
298   std::string ConstructSpdyReplyString(
299       const spdy::Http2HeaderBlock& headers) const;
300 
301   // Construct an expected SPDY SETTINGS frame.
302   // |settings| are the settings to set.
303   // Returns the constructed frame.
304   spdy::SpdySerializedFrame ConstructSpdySettings(
305       const spdy::SettingsMap& settings);
306 
307   // Constructs an expected SPDY SETTINGS acknowledgement frame.
308   spdy::SpdySerializedFrame ConstructSpdySettingsAck();
309 
310   // Construct a SPDY PING frame.  Returns the constructed frame.
311   spdy::SpdySerializedFrame ConstructSpdyPing(uint32_t ping_id, bool is_ack);
312 
313   // Construct a SPDY GOAWAY frame with the specified last_good_stream_id.
314   // Returns the constructed frame.
315   spdy::SpdySerializedFrame ConstructSpdyGoAway(
316       spdy::SpdyStreamId last_good_stream_id);
317 
318   // Construct a SPDY GOAWAY frame with the specified last_good_stream_id,
319   // status, and description. Returns the constructed frame.
320   spdy::SpdySerializedFrame ConstructSpdyGoAway(
321       spdy::SpdyStreamId last_good_stream_id,
322       spdy::SpdyErrorCode error_code,
323       const std::string& desc);
324 
325   // Construct a SPDY WINDOW_UPDATE frame.  Returns the constructed frame.
326   spdy::SpdySerializedFrame ConstructSpdyWindowUpdate(
327       spdy::SpdyStreamId stream_id,
328       uint32_t delta_window_size);
329 
330   // Construct a SPDY RST_STREAM frame.  Returns the constructed frame.
331   spdy::SpdySerializedFrame ConstructSpdyRstStream(
332       spdy::SpdyStreamId stream_id,
333       spdy::SpdyErrorCode error_code);
334 
335   // Construct a PRIORITY frame. The weight is derived from |request_priority|.
336   // Returns the constructed frame.
337   spdy::SpdySerializedFrame ConstructSpdyPriority(
338       spdy::SpdyStreamId stream_id,
339       spdy::SpdyStreamId parent_stream_id,
340       RequestPriority request_priority,
341       bool exclusive);
342 
343   // Constructs a standard SPDY GET HEADERS frame for |url| with header
344   // compression.
345   // |extra_headers| are the extra header-value pairs, which typically
346   // will vary the most between calls.
347   spdy::SpdySerializedFrame ConstructSpdyGet(
348       const char* const url,
349       spdy::SpdyStreamId stream_id,
350       RequestPriority request_priority,
351       bool priority_incremental = kDefaultPriorityIncremental,
352       std::optional<RequestPriority> header_request_priority = std::nullopt);
353 
354   // Constructs a standard SPDY GET HEADERS frame with header compression.
355   // |extra_headers| are the extra header-value pairs, which typically
356   // will vary the most between calls.  If |direct| is false, the
357   // the full url will be used instead of simply the path.
358   spdy::SpdySerializedFrame ConstructSpdyGet(
359       const char* const extra_headers[],
360       int extra_header_count,
361       int stream_id,
362       RequestPriority request_priority,
363       bool priority_incremental = kDefaultPriorityIncremental,
364       std::optional<RequestPriority> header_request_priority = std::nullopt);
365 
366   // Constructs a SPDY HEADERS frame for a CONNECT request.
367   spdy::SpdySerializedFrame ConstructSpdyConnect(
368       const char* const extra_headers[],
369       int extra_header_count,
370       int stream_id,
371       RequestPriority priority,
372       const HostPortPair& host_port_pair);
373 
374   // Constructs a PUSH_PROMISE frame.
375   spdy::SpdySerializedFrame ConstructSpdyPushPromise(
376       spdy::SpdyStreamId associated_stream_id,
377       spdy::SpdyStreamId stream_id,
378       spdy::Http2HeaderBlock headers);
379 
380   // Constructs a HEADERS frame with the request header compression context with
381   // END_STREAM flag set to |fin|.
382   spdy::SpdySerializedFrame ConstructSpdyResponseHeaders(
383       int stream_id,
384       spdy::Http2HeaderBlock headers,
385       bool fin);
386 
387   // Construct a HEADERS frame carrying exactly the given headers and priority.
388   spdy::SpdySerializedFrame ConstructSpdyHeaders(
389       int stream_id,
390       spdy::Http2HeaderBlock headers,
391       RequestPriority priority,
392       bool fin,
393       bool priority_incremental = kDefaultPriorityIncremental,
394       std::optional<RequestPriority> header_request_priority = std::nullopt);
395 
396   // Construct a reply HEADERS frame carrying exactly the given headers and the
397   // default priority.
398   spdy::SpdySerializedFrame ConstructSpdyReply(int stream_id,
399                                                spdy::Http2HeaderBlock headers);
400 
401   // Constructs a standard SPDY HEADERS frame to match the SPDY GET.
402   // |extra_headers| are the extra header-value pairs, which typically
403   // will vary the most between calls.
404   spdy::SpdySerializedFrame ConstructSpdyGetReply(
405       const char* const extra_headers[],
406       int extra_header_count,
407       int stream_id);
408 
409   // Constructs a standard SPDY HEADERS frame with an Internal Server
410   // Error status code.
411   spdy::SpdySerializedFrame ConstructSpdyReplyError(int stream_id);
412 
413   // Constructs a standard SPDY HEADERS frame with the specified status code.
414   spdy::SpdySerializedFrame ConstructSpdyReplyError(
415       const char* const status,
416       const char* const* const extra_headers,
417       int extra_header_count,
418       int stream_id);
419 
420   // Constructs a standard SPDY POST HEADERS frame.
421   // |extra_headers| are the extra header-value pairs, which typically
422   // will vary the most between calls.
423   spdy::SpdySerializedFrame ConstructSpdyPost(
424       const char* url,
425       spdy::SpdyStreamId stream_id,
426       int64_t content_length,
427       RequestPriority request_priority,
428       const char* const extra_headers[],
429       int extra_header_count,
430       bool priority_incremental = kDefaultPriorityIncremental);
431 
432   // Constructs a chunked transfer SPDY POST HEADERS frame.
433   // |extra_headers| are the extra header-value pairs, which typically
434   // will vary the most between calls.
435   spdy::SpdySerializedFrame ConstructChunkedSpdyPost(
436       const char* const extra_headers[],
437       int extra_header_count,
438       RequestPriority request_priority = RequestPriority::DEFAULT_PRIORITY,
439       bool priority_incremental = kDefaultPriorityIncremental);
440 
441   // Constructs a standard SPDY HEADERS frame to match the SPDY POST.
442   // |extra_headers| are the extra header-value pairs, which typically
443   // will vary the most between calls.
444   spdy::SpdySerializedFrame ConstructSpdyPostReply(
445       const char* const extra_headers[],
446       int extra_header_count);
447 
448   // Constructs a single SPDY data frame with the contents "hello!"
449   spdy::SpdySerializedFrame ConstructSpdyDataFrame(int stream_id, bool fin);
450 
451   // Constructs a single SPDY data frame with the given content.
452   spdy::SpdySerializedFrame ConstructSpdyDataFrame(int stream_id,
453                                                    std::string_view data,
454                                                    bool fin);
455 
456   // Constructs a single SPDY data frame with the given content and padding.
457   spdy::SpdySerializedFrame ConstructSpdyDataFrame(int stream_id,
458                                                    std::string_view data,
459                                                    bool fin,
460                                                    int padding_length);
461 
462   // Wraps |frame| in the payload of a data frame in stream |stream_id|.
463   spdy::SpdySerializedFrame ConstructWrappedSpdyFrame(
464       const spdy::SpdySerializedFrame& frame,
465       int stream_id);
466 
467   // Serialize a spdy::SpdyFrameIR with |headerless_spdy_framer_|.
468   spdy::SpdySerializedFrame SerializeFrame(const spdy::SpdyFrameIR& frame_ir);
469 
470   // Called when necessary (when it will affect stream dependency specification
471   // when setting dependencies based on priorioties) to notify the utility
472   // class of stream destruction.
473   void UpdateWithStreamDestruction(int stream_id);
474 
set_default_url(const GURL & url)475   void set_default_url(const GURL& url) { default_url_ = url; }
476 
477  private:
478   // |content_length| may be NULL, in which case the content-length
479   // header will be omitted.
480   static spdy::Http2HeaderBlock ConstructHeaderBlock(std::string_view method,
481                                                      std::string_view url,
482                                                      int64_t* content_length);
483 
484   // Multiple SpdyFramers are required to keep track of header compression
485   // state.
486   // Use to serialize frames (request or response) without headers.
487   spdy::SpdyFramer headerless_spdy_framer_;
488   // Use to serialize request frames with headers.
489   spdy::SpdyFramer request_spdy_framer_;
490   // Use to serialize response frames with headers.
491   spdy::SpdyFramer response_spdy_framer_;
492 
493   GURL default_url_;
494 
495   // Enable support for addint the "priority" header to requests.
496   bool use_priority_header_;
497 
498   // Track a FIFO list of the stream_id of all created requests by priority.
499   std::map<int, std::vector<int>> priority_to_stream_id_list_;
500 };
501 
502 namespace test {
503 
504 // Returns a SHA1 HashValue in which each byte has the value |label|.
505 HashValue GetTestHashValue(uint8_t label);
506 
507 }  // namespace test
508 }  // namespace net
509 
510 #endif  // NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
511