Add more WeakPtr checks for SurfaceFactory in SurfaceAggregator.
[chromium-blink-merge.git] / net / spdy / spdy_test_util_common.cc
blobbaa3548f16d59df9883392e938aa9cdf0e72c48a
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 #include "net/spdy/spdy_test_util_common.h"
7 #include <cstddef>
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h"
13 #include "net/cert/mock_cert_verifier.h"
14 #include "net/http/http_cache.h"
15 #include "net/http/http_network_session.h"
16 #include "net/http/http_network_transaction.h"
17 #include "net/http/http_server_properties_impl.h"
18 #include "net/socket/socket_test_util.h"
19 #include "net/socket/ssl_client_socket.h"
20 #include "net/socket/transport_client_socket_pool.h"
21 #include "net/spdy/buffered_spdy_framer.h"
22 #include "net/spdy/spdy_framer.h"
23 #include "net/spdy/spdy_http_utils.h"
24 #include "net/spdy/spdy_session.h"
25 #include "net/spdy/spdy_session_pool.h"
26 #include "net/spdy/spdy_stream.h"
27 #include "net/url_request/url_request_job_factory_impl.h"
29 namespace net {
31 namespace {
33 bool next_proto_is_spdy(NextProto next_proto) {
34 return next_proto >= kProtoSPDYMinimumVersion &&
35 next_proto <= kProtoSPDYMaximumVersion;
38 // Parses a URL into the scheme, host, and path components required for a
39 // SPDY request.
40 void ParseUrl(base::StringPiece url, std::string* scheme, std::string* host,
41 std::string* path) {
42 GURL gurl(url.as_string());
43 path->assign(gurl.PathForRequest());
44 scheme->assign(gurl.scheme());
45 host->assign(gurl.host());
46 if (gurl.has_port()) {
47 host->append(":");
48 host->append(gurl.port());
52 } // namespace
54 NextProtoVector SpdyNextProtos() {
55 NextProtoVector next_protos;
56 next_protos.push_back(kProtoHTTP11);
57 next_protos.push_back(kProtoDeprecatedSPDY2);
58 next_protos.push_back(kProtoSPDY3);
59 next_protos.push_back(kProtoSPDY31);
60 next_protos.push_back(kProtoSPDY4);
61 next_protos.push_back(kProtoQUIC1SPDY3);
62 return next_protos;
65 // Chop a frame into an array of MockWrites.
66 // |data| is the frame to chop.
67 // |length| is the length of the frame to chop.
68 // |num_chunks| is the number of chunks to create.
69 MockWrite* ChopWriteFrame(const char* data, int length, int num_chunks) {
70 MockWrite* chunks = new MockWrite[num_chunks];
71 int chunk_size = length / num_chunks;
72 for (int index = 0; index < num_chunks; index++) {
73 const char* ptr = data + (index * chunk_size);
74 if (index == num_chunks - 1)
75 chunk_size += length % chunk_size; // The last chunk takes the remainder.
76 chunks[index] = MockWrite(ASYNC, ptr, chunk_size);
78 return chunks;
81 // Chop a SpdyFrame into an array of MockWrites.
82 // |frame| is the frame to chop.
83 // |num_chunks| is the number of chunks to create.
84 MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks) {
85 return ChopWriteFrame(frame.data(), frame.size(), num_chunks);
88 // Chop a frame into an array of MockReads.
89 // |data| is the frame to chop.
90 // |length| is the length of the frame to chop.
91 // |num_chunks| is the number of chunks to create.
92 MockRead* ChopReadFrame(const char* data, int length, int num_chunks) {
93 MockRead* chunks = new MockRead[num_chunks];
94 int chunk_size = length / num_chunks;
95 for (int index = 0; index < num_chunks; index++) {
96 const char* ptr = data + (index * chunk_size);
97 if (index == num_chunks - 1)
98 chunk_size += length % chunk_size; // The last chunk takes the remainder.
99 chunks[index] = MockRead(ASYNC, ptr, chunk_size);
101 return chunks;
104 // Chop a SpdyFrame into an array of MockReads.
105 // |frame| is the frame to chop.
106 // |num_chunks| is the number of chunks to create.
107 MockRead* ChopReadFrame(const SpdyFrame& frame, int num_chunks) {
108 return ChopReadFrame(frame.data(), frame.size(), num_chunks);
111 // Adds headers and values to a map.
112 // |extra_headers| is an array of { name, value } pairs, arranged as strings
113 // where the even entries are the header names, and the odd entries are the
114 // header values.
115 // |headers| gets filled in from |extra_headers|.
116 void AppendToHeaderBlock(const char* const extra_headers[],
117 int extra_header_count,
118 SpdyHeaderBlock* headers) {
119 std::string this_header;
120 std::string this_value;
122 if (!extra_header_count)
123 return;
125 // Sanity check: Non-NULL header list.
126 DCHECK(NULL != extra_headers) << "NULL header value pair list";
127 // Sanity check: Non-NULL header map.
128 DCHECK(NULL != headers) << "NULL header map";
129 // Copy in the headers.
130 for (int i = 0; i < extra_header_count; i++) {
131 // Sanity check: Non-empty header.
132 DCHECK_NE('\0', *extra_headers[i * 2]) << "Empty header value pair";
133 this_header = extra_headers[i * 2];
134 std::string::size_type header_len = this_header.length();
135 if (!header_len)
136 continue;
137 this_value = extra_headers[1 + (i * 2)];
138 std::string new_value;
139 if (headers->find(this_header) != headers->end()) {
140 // More than one entry in the header.
141 // Don't add the header again, just the append to the value,
142 // separated by a NULL character.
144 // Adjust the value.
145 new_value = (*headers)[this_header];
146 // Put in a NULL separator.
147 new_value.append(1, '\0');
148 // Append the new value.
149 new_value += this_value;
150 } else {
151 // Not a duplicate, just write the value.
152 new_value = this_value;
154 (*headers)[this_header] = new_value;
158 // Create a MockWrite from the given SpdyFrame.
159 MockWrite CreateMockWrite(const SpdyFrame& req) {
160 return MockWrite(ASYNC, req.data(), req.size());
163 // Create a MockWrite from the given SpdyFrame and sequence number.
164 MockWrite CreateMockWrite(const SpdyFrame& req, int seq) {
165 return CreateMockWrite(req, seq, ASYNC);
168 // Create a MockWrite from the given SpdyFrame and sequence number.
169 MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode) {
170 return MockWrite(mode, req.data(), req.size(), seq);
173 // Create a MockRead from the given SpdyFrame.
174 MockRead CreateMockRead(const SpdyFrame& resp) {
175 return MockRead(ASYNC, resp.data(), resp.size());
178 // Create a MockRead from the given SpdyFrame and sequence number.
179 MockRead CreateMockRead(const SpdyFrame& resp, int seq) {
180 return CreateMockRead(resp, seq, ASYNC);
183 // Create a MockRead from the given SpdyFrame and sequence number.
184 MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode) {
185 return MockRead(mode, resp.data(), resp.size(), seq);
188 // Combines the given SpdyFrames into the given char array and returns
189 // the total length.
190 int CombineFrames(const SpdyFrame** frames, int num_frames,
191 char* buff, int buff_len) {
192 int total_len = 0;
193 for (int i = 0; i < num_frames; ++i) {
194 total_len += frames[i]->size();
196 DCHECK_LE(total_len, buff_len);
197 char* ptr = buff;
198 for (int i = 0; i < num_frames; ++i) {
199 int len = frames[i]->size();
200 memcpy(ptr, frames[i]->data(), len);
201 ptr += len;
203 return total_len;
206 namespace {
208 class PriorityGetter : public BufferedSpdyFramerVisitorInterface {
209 public:
210 PriorityGetter() : priority_(0) {}
211 ~PriorityGetter() override {}
213 SpdyPriority priority() const {
214 return priority_;
217 void OnError(SpdyFramer::SpdyError error_code) override {}
218 void OnStreamError(SpdyStreamId stream_id,
219 const std::string& description) override {}
220 void OnSynStream(SpdyStreamId stream_id,
221 SpdyStreamId associated_stream_id,
222 SpdyPriority priority,
223 bool fin,
224 bool unidirectional,
225 const SpdyHeaderBlock& headers) override {
226 priority_ = priority;
228 void OnSynReply(SpdyStreamId stream_id,
229 bool fin,
230 const SpdyHeaderBlock& headers) override {}
231 void OnHeaders(SpdyStreamId stream_id,
232 bool fin,
233 const SpdyHeaderBlock& headers) override {}
234 void OnDataFrameHeader(SpdyStreamId stream_id,
235 size_t length,
236 bool fin) override {}
237 void OnStreamFrameData(SpdyStreamId stream_id,
238 const char* data,
239 size_t len,
240 bool fin) override {}
241 void OnSettings(bool clear_persisted) override {}
242 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {}
243 void OnPing(SpdyPingId unique_id, bool is_ack) override {}
244 void OnRstStream(SpdyStreamId stream_id,
245 SpdyRstStreamStatus status) override {}
246 void OnGoAway(SpdyStreamId last_accepted_stream_id,
247 SpdyGoAwayStatus status) override {}
248 void OnWindowUpdate(SpdyStreamId stream_id,
249 uint32 delta_window_size) override {}
250 void OnPushPromise(SpdyStreamId stream_id,
251 SpdyStreamId promised_stream_id,
252 const SpdyHeaderBlock& headers) override {}
253 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
254 return false;
257 private:
258 SpdyPriority priority_;
261 } // namespace
263 bool GetSpdyPriority(SpdyMajorVersion version,
264 const SpdyFrame& frame,
265 SpdyPriority* priority) {
266 BufferedSpdyFramer framer(version, false);
267 PriorityGetter priority_getter;
268 framer.set_visitor(&priority_getter);
269 size_t frame_size = frame.size();
270 if (framer.ProcessInput(frame.data(), frame_size) != frame_size) {
271 return false;
273 *priority = priority_getter.priority();
274 return true;
277 base::WeakPtr<SpdyStream> CreateStreamSynchronously(
278 SpdyStreamType type,
279 const base::WeakPtr<SpdySession>& session,
280 const GURL& url,
281 RequestPriority priority,
282 const BoundNetLog& net_log) {
283 SpdyStreamRequest stream_request;
284 int rv = stream_request.StartRequest(type, session, url, priority, net_log,
285 CompletionCallback());
286 return
287 (rv == OK) ? stream_request.ReleaseStream() : base::WeakPtr<SpdyStream>();
290 StreamReleaserCallback::StreamReleaserCallback() {}
292 StreamReleaserCallback::~StreamReleaserCallback() {}
294 CompletionCallback StreamReleaserCallback::MakeCallback(
295 SpdyStreamRequest* request) {
296 return base::Bind(&StreamReleaserCallback::OnComplete,
297 base::Unretained(this),
298 request);
301 void StreamReleaserCallback::OnComplete(
302 SpdyStreamRequest* request, int result) {
303 if (result == OK)
304 request->ReleaseStream()->Cancel();
305 SetResult(result);
308 MockECSignatureCreator::MockECSignatureCreator(crypto::ECPrivateKey* key)
309 : key_(key) {
312 bool MockECSignatureCreator::Sign(const uint8* data,
313 int data_len,
314 std::vector<uint8>* signature) {
315 std::vector<uint8> private_key_value;
316 key_->ExportValue(&private_key_value);
317 std::string head = "fakesignature";
318 std::string tail = "/fakesignature";
320 signature->clear();
321 signature->insert(signature->end(), head.begin(), head.end());
322 signature->insert(signature->end(), private_key_value.begin(),
323 private_key_value.end());
324 signature->insert(signature->end(), '-');
325 signature->insert(signature->end(), data, data + data_len);
326 signature->insert(signature->end(), tail.begin(), tail.end());
327 return true;
330 bool MockECSignatureCreator::DecodeSignature(
331 const std::vector<uint8>& signature,
332 std::vector<uint8>* out_raw_sig) {
333 *out_raw_sig = signature;
334 return true;
337 MockECSignatureCreatorFactory::MockECSignatureCreatorFactory() {
338 crypto::ECSignatureCreator::SetFactoryForTesting(this);
341 MockECSignatureCreatorFactory::~MockECSignatureCreatorFactory() {
342 crypto::ECSignatureCreator::SetFactoryForTesting(NULL);
345 crypto::ECSignatureCreator* MockECSignatureCreatorFactory::Create(
346 crypto::ECPrivateKey* key) {
347 return new MockECSignatureCreator(key);
350 SpdySessionDependencies::SpdySessionDependencies(NextProto protocol)
351 : host_resolver(new MockCachingHostResolver),
352 cert_verifier(new MockCertVerifier),
353 transport_security_state(new TransportSecurityState),
354 proxy_service(ProxyService::CreateDirect()),
355 ssl_config_service(new SSLConfigServiceDefaults),
356 socket_factory(new MockClientSocketFactory),
357 deterministic_socket_factory(new DeterministicMockClientSocketFactory),
358 http_auth_handler_factory(
359 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
360 enable_ip_pooling(true),
361 enable_compression(false),
362 enable_ping(false),
363 enable_user_alternate_protocol_ports(false),
364 protocol(protocol),
365 stream_initial_recv_window_size(kSpdyStreamInitialWindowSize),
366 time_func(&base::TimeTicks::Now),
367 force_spdy_over_ssl(false),
368 force_spdy_always(false),
369 use_alternate_protocols(false),
370 enable_websocket_over_spdy(false),
371 net_log(NULL) {
372 DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
374 // Note: The CancelledTransaction test does cleanup by running all
375 // tasks in the message loop (RunAllPending). Unfortunately, that
376 // doesn't clean up tasks on the host resolver thread; and
377 // TCPConnectJob is currently not cancellable. Using synchronous
378 // lookups allows the test to shutdown cleanly. Until we have
379 // cancellable TCPConnectJobs, use synchronous lookups.
380 host_resolver->set_synchronous_mode(true);
383 SpdySessionDependencies::SpdySessionDependencies(
384 NextProto protocol, ProxyService* proxy_service)
385 : host_resolver(new MockHostResolver),
386 cert_verifier(new MockCertVerifier),
387 transport_security_state(new TransportSecurityState),
388 proxy_service(proxy_service),
389 ssl_config_service(new SSLConfigServiceDefaults),
390 socket_factory(new MockClientSocketFactory),
391 deterministic_socket_factory(new DeterministicMockClientSocketFactory),
392 http_auth_handler_factory(
393 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
394 enable_ip_pooling(true),
395 enable_compression(false),
396 enable_ping(false),
397 enable_user_alternate_protocol_ports(false),
398 protocol(protocol),
399 stream_initial_recv_window_size(kSpdyStreamInitialWindowSize),
400 time_func(&base::TimeTicks::Now),
401 force_spdy_over_ssl(false),
402 force_spdy_always(false),
403 use_alternate_protocols(false),
404 enable_websocket_over_spdy(false),
405 net_log(NULL) {
406 DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
409 SpdySessionDependencies::~SpdySessionDependencies() {}
411 // static
412 HttpNetworkSession* SpdySessionDependencies::SpdyCreateSession(
413 SpdySessionDependencies* session_deps) {
414 net::HttpNetworkSession::Params params = CreateSessionParams(session_deps);
415 params.client_socket_factory = session_deps->socket_factory.get();
416 HttpNetworkSession* http_session = new HttpNetworkSession(params);
417 SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool());
418 pool_peer.SetEnableSendingInitialData(false);
419 return http_session;
422 // static
423 HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
424 SpdySessionDependencies* session_deps) {
425 net::HttpNetworkSession::Params params = CreateSessionParams(session_deps);
426 params.client_socket_factory =
427 session_deps->deterministic_socket_factory.get();
428 HttpNetworkSession* http_session = new HttpNetworkSession(params);
429 SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool());
430 pool_peer.SetEnableSendingInitialData(false);
431 return http_session;
434 // static
435 net::HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
436 SpdySessionDependencies* session_deps) {
437 DCHECK(next_proto_is_spdy(session_deps->protocol)) <<
438 "Invalid protocol: " << session_deps->protocol;
440 net::HttpNetworkSession::Params params;
441 params.host_resolver = session_deps->host_resolver.get();
442 params.cert_verifier = session_deps->cert_verifier.get();
443 params.transport_security_state =
444 session_deps->transport_security_state.get();
445 params.proxy_service = session_deps->proxy_service.get();
446 params.ssl_config_service = session_deps->ssl_config_service.get();
447 params.http_auth_handler_factory =
448 session_deps->http_auth_handler_factory.get();
449 params.http_server_properties =
450 session_deps->http_server_properties.GetWeakPtr();
451 params.enable_spdy_compression = session_deps->enable_compression;
452 params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping;
453 params.enable_user_alternate_protocol_ports =
454 session_deps->enable_user_alternate_protocol_ports;
455 params.spdy_default_protocol = session_deps->protocol;
456 params.spdy_stream_initial_recv_window_size =
457 session_deps->stream_initial_recv_window_size;
458 params.time_func = session_deps->time_func;
459 params.next_protos = session_deps->next_protos;
460 params.trusted_spdy_proxy = session_deps->trusted_spdy_proxy;
461 params.force_spdy_over_ssl = session_deps->force_spdy_over_ssl;
462 params.force_spdy_always = session_deps->force_spdy_always;
463 params.use_alternate_protocols = session_deps->use_alternate_protocols;
464 params.enable_websocket_over_spdy = session_deps->enable_websocket_over_spdy;
465 params.net_log = session_deps->net_log;
466 return params;
469 SpdyURLRequestContext::SpdyURLRequestContext(NextProto protocol,
470 bool force_spdy_over_ssl,
471 bool force_spdy_always)
472 : storage_(this) {
473 DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
475 storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver));
476 storage_.set_cert_verifier(new MockCertVerifier);
477 storage_.set_transport_security_state(new TransportSecurityState);
478 storage_.set_proxy_service(ProxyService::CreateDirect());
479 storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
480 storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault(
481 host_resolver()));
482 storage_.set_http_server_properties(
483 scoped_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
484 storage_.set_job_factory(new URLRequestJobFactoryImpl());
485 net::HttpNetworkSession::Params params;
486 params.client_socket_factory = &socket_factory_;
487 params.host_resolver = host_resolver();
488 params.cert_verifier = cert_verifier();
489 params.transport_security_state = transport_security_state();
490 params.proxy_service = proxy_service();
491 params.ssl_config_service = ssl_config_service();
492 params.http_auth_handler_factory = http_auth_handler_factory();
493 params.network_delegate = network_delegate();
494 params.enable_spdy_compression = false;
495 params.enable_spdy_ping_based_connection_checking = false;
496 params.spdy_default_protocol = protocol;
497 params.force_spdy_over_ssl = force_spdy_over_ssl;
498 params.force_spdy_always = force_spdy_always;
499 params.http_server_properties = http_server_properties();
500 scoped_refptr<HttpNetworkSession> network_session(
501 new HttpNetworkSession(params));
502 SpdySessionPoolPeer pool_peer(network_session->spdy_session_pool());
503 pool_peer.SetEnableSendingInitialData(false);
504 storage_.set_http_transaction_factory(new HttpCache(
505 network_session.get(), HttpCache::DefaultBackend::InMemory(0)));
508 SpdyURLRequestContext::~SpdyURLRequestContext() {
509 AssertNoURLRequests();
512 bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key) {
513 return pool->FindAvailableSession(key, BoundNetLog()) != NULL;
516 namespace {
518 base::WeakPtr<SpdySession> CreateSpdySessionHelper(
519 const scoped_refptr<HttpNetworkSession>& http_session,
520 const SpdySessionKey& key,
521 const BoundNetLog& net_log,
522 Error expected_status,
523 bool is_secure) {
524 EXPECT_FALSE(HasSpdySession(http_session->spdy_session_pool(), key));
526 scoped_refptr<TransportSocketParams> transport_params(
527 new TransportSocketParams(
528 key.host_port_pair(), false, false, OnHostResolutionCallback(),
529 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
531 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
532 TestCompletionCallback callback;
534 int rv = ERR_UNEXPECTED;
535 if (is_secure) {
536 SSLConfig ssl_config;
537 scoped_refptr<SSLSocketParams> ssl_params(
538 new SSLSocketParams(transport_params,
539 NULL,
540 NULL,
541 key.host_port_pair(),
542 ssl_config,
543 key.privacy_mode(),
545 false,
546 false));
547 rv = connection->Init(key.host_port_pair().ToString(),
548 ssl_params,
549 MEDIUM,
550 callback.callback(),
551 http_session->GetSSLSocketPool(
552 HttpNetworkSession::NORMAL_SOCKET_POOL),
553 net_log);
554 } else {
555 rv = connection->Init(key.host_port_pair().ToString(),
556 transport_params,
557 MEDIUM,
558 callback.callback(),
559 http_session->GetTransportSocketPool(
560 HttpNetworkSession::NORMAL_SOCKET_POOL),
561 net_log);
564 if (rv == ERR_IO_PENDING)
565 rv = callback.WaitForResult();
567 EXPECT_EQ(OK, rv);
569 base::WeakPtr<SpdySession> spdy_session =
570 http_session->spdy_session_pool()->CreateAvailableSessionFromSocket(
571 key, connection.Pass(), net_log, OK, is_secure);
572 // Failure is reported asynchronously.
573 EXPECT_TRUE(spdy_session != NULL);
574 EXPECT_TRUE(HasSpdySession(http_session->spdy_session_pool(), key));
575 return spdy_session;
578 } // namespace
580 base::WeakPtr<SpdySession> CreateInsecureSpdySession(
581 const scoped_refptr<HttpNetworkSession>& http_session,
582 const SpdySessionKey& key,
583 const BoundNetLog& net_log) {
584 return CreateSpdySessionHelper(http_session, key, net_log,
585 OK, false /* is_secure */);
588 base::WeakPtr<SpdySession> TryCreateInsecureSpdySessionExpectingFailure(
589 const scoped_refptr<HttpNetworkSession>& http_session,
590 const SpdySessionKey& key,
591 Error expected_error,
592 const BoundNetLog& net_log) {
593 DCHECK_LT(expected_error, ERR_IO_PENDING);
594 return CreateSpdySessionHelper(http_session, key, net_log,
595 expected_error, false /* is_secure */);
598 base::WeakPtr<SpdySession> CreateSecureSpdySession(
599 const scoped_refptr<HttpNetworkSession>& http_session,
600 const SpdySessionKey& key,
601 const BoundNetLog& net_log) {
602 return CreateSpdySessionHelper(http_session, key, net_log,
603 OK, true /* is_secure */);
606 namespace {
608 // A ClientSocket used for CreateFakeSpdySession() below.
609 class FakeSpdySessionClientSocket : public MockClientSocket {
610 public:
611 FakeSpdySessionClientSocket(int read_result)
612 : MockClientSocket(BoundNetLog()),
613 read_result_(read_result) {}
615 ~FakeSpdySessionClientSocket() override {}
617 int Read(IOBuffer* buf,
618 int buf_len,
619 const CompletionCallback& callback) override {
620 return read_result_;
623 int Write(IOBuffer* buf,
624 int buf_len,
625 const CompletionCallback& callback) override {
626 return ERR_IO_PENDING;
629 // Return kProtoUnknown to use the pool's default protocol.
630 NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
632 // The functions below are not expected to be called.
634 int Connect(const CompletionCallback& callback) override {
635 ADD_FAILURE();
636 return ERR_UNEXPECTED;
639 bool WasEverUsed() const override {
640 ADD_FAILURE();
641 return false;
644 bool UsingTCPFastOpen() const override {
645 ADD_FAILURE();
646 return false;
649 bool WasNpnNegotiated() const override {
650 ADD_FAILURE();
651 return false;
654 bool GetSSLInfo(SSLInfo* ssl_info) override {
655 ADD_FAILURE();
656 return false;
659 private:
660 int read_result_;
663 base::WeakPtr<SpdySession> CreateFakeSpdySessionHelper(
664 SpdySessionPool* pool,
665 const SpdySessionKey& key,
666 Error expected_status) {
667 EXPECT_NE(expected_status, ERR_IO_PENDING);
668 EXPECT_FALSE(HasSpdySession(pool, key));
669 scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle());
670 handle->SetSocket(scoped_ptr<StreamSocket>(new FakeSpdySessionClientSocket(
671 expected_status == OK ? ERR_IO_PENDING : expected_status)));
672 base::WeakPtr<SpdySession> spdy_session =
673 pool->CreateAvailableSessionFromSocket(
674 key, handle.Pass(), BoundNetLog(), OK, true /* is_secure */);
675 // Failure is reported asynchronously.
676 EXPECT_TRUE(spdy_session != NULL);
677 EXPECT_TRUE(HasSpdySession(pool, key));
678 return spdy_session;
681 } // namespace
683 base::WeakPtr<SpdySession> CreateFakeSpdySession(SpdySessionPool* pool,
684 const SpdySessionKey& key) {
685 return CreateFakeSpdySessionHelper(pool, key, OK);
688 base::WeakPtr<SpdySession> TryCreateFakeSpdySessionExpectingFailure(
689 SpdySessionPool* pool,
690 const SpdySessionKey& key,
691 Error expected_error) {
692 DCHECK_LT(expected_error, ERR_IO_PENDING);
693 return CreateFakeSpdySessionHelper(pool, key, expected_error);
696 SpdySessionPoolPeer::SpdySessionPoolPeer(SpdySessionPool* pool) : pool_(pool) {
699 void SpdySessionPoolPeer::RemoveAliases(const SpdySessionKey& key) {
700 pool_->RemoveAliases(key);
703 void SpdySessionPoolPeer::DisableDomainAuthenticationVerification() {
704 pool_->verify_domain_authentication_ = false;
707 void SpdySessionPoolPeer::SetEnableSendingInitialData(bool enabled) {
708 pool_->enable_sending_initial_data_ = enabled;
711 SpdyTestUtil::SpdyTestUtil(NextProto protocol)
712 : protocol_(protocol),
713 spdy_version_(NextProtoToSpdyMajorVersion(protocol)) {
714 DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
717 void SpdyTestUtil::AddUrlToHeaderBlock(base::StringPiece url,
718 SpdyHeaderBlock* headers) const {
719 if (is_spdy2()) {
720 (*headers)["url"] = url.as_string();
721 } else {
722 std::string scheme, host, path;
723 ParseUrl(url, &scheme, &host, &path);
724 (*headers)[GetSchemeKey()] = scheme;
725 (*headers)[GetHostKey()] = host;
726 (*headers)[GetPathKey()] = path;
730 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructGetHeaderBlock(
731 base::StringPiece url) const {
732 return ConstructHeaderBlock("GET", url, NULL);
735 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructGetHeaderBlockForProxy(
736 base::StringPiece url) const {
737 scoped_ptr<SpdyHeaderBlock> headers(ConstructGetHeaderBlock(url));
738 if (is_spdy2())
739 (*headers)[GetPathKey()] = url.data();
740 return headers.Pass();
743 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructHeadHeaderBlock(
744 base::StringPiece url,
745 int64 content_length) const {
746 return ConstructHeaderBlock("HEAD", url, &content_length);
749 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructPostHeaderBlock(
750 base::StringPiece url,
751 int64 content_length) const {
752 return ConstructHeaderBlock("POST", url, &content_length);
755 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructPutHeaderBlock(
756 base::StringPiece url,
757 int64 content_length) const {
758 return ConstructHeaderBlock("PUT", url, &content_length);
761 SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(
762 const SpdyHeaderInfo& header_info,
763 scoped_ptr<SpdyHeaderBlock> headers) const {
764 BufferedSpdyFramer framer(spdy_version_, header_info.compressed);
765 SpdyFrame* frame = NULL;
766 switch (header_info.kind) {
767 case DATA:
768 frame = framer.CreateDataFrame(header_info.id, header_info.data,
769 header_info.data_length,
770 header_info.data_flags);
771 break;
772 case SYN_STREAM:
774 frame = framer.CreateSynStream(header_info.id, header_info.assoc_id,
775 header_info.priority,
776 header_info.control_flags,
777 headers.get());
779 break;
780 case SYN_REPLY:
781 frame = framer.CreateSynReply(header_info.id, header_info.control_flags,
782 headers.get());
783 break;
784 case RST_STREAM:
785 frame = framer.CreateRstStream(header_info.id, header_info.status);
786 break;
787 case HEADERS:
788 frame = framer.CreateHeaders(header_info.id, header_info.control_flags,
789 headers.get());
790 break;
791 default:
792 ADD_FAILURE();
793 break;
795 return frame;
798 SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
799 const char* const extra_headers[],
800 int extra_header_count,
801 const char* const tail_headers[],
802 int tail_header_count) const {
803 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
804 AppendToHeaderBlock(extra_headers, extra_header_count, headers.get());
805 if (tail_headers && tail_header_count)
806 AppendToHeaderBlock(tail_headers, tail_header_count, headers.get());
807 return ConstructSpdyFrame(header_info, headers.Pass());
810 SpdyFrame* SpdyTestUtil::ConstructSpdyControlFrame(
811 scoped_ptr<SpdyHeaderBlock> headers,
812 bool compressed,
813 SpdyStreamId stream_id,
814 RequestPriority request_priority,
815 SpdyFrameType type,
816 SpdyControlFlags flags,
817 SpdyStreamId associated_stream_id) const {
818 EXPECT_GE(type, DATA);
819 EXPECT_LE(type, PRIORITY);
820 const SpdyHeaderInfo header_info = {
821 type,
822 stream_id,
823 associated_stream_id,
824 ConvertRequestPriorityToSpdyPriority(request_priority, spdy_version_),
825 0, // credential slot
826 flags,
827 compressed,
828 RST_STREAM_INVALID, // status
829 NULL, // data
830 0, // length
831 DATA_FLAG_NONE
833 return ConstructSpdyFrame(header_info, headers.Pass());
836 SpdyFrame* SpdyTestUtil::ConstructSpdyControlFrame(
837 const char* const extra_headers[],
838 int extra_header_count,
839 bool compressed,
840 SpdyStreamId stream_id,
841 RequestPriority request_priority,
842 SpdyFrameType type,
843 SpdyControlFlags flags,
844 const char* const* tail_headers,
845 int tail_header_size,
846 SpdyStreamId associated_stream_id) const {
847 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
848 AppendToHeaderBlock(extra_headers, extra_header_count, headers.get());
849 if (tail_headers && tail_header_size)
850 AppendToHeaderBlock(tail_headers, tail_header_size / 2, headers.get());
851 return ConstructSpdyControlFrame(
852 headers.Pass(), compressed, stream_id,
853 request_priority, type, flags, associated_stream_id);
856 std::string SpdyTestUtil::ConstructSpdyReplyString(
857 const SpdyHeaderBlock& headers) const {
858 std::string reply_string;
859 for (SpdyHeaderBlock::const_iterator it = headers.begin();
860 it != headers.end(); ++it) {
861 std::string key = it->first;
862 // Remove leading colon from "special" headers (for SPDY3 and
863 // above).
864 if (spdy_version() >= SPDY3 && key[0] == ':')
865 key = key.substr(1);
866 std::vector<std::string> values;
867 base::SplitString(it->second, '\0', &values);
868 for (std::vector<std::string>::const_iterator it2 = values.begin();
869 it2 != values.end(); ++it2) {
870 reply_string += key + ": " + *it2 + "\n";
873 return reply_string;
876 // TODO(jgraettinger): Eliminate uses of this method in tests (prefer
877 // SpdySettingsIR).
878 SpdyFrame* SpdyTestUtil::ConstructSpdySettings(
879 const SettingsMap& settings) const {
880 SpdySettingsIR settings_ir;
881 for (SettingsMap::const_iterator it = settings.begin();
882 it != settings.end();
883 ++it) {
884 settings_ir.AddSetting(
885 it->first,
886 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
887 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
888 it->second.second);
890 return CreateFramer(false)->SerializeFrame(settings_ir);
893 SpdyFrame* SpdyTestUtil::ConstructSpdySettingsAck() const {
894 char kEmptyWrite[] = "";
896 if (spdy_version() > SPDY3) {
897 SpdySettingsIR settings_ir;
898 settings_ir.set_is_ack(true);
899 return CreateFramer(false)->SerializeFrame(settings_ir);
901 // No settings ACK write occurs. Create an empty placeholder write.
902 return new SpdyFrame(kEmptyWrite, 0, false);
905 SpdyFrame* SpdyTestUtil::ConstructSpdyPing(uint32 ping_id, bool is_ack) const {
906 SpdyPingIR ping_ir(ping_id);
907 ping_ir.set_is_ack(is_ack);
908 return CreateFramer(false)->SerializeFrame(ping_ir);
911 SpdyFrame* SpdyTestUtil::ConstructSpdyGoAway() const {
912 return ConstructSpdyGoAway(0);
915 SpdyFrame* SpdyTestUtil::ConstructSpdyGoAway(
916 SpdyStreamId last_good_stream_id) const {
917 SpdyGoAwayIR go_ir(last_good_stream_id, GOAWAY_OK, "go away");
918 return CreateFramer(false)->SerializeFrame(go_ir);
921 SpdyFrame* SpdyTestUtil::ConstructSpdyGoAway(SpdyStreamId last_good_stream_id,
922 SpdyGoAwayStatus status,
923 const std::string& desc) const {
924 SpdyGoAwayIR go_ir(last_good_stream_id, status, desc);
925 return CreateFramer(false)->SerializeFrame(go_ir);
928 SpdyFrame* SpdyTestUtil::ConstructSpdyWindowUpdate(
929 const SpdyStreamId stream_id, uint32 delta_window_size) const {
930 SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
931 return CreateFramer(false)->SerializeFrame(update_ir);
934 // TODO(jgraettinger): Eliminate uses of this method in tests (prefer
935 // SpdyRstStreamIR).
936 SpdyFrame* SpdyTestUtil::ConstructSpdyRstStream(
937 SpdyStreamId stream_id,
938 SpdyRstStreamStatus status) const {
939 SpdyRstStreamIR rst_ir(stream_id, status, "");
940 return CreateFramer(false)->SerializeRstStream(rst_ir);
943 SpdyFrame* SpdyTestUtil::ConstructSpdyGet(
944 const char* const url,
945 bool compressed,
946 SpdyStreamId stream_id,
947 RequestPriority request_priority) const {
948 scoped_ptr<SpdyHeaderBlock> block(ConstructGetHeaderBlock(url));
949 return ConstructSpdySyn(
950 stream_id, *block, request_priority, compressed, true);
953 SpdyFrame* SpdyTestUtil::ConstructSpdyGet(const char* const extra_headers[],
954 int extra_header_count,
955 bool compressed,
956 int stream_id,
957 RequestPriority request_priority,
958 bool direct) const {
959 SpdyHeaderBlock block;
960 block[GetMethodKey()] = "GET";
961 block[GetPathKey()] =
962 (is_spdy2() && !direct) ? "http://www.google.com/" : "/";
963 block[GetHostKey()] = "www.google.com";
964 block[GetSchemeKey()] = "http";
965 MaybeAddVersionHeader(&block);
966 AppendToHeaderBlock(extra_headers, extra_header_count, &block);
967 return ConstructSpdySyn(stream_id, block, request_priority, compressed, true);
970 SpdyFrame* SpdyTestUtil::ConstructSpdyConnect(
971 const char* const extra_headers[],
972 int extra_header_count,
973 int stream_id,
974 RequestPriority priority) const {
975 SpdyHeaderBlock block;
976 block[GetMethodKey()] = "CONNECT";
977 block[GetPathKey()] = "www.google.com:443";
978 block[GetHostKey()] = "www.google.com";
979 MaybeAddVersionHeader(&block);
980 AppendToHeaderBlock(extra_headers, extra_header_count, &block);
981 return ConstructSpdySyn(stream_id, block, priority, false, false);
984 SpdyFrame* SpdyTestUtil::ConstructSpdyPush(const char* const extra_headers[],
985 int extra_header_count,
986 int stream_id,
987 int associated_stream_id,
988 const char* url) {
989 if (spdy_version() < SPDY4) {
990 SpdySynStreamIR syn_stream(stream_id);
991 syn_stream.set_associated_to_stream_id(associated_stream_id);
992 syn_stream.SetHeader("hello", "bye");
993 syn_stream.SetHeader(GetStatusKey(), "200 OK");
994 syn_stream.SetHeader(GetVersionKey(), "HTTP/1.1");
995 AddUrlToHeaderBlock(url, syn_stream.mutable_name_value_block());
996 AppendToHeaderBlock(extra_headers,
997 extra_header_count,
998 syn_stream.mutable_name_value_block());
999 return CreateFramer(false)->SerializeFrame(syn_stream);
1000 } else {
1001 SpdyPushPromiseIR push_promise(associated_stream_id, stream_id);
1002 AddUrlToHeaderBlock(url, push_promise.mutable_name_value_block());
1003 scoped_ptr<SpdyFrame> push_promise_frame(
1004 CreateFramer(false)->SerializeFrame(push_promise));
1006 SpdyHeadersIR headers(stream_id);
1007 headers.SetHeader("hello", "bye");
1008 headers.SetHeader(GetStatusKey(), "200 OK");
1009 AppendToHeaderBlock(
1010 extra_headers, extra_header_count, headers.mutable_name_value_block());
1011 scoped_ptr<SpdyFrame> headers_frame(
1012 CreateFramer(false)->SerializeFrame(headers));
1014 int joint_data_size = push_promise_frame->size() + headers_frame->size();
1015 scoped_ptr<char[]> data(new char[joint_data_size]);
1016 const SpdyFrame* frames[2] = {
1017 push_promise_frame.get(), headers_frame.get(),
1019 int combined_size =
1020 CombineFrames(frames, arraysize(frames), data.get(), joint_data_size);
1021 DCHECK_EQ(combined_size, joint_data_size);
1022 return new SpdyFrame(data.release(), joint_data_size, true);
1026 SpdyFrame* SpdyTestUtil::ConstructSpdyPush(const char* const extra_headers[],
1027 int extra_header_count,
1028 int stream_id,
1029 int associated_stream_id,
1030 const char* url,
1031 const char* status,
1032 const char* location) {
1033 if (spdy_version() < SPDY4) {
1034 SpdySynStreamIR syn_stream(stream_id);
1035 syn_stream.set_associated_to_stream_id(associated_stream_id);
1036 syn_stream.SetHeader("hello", "bye");
1037 syn_stream.SetHeader(GetStatusKey(), status);
1038 syn_stream.SetHeader(GetVersionKey(), "HTTP/1.1");
1039 syn_stream.SetHeader("location", location);
1040 AddUrlToHeaderBlock(url, syn_stream.mutable_name_value_block());
1041 AppendToHeaderBlock(extra_headers,
1042 extra_header_count,
1043 syn_stream.mutable_name_value_block());
1044 return CreateFramer(false)->SerializeFrame(syn_stream);
1045 } else {
1046 SpdyPushPromiseIR push_promise(associated_stream_id, stream_id);
1047 AddUrlToHeaderBlock(url, push_promise.mutable_name_value_block());
1048 scoped_ptr<SpdyFrame> push_promise_frame(
1049 CreateFramer(false)->SerializeFrame(push_promise));
1051 SpdyHeadersIR headers(stream_id);
1052 headers.SetHeader("hello", "bye");
1053 headers.SetHeader(GetStatusKey(), status);
1054 headers.SetHeader("location", location);
1055 AppendToHeaderBlock(
1056 extra_headers, extra_header_count, headers.mutable_name_value_block());
1057 scoped_ptr<SpdyFrame> headers_frame(
1058 CreateFramer(false)->SerializeFrame(headers));
1060 int joint_data_size = push_promise_frame->size() + headers_frame->size();
1061 scoped_ptr<char[]> data(new char[joint_data_size]);
1062 const SpdyFrame* frames[2] = {
1063 push_promise_frame.get(), headers_frame.get(),
1065 int combined_size =
1066 CombineFrames(frames, arraysize(frames), data.get(), joint_data_size);
1067 DCHECK_EQ(combined_size, joint_data_size);
1068 return new SpdyFrame(data.release(), joint_data_size, true);
1072 SpdyFrame* SpdyTestUtil::ConstructInitialSpdyPushFrame(
1073 scoped_ptr<SpdyHeaderBlock> headers,
1074 int stream_id,
1075 int associated_stream_id) {
1076 if (spdy_version() < SPDY4) {
1077 SpdySynStreamIR syn_stream(stream_id);
1078 syn_stream.set_associated_to_stream_id(associated_stream_id);
1079 SetPriority(LOWEST, &syn_stream);
1080 syn_stream.set_name_value_block(*headers);
1081 return CreateFramer(false)->SerializeFrame(syn_stream);
1082 } else {
1083 SpdyPushPromiseIR push_promise(associated_stream_id, stream_id);
1084 push_promise.set_name_value_block(*headers);
1085 return CreateFramer(false)->SerializeFrame(push_promise);
1089 SpdyFrame* SpdyTestUtil::ConstructSpdyPushHeaders(
1090 int stream_id,
1091 const char* const extra_headers[],
1092 int extra_header_count) {
1093 SpdyHeadersIR headers(stream_id);
1094 headers.SetHeader(GetStatusKey(), "200 OK");
1095 MaybeAddVersionHeader(&headers);
1096 AppendToHeaderBlock(extra_headers, extra_header_count,
1097 headers.mutable_name_value_block());
1098 return CreateFramer(false)->SerializeFrame(headers);
1101 SpdyFrame* SpdyTestUtil::ConstructSpdySyn(int stream_id,
1102 const SpdyHeaderBlock& block,
1103 RequestPriority priority,
1104 bool compressed,
1105 bool fin) const {
1106 if (protocol_ < kProtoSPDY4) {
1107 SpdySynStreamIR syn_stream(stream_id);
1108 syn_stream.set_name_value_block(block);
1109 syn_stream.set_priority(
1110 ConvertRequestPriorityToSpdyPriority(priority, spdy_version()));
1111 syn_stream.set_fin(fin);
1112 return CreateFramer(compressed)->SerializeFrame(syn_stream);
1113 } else {
1114 SpdyHeadersIR headers(stream_id);
1115 headers.set_name_value_block(block);
1116 headers.set_has_priority(true);
1117 headers.set_priority(
1118 ConvertRequestPriorityToSpdyPriority(priority, spdy_version()));
1119 headers.set_fin(fin);
1120 return CreateFramer(compressed)->SerializeFrame(headers);
1124 SpdyFrame* SpdyTestUtil::ConstructSpdyReply(int stream_id,
1125 const SpdyHeaderBlock& headers) {
1126 if (protocol_ < kProtoSPDY4) {
1127 SpdySynReplyIR syn_reply(stream_id);
1128 syn_reply.set_name_value_block(headers);
1129 return CreateFramer(false)->SerializeFrame(syn_reply);
1130 } else {
1131 SpdyHeadersIR reply(stream_id);
1132 reply.set_name_value_block(headers);
1133 return CreateFramer(false)->SerializeFrame(reply);
1137 SpdyFrame* SpdyTestUtil::ConstructSpdySynReplyError(
1138 const char* const status,
1139 const char* const* const extra_headers,
1140 int extra_header_count,
1141 int stream_id) {
1142 SpdyHeaderBlock block;
1143 block["hello"] = "bye";
1144 block[GetStatusKey()] = status;
1145 MaybeAddVersionHeader(&block);
1146 AppendToHeaderBlock(extra_headers, extra_header_count, &block);
1148 return ConstructSpdyReply(stream_id, block);
1151 SpdyFrame* SpdyTestUtil::ConstructSpdyGetSynReplyRedirect(int stream_id) {
1152 static const char* const kExtraHeaders[] = {
1153 "location", "http://www.foo.com/index.php",
1155 return ConstructSpdySynReplyError("301 Moved Permanently", kExtraHeaders,
1156 arraysize(kExtraHeaders)/2, stream_id);
1159 SpdyFrame* SpdyTestUtil::ConstructSpdySynReplyError(int stream_id) {
1160 return ConstructSpdySynReplyError("500 Internal Server Error", NULL, 0, 1);
1163 SpdyFrame* SpdyTestUtil::ConstructSpdyGetSynReply(
1164 const char* const extra_headers[],
1165 int extra_header_count,
1166 int stream_id) {
1167 SpdyHeaderBlock block;
1168 block["hello"] = "bye";
1169 block[GetStatusKey()] = "200";
1170 MaybeAddVersionHeader(&block);
1171 AppendToHeaderBlock(extra_headers, extra_header_count, &block);
1173 return ConstructSpdyReply(stream_id, block);
1176 SpdyFrame* SpdyTestUtil::ConstructSpdyPost(const char* url,
1177 SpdyStreamId stream_id,
1178 int64 content_length,
1179 RequestPriority priority,
1180 const char* const extra_headers[],
1181 int extra_header_count) {
1182 scoped_ptr<SpdyHeaderBlock> block(
1183 ConstructPostHeaderBlock(url, content_length));
1184 AppendToHeaderBlock(extra_headers, extra_header_count, block.get());
1185 return ConstructSpdySyn(stream_id, *block, priority, false, false);
1188 SpdyFrame* SpdyTestUtil::ConstructChunkedSpdyPost(
1189 const char* const extra_headers[],
1190 int extra_header_count) {
1191 SpdyHeaderBlock block;
1192 block[GetMethodKey()] = "POST";
1193 block[GetPathKey()] = "/";
1194 block[GetHostKey()] = "www.google.com";
1195 block[GetSchemeKey()] = "http";
1196 MaybeAddVersionHeader(&block);
1197 AppendToHeaderBlock(extra_headers, extra_header_count, &block);
1198 return ConstructSpdySyn(1, block, LOWEST, false, false);
1201 SpdyFrame* SpdyTestUtil::ConstructSpdyPostSynReply(
1202 const char* const extra_headers[],
1203 int extra_header_count) {
1204 // TODO(jgraettinger): Remove this method.
1205 return ConstructSpdyGetSynReply(NULL, 0, 1);
1208 SpdyFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id, bool fin) {
1209 SpdyFramer framer(spdy_version_);
1210 SpdyDataIR data_ir(stream_id,
1211 base::StringPiece(kUploadData, kUploadDataSize));
1212 data_ir.set_fin(fin);
1213 return framer.SerializeData(data_ir);
1216 SpdyFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id,
1217 const char* data,
1218 uint32 len,
1219 bool fin) {
1220 SpdyFramer framer(spdy_version_);
1221 SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
1222 data_ir.set_fin(fin);
1223 return framer.SerializeData(data_ir);
1226 SpdyFrame* SpdyTestUtil::ConstructWrappedSpdyFrame(
1227 const scoped_ptr<SpdyFrame>& frame,
1228 int stream_id) {
1229 return ConstructSpdyBodyFrame(stream_id, frame->data(),
1230 frame->size(), false);
1233 const SpdyHeaderInfo SpdyTestUtil::MakeSpdyHeader(SpdyFrameType type) {
1234 const SpdyHeaderInfo kHeader = {
1235 type,
1236 1, // Stream ID
1237 0, // Associated stream ID
1238 ConvertRequestPriorityToSpdyPriority(LOWEST, spdy_version_),
1239 kSpdyCredentialSlotUnused,
1240 CONTROL_FLAG_FIN, // Control Flags
1241 false, // Compressed
1242 RST_STREAM_INVALID,
1243 NULL, // Data
1244 0, // Length
1245 DATA_FLAG_NONE
1247 return kHeader;
1250 scoped_ptr<SpdyFramer> SpdyTestUtil::CreateFramer(bool compressed) const {
1251 scoped_ptr<SpdyFramer> framer(new SpdyFramer(spdy_version_));
1252 framer->set_enable_compression(compressed);
1253 return framer.Pass();
1256 const char* SpdyTestUtil::GetMethodKey() const {
1257 return is_spdy2() ? "method" : ":method";
1260 const char* SpdyTestUtil::GetStatusKey() const {
1261 return is_spdy2() ? "status" : ":status";
1264 const char* SpdyTestUtil::GetHostKey() const {
1265 if (protocol_ < kProtoSPDY3)
1266 return "host";
1267 if (protocol_ < kProtoSPDY4)
1268 return ":host";
1269 else
1270 return ":authority";
1273 const char* SpdyTestUtil::GetSchemeKey() const {
1274 return is_spdy2() ? "scheme" : ":scheme";
1277 const char* SpdyTestUtil::GetVersionKey() const {
1278 return is_spdy2() ? "version" : ":version";
1281 const char* SpdyTestUtil::GetPathKey() const {
1282 return is_spdy2() ? "url" : ":path";
1285 scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructHeaderBlock(
1286 base::StringPiece method,
1287 base::StringPiece url,
1288 int64* content_length) const {
1289 std::string scheme, host, path;
1290 ParseUrl(url.data(), &scheme, &host, &path);
1291 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
1292 (*headers)[GetMethodKey()] = method.as_string();
1293 (*headers)[GetPathKey()] = path.c_str();
1294 (*headers)[GetHostKey()] = host.c_str();
1295 (*headers)[GetSchemeKey()] = scheme.c_str();
1296 if (include_version_header()) {
1297 (*headers)[GetVersionKey()] = "HTTP/1.1";
1299 if (content_length) {
1300 std::string length_str = base::Int64ToString(*content_length);
1301 (*headers)["content-length"] = length_str;
1303 return headers.Pass();
1306 void SpdyTestUtil::MaybeAddVersionHeader(
1307 SpdyFrameWithNameValueBlockIR* frame_ir) const {
1308 if (include_version_header()) {
1309 frame_ir->SetHeader(GetVersionKey(), "HTTP/1.1");
1313 void SpdyTestUtil::MaybeAddVersionHeader(SpdyHeaderBlock* block) const {
1314 if (include_version_header()) {
1315 (*block)[GetVersionKey()] = "HTTP/1.1";
1319 void SpdyTestUtil::SetPriority(RequestPriority priority,
1320 SpdySynStreamIR* ir) const {
1321 ir->set_priority(ConvertRequestPriorityToSpdyPriority(
1322 priority, spdy_version()));
1325 } // namespace net