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