1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
6 #define NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "crypto/ec_private_key.h"
14 #include "crypto/ec_signature_creator.h"
15 #include "net/base/completion_callback.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/cert/cert_verifier.h"
19 #include "net/dns/mock_host_resolver.h"
20 #include "net/http/http_auth_handler_factory.h"
21 #include "net/http/http_network_session.h"
22 #include "net/http/http_response_info.h"
23 #include "net/http/http_server_properties_impl.h"
24 #include "net/http/transport_security_state.h"
25 #include "net/proxy/proxy_service.h"
26 #include "net/socket/next_proto.h"
27 #include "net/socket/socket_test_util.h"
28 #include "net/spdy/spdy_protocol.h"
29 #include "net/ssl/ssl_config_service_defaults.h"
30 #include "net/url_request/url_request_context.h"
31 #include "net/url_request/url_request_context_storage.h"
32 #include "testing/gtest/include/gtest/gtest.h"
41 class SpdySessionPool;
43 class SpdyStreamRequest;
45 // Default upload data used by both, mock objects and framer when creating
47 const char kDefaultURL[] = "http://www.google.com";
48 const char kUploadData[] = "hello!";
49 const int kUploadDataSize = arraysize(kUploadData)-1;
51 // SpdyNextProtos returns a vector of next protocols for negotiating
53 std::vector<NextProto> SpdyNextProtos();
55 // Chop a frame into an array of MockWrites.
56 // |data| is the frame to chop.
57 // |length| is the length of the frame to chop.
58 // |num_chunks| is the number of chunks to create.
59 MockWrite* ChopWriteFrame(const char* data, int length, int num_chunks);
61 // Chop a SpdyFrame into an array of MockWrites.
62 // |frame| is the frame to chop.
63 // |num_chunks| is the number of chunks to create.
64 MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks);
66 // Chop a frame into an array of MockReads.
67 // |data| is the frame to chop.
68 // |length| is the length of the frame to chop.
69 // |num_chunks| is the number of chunks to create.
70 MockRead* ChopReadFrame(const char* data, int length, int num_chunks);
72 // Chop a SpdyFrame into an array of MockReads.
73 // |frame| is the frame to chop.
74 // |num_chunks| is the number of chunks to create.
75 MockRead* ChopReadFrame(const SpdyFrame& frame, int num_chunks);
77 // Adds headers and values to a map.
78 // |extra_headers| is an array of { name, value } pairs, arranged as strings
79 // where the even entries are the header names, and the odd entries are the
81 // |headers| gets filled in from |extra_headers|.
82 void AppendToHeaderBlock(const char* const extra_headers[],
83 int extra_header_count,
84 SpdyHeaderBlock* headers);
86 // Create an async MockWrite from the given SpdyFrame.
87 MockWrite CreateMockWrite(const SpdyFrame& req);
89 // Create an async MockWrite from the given SpdyFrame and sequence number.
90 MockWrite CreateMockWrite(const SpdyFrame& req, int seq);
92 MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode);
94 // Create a MockRead from the given SpdyFrame.
95 MockRead CreateMockRead(const SpdyFrame& resp);
97 // Create a MockRead from the given SpdyFrame and sequence number.
98 MockRead CreateMockRead(const SpdyFrame& resp, int seq);
100 MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode);
102 // Combines the given SpdyFrames into the given char array and returns
104 int CombineFrames(const SpdyFrame** frames, int num_frames,
105 char* buff, int buff_len);
107 // Returns the SpdyPriority embedded in the given frame. Returns true
108 // and fills in |priority| on success.
109 bool GetSpdyPriority(SpdyMajorVersion version,
110 const SpdyFrame& frame,
111 SpdyPriority* priority);
113 // Tries to create a stream in |session| synchronously. Returns NULL
115 base::WeakPtr<SpdyStream> CreateStreamSynchronously(
117 const base::WeakPtr<SpdySession>& session,
119 RequestPriority priority,
120 const BoundNetLog& net_log);
122 // Helper class used by some tests to release a stream as soon as it's
124 class StreamReleaserCallback : public TestCompletionCallbackBase {
126 StreamReleaserCallback();
128 virtual ~StreamReleaserCallback();
130 // Returns a callback that releases |request|'s stream.
131 CompletionCallback MakeCallback(SpdyStreamRequest* request);
134 void OnComplete(SpdyStreamRequest* request, int result);
137 const size_t kSpdyCredentialSlotUnused = 0;
139 // This struct holds information used to construct spdy control and data frames.
140 struct SpdyHeaderInfo {
143 SpdyStreamId assoc_id;
144 SpdyPriority priority;
145 size_t credential_slot; // SPDY3 only
146 SpdyControlFlags control_flags;
148 SpdyRstStreamStatus status;
151 SpdyDataFlags data_flags;
154 // An ECSignatureCreator that returns deterministic signatures.
155 class MockECSignatureCreator : public crypto::ECSignatureCreator {
157 explicit MockECSignatureCreator(crypto::ECPrivateKey* key);
159 // crypto::ECSignatureCreator
160 virtual bool Sign(const uint8* data,
162 std::vector<uint8>* signature) OVERRIDE;
163 virtual bool DecodeSignature(const std::vector<uint8>& signature,
164 std::vector<uint8>* out_raw_sig) OVERRIDE;
167 crypto::ECPrivateKey* key_;
169 DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreator);
172 // An ECSignatureCreatorFactory creates MockECSignatureCreator.
173 class MockECSignatureCreatorFactory : public crypto::ECSignatureCreatorFactory {
175 MockECSignatureCreatorFactory();
176 virtual ~MockECSignatureCreatorFactory();
178 // crypto::ECSignatureCreatorFactory
179 virtual crypto::ECSignatureCreator* Create(
180 crypto::ECPrivateKey* key) OVERRIDE;
183 DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreatorFactory);
186 // Helper to manage the lifetimes of the dependencies for a
187 // HttpNetworkTransaction.
188 struct SpdySessionDependencies {
189 // Default set of dependencies -- "null" proxy service.
190 explicit SpdySessionDependencies(NextProto protocol);
192 // Custom proxy service dependency.
193 SpdySessionDependencies(NextProto protocol, ProxyService* proxy_service);
195 ~SpdySessionDependencies();
197 static HttpNetworkSession* SpdyCreateSession(
198 SpdySessionDependencies* session_deps);
199 static HttpNetworkSession* SpdyCreateSessionDeterministic(
200 SpdySessionDependencies* session_deps);
201 static HttpNetworkSession::Params CreateSessionParams(
202 SpdySessionDependencies* session_deps);
204 // NOTE: host_resolver must be ordered before http_auth_handler_factory.
205 scoped_ptr<MockHostResolverBase> host_resolver;
206 scoped_ptr<CertVerifier> cert_verifier;
207 scoped_ptr<TransportSecurityState> transport_security_state;
208 scoped_ptr<ProxyService> proxy_service;
209 scoped_refptr<SSLConfigService> ssl_config_service;
210 scoped_ptr<MockClientSocketFactory> socket_factory;
211 scoped_ptr<DeterministicMockClientSocketFactory> deterministic_socket_factory;
212 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
213 HttpServerPropertiesImpl http_server_properties;
214 bool enable_ip_pooling;
215 bool enable_compression;
217 bool enable_user_alternate_protocol_ports;
219 size_t stream_initial_recv_window_size;
220 SpdySession::TimeFunc time_func;
221 std::string trusted_spdy_proxy;
225 class SpdyURLRequestContext : public URLRequestContext {
227 explicit SpdyURLRequestContext(NextProto protocol);
228 virtual ~SpdyURLRequestContext();
230 MockClientSocketFactory& socket_factory() { return socket_factory_; }
233 MockClientSocketFactory socket_factory_;
234 net::URLRequestContextStorage storage_;
237 // Equivalent to pool->GetIfExists(spdy_session_key, BoundNetLog()) != NULL.
238 bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key);
240 // Creates a SPDY session for the given key and puts it in the SPDY
241 // session pool in |http_session|. A SPDY session for |key| must not
243 base::WeakPtr<SpdySession> CreateInsecureSpdySession(
244 const scoped_refptr<HttpNetworkSession>& http_session,
245 const SpdySessionKey& key,
246 const BoundNetLog& net_log);
248 // Tries to create a SPDY session for the given key but expects the
249 // attempt to fail with the given error. A SPDY session for |key| must
250 // not already exist.
251 void TryCreateInsecureSpdySessionExpectingFailure(
252 const scoped_refptr<HttpNetworkSession>& http_session,
253 const SpdySessionKey& key,
254 Error expected_error,
255 const BoundNetLog& net_log);
257 // Like CreateInsecureSpdySession(), but uses TLS.
258 base::WeakPtr<SpdySession> CreateSecureSpdySession(
259 const scoped_refptr<HttpNetworkSession>& http_session,
260 const SpdySessionKey& key,
261 const BoundNetLog& net_log);
263 // Creates an insecure SPDY session for the given key and puts it in
264 // |pool|. The returned session will neither receive nor send any
265 // data. A SPDY session for |key| must not already exist.
266 base::WeakPtr<SpdySession> CreateFakeSpdySession(SpdySessionPool* pool,
267 const SpdySessionKey& key);
269 // Tries to create an insecure SPDY session for the given key but
270 // expects the attempt to fail with the given error. The session will
271 // neither receive nor send any data. A SPDY session for |key| must
272 // not already exist.
273 void TryCreateFakeSpdySessionExpectingFailure(SpdySessionPool* pool,
274 const SpdySessionKey& key,
275 Error expected_error);
277 class SpdySessionPoolPeer {
279 explicit SpdySessionPoolPeer(SpdySessionPool* pool);
281 void RemoveAliases(const SpdySessionKey& key);
282 void DisableDomainAuthenticationVerification();
283 void SetEnableSendingInitialData(bool enabled);
286 SpdySessionPool* const pool_;
288 DISALLOW_COPY_AND_ASSIGN(SpdySessionPoolPeer);
293 explicit SpdyTestUtil(NextProto protocol);
295 // Add the appropriate headers to put |url| into |block|.
296 void AddUrlToHeaderBlock(base::StringPiece url,
297 SpdyHeaderBlock* headers) const;
299 scoped_ptr<SpdyHeaderBlock> ConstructGetHeaderBlock(
300 base::StringPiece url) const;
301 scoped_ptr<SpdyHeaderBlock> ConstructGetHeaderBlockForProxy(
302 base::StringPiece url) const;
303 scoped_ptr<SpdyHeaderBlock> ConstructHeadHeaderBlock(
304 base::StringPiece url,
305 int64 content_length) const;
306 scoped_ptr<SpdyHeaderBlock> ConstructPostHeaderBlock(
307 base::StringPiece url,
308 int64 content_length) const;
309 scoped_ptr<SpdyHeaderBlock> ConstructPutHeaderBlock(
310 base::StringPiece url,
311 int64 content_length) const;
313 // Construct a SPDY frame. If it is a SYN_STREAM or SYN_REPLY frame (as
314 // specified in header_info.kind), the provided headers are included in the
316 SpdyFrame* ConstructSpdyFrame(
317 const SpdyHeaderInfo& header_info,
318 scoped_ptr<SpdyHeaderBlock> headers) const;
320 // Construct a SPDY frame. If it is a SYN_STREAM or SYN_REPLY frame (as
321 // specified in header_info.kind), the headers provided in extra_headers and
322 // (if non-NULL) tail_headers are concatenated and included in the frame.
323 // (extra_headers must always be non-NULL.)
324 SpdyFrame* ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
325 const char* const extra_headers[],
326 int extra_header_count,
327 const char* const tail_headers[],
328 int tail_header_count) const;
330 // Construct a generic SpdyControlFrame.
331 SpdyFrame* ConstructSpdyControlFrame(
332 scoped_ptr<SpdyHeaderBlock> headers,
334 SpdyStreamId stream_id,
335 RequestPriority request_priority,
337 SpdyControlFlags flags,
338 SpdyStreamId associated_stream_id) const;
340 // Construct a generic SpdyControlFrame.
342 // Warning: extra_header_count is the number of header-value pairs in
343 // extra_headers (so half the number of elements), but tail_headers_size is
344 // the actual number of elements (both keys and values) in tail_headers.
345 // TODO(ttuttle): Fix this inconsistency.
346 SpdyFrame* ConstructSpdyControlFrame(
347 const char* const extra_headers[],
348 int extra_header_count,
350 SpdyStreamId stream_id,
351 RequestPriority request_priority,
353 SpdyControlFlags flags,
354 const char* const* tail_headers,
355 int tail_headers_size,
356 SpdyStreamId associated_stream_id) const;
358 // Construct an expected SPDY reply string from the given headers.
359 std::string ConstructSpdyReplyString(const SpdyHeaderBlock& headers) const;
361 // Construct an expected SPDY SETTINGS frame.
362 // |settings| are the settings to set.
363 // Returns the constructed frame. The caller takes ownership of the frame.
364 SpdyFrame* ConstructSpdySettings(const SettingsMap& settings) const;
366 // Construct an expected SPDY CREDENTIAL frame.
367 // |credential| is the credential to send.
368 // Returns the constructed frame. The caller takes ownership of the frame.
369 SpdyFrame* ConstructSpdyCredential(const SpdyCredential& credential) const;
371 // Construct a SPDY PING frame.
372 // Returns the constructed frame. The caller takes ownership of the frame.
373 SpdyFrame* ConstructSpdyPing(uint32 ping_id) const;
375 // Construct a SPDY GOAWAY frame with last_good_stream_id = 0.
376 // Returns the constructed frame. The caller takes ownership of the frame.
377 SpdyFrame* ConstructSpdyGoAway() const;
379 // Construct a SPDY GOAWAY frame with the specified last_good_stream_id.
380 // Returns the constructed frame. The caller takes ownership of the frame.
381 SpdyFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id) const;
383 // Construct a SPDY WINDOW_UPDATE frame.
384 // Returns the constructed frame. The caller takes ownership of the frame.
385 SpdyFrame* ConstructSpdyWindowUpdate(
386 SpdyStreamId stream_id,
387 uint32 delta_window_size) const;
389 // Construct a SPDY RST_STREAM frame.
390 // Returns the constructed frame. The caller takes ownership of the frame.
391 SpdyFrame* ConstructSpdyRstStream(SpdyStreamId stream_id,
392 SpdyRstStreamStatus status) const;
394 // Constructs a standard SPDY GET SYN frame, optionally compressed
395 // for the url |url|.
396 // |extra_headers| are the extra header-value pairs, which typically
397 // will vary the most between calls.
398 // Returns a SpdyFrame.
399 SpdyFrame* ConstructSpdyGet(const char* const url,
401 SpdyStreamId stream_id,
402 RequestPriority request_priority) const;
404 SpdyFrame* ConstructSpdyGetForProxy(const char* const url,
406 SpdyStreamId stream_id,
407 RequestPriority request_priority) const;
409 // Constructs a standard SPDY GET SYN frame, optionally compressed.
410 // |extra_headers| are the extra header-value pairs, which typically
411 // will vary the most between calls. If |direct| is false, the
412 // the full url will be used instead of simply the path.
413 // Returns a SpdyFrame.
414 SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
415 int extra_header_count,
418 RequestPriority request_priority,
421 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
422 SpdyFrame* ConstructSpdyConnect(const char* const extra_headers[],
423 int extra_header_count,
425 RequestPriority priority) const;
427 // Constructs a standard SPDY push SYN frame.
428 // |extra_headers| are the extra header-value pairs, which typically
429 // will vary the most between calls.
430 // Returns a SpdyFrame.
431 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
432 int extra_header_count,
434 int associated_stream_id,
436 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
437 int extra_header_count,
439 int associated_stream_id,
442 const char* location);
444 SpdyFrame* ConstructSpdyPushHeaders(int stream_id,
445 const char* const extra_headers[],
446 int extra_header_count);
448 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY GET.
449 // |extra_headers| are the extra header-value pairs, which typically
450 // will vary the most between calls.
451 // Returns a SpdyFrame.
452 SpdyFrame* ConstructSpdyGetSynReply(const char* const extra_headers[],
453 int extra_header_count,
456 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY GET.
457 // |extra_headers| are the extra header-value pairs, which typically
458 // will vary the most between calls.
459 // Returns a SpdyFrame.
460 SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id);
462 // Constructs a standard SPDY SYN_REPLY frame with an Internal Server
463 // Error status code.
464 // Returns a SpdyFrame.
465 SpdyFrame* ConstructSpdySynReplyError(int stream_id);
467 // Constructs a standard SPDY SYN_REPLY frame with the specified status code.
468 // Returns a SpdyFrame.
469 SpdyFrame* ConstructSpdySynReplyError(const char* const status,
470 const char* const* const extra_headers,
471 int extra_header_count,
474 // Constructs a standard SPDY POST SYN frame.
475 // |extra_headers| are the extra header-value pairs, which typically
476 // will vary the most between calls.
477 // Returns a SpdyFrame.
478 SpdyFrame* ConstructSpdyPost(const char* url,
479 SpdyStreamId stream_id,
480 int64 content_length,
481 RequestPriority priority,
482 const char* const extra_headers[],
483 int extra_header_count);
485 // Constructs a chunked transfer SPDY POST SYN frame.
486 // |extra_headers| are the extra header-value pairs, which typically
487 // will vary the most between calls.
488 // Returns a SpdyFrame.
489 SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[],
490 int extra_header_count);
492 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY POST.
493 // |extra_headers| are the extra header-value pairs, which typically
494 // will vary the most between calls.
495 // Returns a SpdyFrame.
496 SpdyFrame* ConstructSpdyPostSynReply(const char* const extra_headers[],
497 int extra_header_count);
499 // Constructs a single SPDY data frame with the contents "hello!"
500 SpdyFrame* ConstructSpdyBodyFrame(int stream_id,
503 // Constructs a single SPDY data frame with the given content.
504 SpdyFrame* ConstructSpdyBodyFrame(int stream_id, const char* data,
505 uint32 len, bool fin);
507 // Wraps |frame| in the payload of a data frame in stream |stream_id|.
508 SpdyFrame* ConstructWrappedSpdyFrame(const scoped_ptr<SpdyFrame>& frame,
511 const SpdyHeaderInfo MakeSpdyHeader(SpdyFrameType type);
513 NextProto protocol() const { return protocol_; }
514 SpdyMajorVersion spdy_version() const { return spdy_version_; }
515 bool is_spdy2() const { return protocol_ < kProtoSPDY3; }
516 scoped_ptr<SpdyFramer> CreateFramer() const;
518 const char* GetMethodKey() const;
519 const char* GetStatusKey() const;
520 const char* GetHostKey() const;
521 const char* GetSchemeKey() const;
522 const char* GetVersionKey() const;
523 const char* GetPathKey() const;
526 // |content_length| may be NULL, in which case the content-length
527 // header will be omitted.
528 scoped_ptr<SpdyHeaderBlock> ConstructHeaderBlock(
529 base::StringPiece method,
530 base::StringPiece url,
531 int64* content_length) const;
533 const NextProto protocol_;
534 const SpdyMajorVersion spdy_version_;
539 #endif // NET_SPDY_SPDY_TEST_UTIL_COMMON_H_