1 // Copyright (c) 2012 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.
9 #include "base/bind_helpers.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_piece.h"
16 #include "base/test/test_file_util.h"
17 #include "net/base/auth.h"
18 #include "net/base/chunked_upload_data_stream.h"
19 #include "net/base/elements_upload_data_stream.h"
20 #include "net/base/request_priority.h"
21 #include "net/base/test_data_directory.h"
22 #include "net/base/upload_bytes_element_reader.h"
23 #include "net/base/upload_file_element_reader.h"
24 #include "net/http/http_network_session_peer.h"
25 #include "net/http/http_network_transaction.h"
26 #include "net/http/http_server_properties.h"
27 #include "net/http/http_transaction_test_util.h"
28 #include "net/log/net_log_unittest.h"
29 #include "net/socket/client_socket_pool_base.h"
30 #include "net/socket/next_proto.h"
31 #include "net/spdy/buffered_spdy_framer.h"
32 #include "net/spdy/spdy_http_stream.h"
33 #include "net/spdy/spdy_http_utils.h"
34 #include "net/spdy/spdy_session.h"
35 #include "net/spdy/spdy_session_pool.h"
36 #include "net/spdy/spdy_test_util_common.h"
37 #include "net/spdy/spdy_test_utils.h"
38 #include "net/ssl/ssl_connection_status_flags.h"
39 #include "net/test/cert_test_util.h"
40 #include "net/url_request/url_request_test_util.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/platform_test.h"
44 //-----------------------------------------------------------------------------
53 enum SpdyNetworkTransactionTestSSLType
{
54 // Request an https:// URL and use NPN (or ALPN) to negotiate SPDY during
57 // Request and http:// URL to a server that supports SPDY via Alternative
58 // Service on port 443.
59 // See: https//tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
60 HTTP_SPDY_VIA_ALT_SVC
,
63 struct SpdyNetworkTransactionTestParams
{
64 SpdyNetworkTransactionTestParams()
65 : protocol(kProtoSPDY31
), ssl_type(HTTPS_SPDY_VIA_NPN
) {}
67 SpdyNetworkTransactionTestParams(NextProto protocol
,
68 SpdyNetworkTransactionTestSSLType ssl_type
)
69 : protocol(protocol
), ssl_type(ssl_type
) {}
71 friend std::ostream
& operator<<(std::ostream
& os
,
72 const SpdyNetworkTransactionTestParams
& p
) {
75 case HTTP_SPDY_VIA_ALT_SVC
:
76 type_str
= "HTTP_SPDY_VIA_ALT_SVC";
78 case HTTPS_SPDY_VIA_NPN
:
79 type_str
= "HTTPS_SPDY_VIA_NPN";
82 os
<< "{ protocol: " << SSLClientSocket::NextProtoToString(p
.protocol
)
83 << ", ssl_type: " << type_str
<< " }";
88 SpdyNetworkTransactionTestSSLType ssl_type
;
91 void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params
,
92 SpdySessionDependencies
* session_deps
) {
93 session_deps
->use_alternate_protocols
= true;
94 session_deps
->next_protos
= SpdyNextProtos();
95 if (test_params
.ssl_type
== HTTP_SPDY_VIA_ALT_SVC
) {
96 session_deps
->http_server_properties
.SetAlternativeService(
97 HostPortPair("www.example.org", 80),
98 AlternativeService(AlternateProtocolFromNextProto(test_params
.protocol
),
99 "www.example.org", 443),
104 SpdySessionDependencies
* CreateSpdySessionDependencies(
105 SpdyNetworkTransactionTestParams test_params
) {
106 SpdySessionDependencies
* session_deps
=
107 new SpdySessionDependencies(test_params
.protocol
);
108 UpdateSpdySessionDependencies(test_params
, session_deps
);
112 SpdySessionDependencies
* CreateSpdySessionDependencies(
113 SpdyNetworkTransactionTestParams test_params
,
114 ProxyService
* proxy_service
) {
115 SpdySessionDependencies
* session_deps
=
116 new SpdySessionDependencies(test_params
.protocol
, proxy_service
);
117 UpdateSpdySessionDependencies(test_params
, session_deps
);
123 class SpdyNetworkTransactionTest
124 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestParams
> {
126 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol
) {
127 spdy_util_
.set_default_url(GURL(GetDefaultUrl()));
130 virtual ~SpdyNetworkTransactionTest() {
131 // UploadDataStream may post a deletion tasks back to the message loop on
133 upload_data_stream_
.reset();
134 base::RunLoop().RunUntilIdle();
137 void SetUp() override
{
138 get_request_initialized_
= false;
139 post_request_initialized_
= false;
140 chunked_post_request_initialized_
= false;
141 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
144 struct TransactionHelperResult
{
146 std::string status_line
;
147 std::string response_data
;
148 HttpResponseInfo response_info
;
151 // A helper class that handles all the initial npn/ssl setup.
152 class NormalSpdyTransactionHelper
{
154 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
155 RequestPriority priority
,
156 const BoundNetLog
& log
,
157 SpdyNetworkTransactionTestParams test_params
,
158 SpdySessionDependencies
* session_deps
)
161 session_deps_(session_deps
== NULL
162 ? CreateSpdySessionDependencies(test_params
)
165 SpdySessionDependencies::SpdyCreateSession(session_deps_
.get())),
167 test_params_(test_params
),
169 deterministic_(false),
170 spdy_enabled_(true) {}
172 ~NormalSpdyTransactionHelper() {
173 // Any test which doesn't close the socket by sending it an EOF will
174 // have a valid session left open, which leaks the entire session pool.
175 // This is just fine - in fact, some of our tests intentionally do this
176 // so that we can check consistency of the SpdySessionPool as the test
177 // finishes. If we had put an EOF on the socket, the SpdySession would
178 // have closed and we wouldn't be able to check the consistency.
180 // Forcefully close existing sessions here.
181 session()->spdy_session_pool()->CloseAllSessions();
184 void SetDeterministic() {
185 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
186 session_deps_
.get());
187 deterministic_
= true;
190 void SetSpdyDisabled() {
191 spdy_enabled_
= false;
192 port_
= test_params_
.ssl_type
== HTTP_SPDY_VIA_ALT_SVC
? 80 : 443;
195 void RunPreTestSetup() {
196 if (!session_deps_
.get())
197 session_deps_
.reset(CreateSpdySessionDependencies(test_params_
));
198 if (!session_
.get()) {
199 session_
= SpdySessionDependencies::SpdyCreateSession(
200 session_deps_
.get());
203 // We're now ready to use SSL-npn SPDY.
204 trans_
.reset(new HttpNetworkTransaction(priority_
, session_
.get()));
207 // Start the transaction, read some data, finish.
208 void RunDefaultTest() {
209 if (!StartDefaultTest())
214 bool StartDefaultTest() {
215 output_
.rv
= trans_
->Start(&request_
, callback_
.callback(), log_
);
217 // We expect an IO Pending or some sort of error.
218 EXPECT_LT(output_
.rv
, 0);
219 return output_
.rv
== ERR_IO_PENDING
;
222 void FinishDefaultTest() {
223 output_
.rv
= callback_
.WaitForResult();
224 if (output_
.rv
!= OK
) {
225 session_
->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED
);
230 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
231 ASSERT_TRUE(response
!= NULL
);
232 ASSERT_TRUE(response
->headers
.get() != NULL
);
233 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
234 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
235 if (HttpStreamFactory::spdy_enabled()) {
237 HttpResponseInfo::ConnectionInfoFromNextProto(
238 test_params_
.protocol
),
239 response
->connection_info
);
241 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
,
242 response
->connection_info
);
245 EXPECT_TRUE(response
->was_npn_negotiated
);
247 // If SPDY is disabled, an HTTP request should not be diverted
248 // over an SSL session.
249 EXPECT_EQ(request_
.url
.SchemeIs("https"),
250 response
->was_npn_negotiated
);
252 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
253 EXPECT_EQ(port_
, response
->socket_address
.port());
254 output_
.status_line
= response
->headers
->GetStatusLine();
255 output_
.response_info
= *response
; // Make a copy so we can verify.
256 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
259 void FinishDefaultTestWithoutVerification() {
260 output_
.rv
= callback_
.WaitForResult();
261 if (output_
.rv
!= OK
)
262 session_
->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED
);
265 // Most tests will want to call this function. In particular, the MockReads
266 // should end with an empty read, and that read needs to be processed to
267 // ensure proper deletion of the spdy_session_pool.
268 void VerifyDataConsumed() {
269 for (DataVector::iterator it
= data_vector_
.begin();
270 it
!= data_vector_
.end(); ++it
) {
271 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
272 << (*it
)->read_count()
274 << (*it
)->read_index();
275 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
276 << (*it
)->write_count()
278 << (*it
)->write_index();
282 // Occasionally a test will expect to error out before certain reads are
283 // processed. In that case we want to explicitly ensure that the reads were
285 void VerifyDataNotConsumed() {
286 for (DataVector::iterator it
= data_vector_
.begin();
287 it
!= data_vector_
.end(); ++it
) {
288 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
289 << (*it
)->read_count()
291 << (*it
)->read_index();
292 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
293 << (*it
)->write_count()
295 << (*it
)->write_index();
299 void RunToCompletion(StaticSocketDataProvider
* data
) {
303 VerifyDataConsumed();
306 void RunToCompletionWithSSLData(
307 StaticSocketDataProvider
* data
,
308 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
310 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
312 VerifyDataConsumed();
315 void AddData(StaticSocketDataProvider
* data
) {
316 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
317 new SSLSocketDataProvider(ASYNC
, OK
));
319 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
320 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
323 void AddDataWithSSLSocketDataProvider(
324 StaticSocketDataProvider
* data
,
325 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
326 DCHECK(!deterministic_
);
327 data_vector_
.push_back(data
);
328 if (ssl_provider
->next_proto_status
==
329 SSLClientSocket::kNextProtoUnsupported
) {
330 ssl_provider
->SetNextProto(test_params_
.protocol
);
333 session_deps_
->socket_factory
->AddSSLSocketDataProvider(
335 ssl_vector_
.push_back(ssl_provider
.release());
337 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
338 if (test_params_
.ssl_type
== HTTP_SPDY_VIA_ALT_SVC
) {
339 MockConnect
hanging_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
340 StaticSocketDataProvider
* hanging_non_alt_svc_socket
=
341 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
342 hanging_non_alt_svc_socket
->set_connect_data(hanging_connect
);
343 session_deps_
->socket_factory
->AddSocketDataProvider(
344 hanging_non_alt_svc_socket
);
345 alternate_vector_
.push_back(hanging_non_alt_svc_socket
);
349 void AddDeterministicData(DeterministicSocketData
* data
) {
350 DCHECK(deterministic_
);
351 data_vector_
.push_back(data
);
352 SSLSocketDataProvider
* ssl_provider
=
353 new SSLSocketDataProvider(ASYNC
, OK
);
354 ssl_provider
->SetNextProto(test_params_
.protocol
);
356 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
357 ssl_vector_
.push_back(ssl_provider
);
358 session_deps_
->deterministic_socket_factory
->AddSSLSocketDataProvider(
361 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
362 if (test_params_
.ssl_type
== HTTP_SPDY_VIA_ALT_SVC
) {
363 MockConnect
hanging_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
364 DeterministicSocketData
* hanging_non_alt_svc_socket
=
365 new DeterministicSocketData(NULL
, 0, NULL
, 0);
366 hanging_non_alt_svc_socket
->set_connect_data(hanging_connect
);
367 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
368 hanging_non_alt_svc_socket
);
369 alternate_vector_
.push_back(hanging_non_alt_svc_socket
);
373 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
376 HttpNetworkTransaction
* trans() { return trans_
.get(); }
377 void ResetTrans() { trans_
.reset(); }
378 TransactionHelperResult
& output() { return output_
; }
379 const HttpRequestInfo
& request() const { return request_
; }
380 const scoped_refptr
<HttpNetworkSession
>& session() const {
383 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
384 return session_deps_
;
386 int port() const { return port_
; }
387 SpdyNetworkTransactionTestParams
test_params() const {
392 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
393 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
394 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
395 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
396 HttpRequestInfo request_
;
397 RequestPriority priority_
;
398 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
399 scoped_refptr
<HttpNetworkSession
> session_
;
400 TransactionHelperResult output_
;
401 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
402 SSLVector ssl_vector_
;
403 TestCompletionCallback callback_
;
404 scoped_ptr
<HttpNetworkTransaction
> trans_
;
405 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
406 DataVector data_vector_
;
407 AlternateVector alternate_vector_
;
408 AlternateDeterministicVector alternate_deterministic_vector_
;
409 const BoundNetLog log_
;
410 SpdyNetworkTransactionTestParams test_params_
;
416 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
417 int expected_status
);
419 void ConnectStatusHelper(const MockRead
& status
);
421 const HttpRequestInfo
& CreateGetPushRequest() {
422 get_push_request_
.method
= "GET";
423 get_push_request_
.url
= GURL(GetDefaultUrlWithPath("/foo.dat"));
424 get_push_request_
.load_flags
= 0;
425 return get_push_request_
;
428 const HttpRequestInfo
& CreateGetRequest() {
429 if (!get_request_initialized_
) {
430 get_request_
.method
= "GET";
431 get_request_
.url
= GURL(GetDefaultUrl());
432 get_request_
.load_flags
= 0;
433 get_request_initialized_
= true;
438 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
439 if (!get_request_initialized_
) {
440 get_request_
.method
= "GET";
441 get_request_
.url
= GURL(GetDefaultUrl());
442 get_request_
.load_flags
= 0;
443 get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
444 get_request_initialized_
= true;
449 const HttpRequestInfo
& CreatePostRequest() {
450 if (!post_request_initialized_
) {
451 ScopedVector
<UploadElementReader
> element_readers
;
452 element_readers
.push_back(
453 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
454 upload_data_stream_
.reset(
455 new ElementsUploadDataStream(element_readers
.Pass(), 0));
457 post_request_
.method
= "POST";
458 post_request_
.url
= GURL(GetDefaultUrl());
459 post_request_
.upload_data_stream
= upload_data_stream_
.get();
460 post_request_initialized_
= true;
462 return post_request_
;
465 const HttpRequestInfo
& CreateFilePostRequest() {
466 if (!post_request_initialized_
) {
467 base::FilePath file_path
;
468 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
469 CHECK_EQ(static_cast<int>(kUploadDataSize
),
470 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
472 ScopedVector
<UploadElementReader
> element_readers
;
473 element_readers
.push_back(
474 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
479 upload_data_stream_
.reset(
480 new ElementsUploadDataStream(element_readers
.Pass(), 0));
482 post_request_
.method
= "POST";
483 post_request_
.url
= GURL(GetDefaultUrl());
484 post_request_
.upload_data_stream
= upload_data_stream_
.get();
485 post_request_initialized_
= true;
487 return post_request_
;
490 const HttpRequestInfo
& CreateUnreadableFilePostRequest() {
491 if (post_request_initialized_
)
492 return post_request_
;
494 base::FilePath file_path
;
495 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
496 CHECK_EQ(static_cast<int>(kUploadDataSize
),
497 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
498 CHECK(base::MakeFileUnreadable(file_path
));
500 ScopedVector
<UploadElementReader
> element_readers
;
501 element_readers
.push_back(
502 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
507 upload_data_stream_
.reset(
508 new ElementsUploadDataStream(element_readers
.Pass(), 0));
510 post_request_
.method
= "POST";
511 post_request_
.url
= GURL(GetDefaultUrl());
512 post_request_
.upload_data_stream
= upload_data_stream_
.get();
513 post_request_initialized_
= true;
514 return post_request_
;
517 const HttpRequestInfo
& CreateComplexPostRequest() {
518 if (!post_request_initialized_
) {
519 const int kFileRangeOffset
= 1;
520 const int kFileRangeLength
= 3;
521 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
523 base::FilePath file_path
;
524 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
525 CHECK_EQ(static_cast<int>(kUploadDataSize
),
526 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
528 ScopedVector
<UploadElementReader
> element_readers
;
529 element_readers
.push_back(
530 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
531 element_readers
.push_back(
532 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
537 element_readers
.push_back(new UploadBytesElementReader(
538 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
539 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
540 upload_data_stream_
.reset(
541 new ElementsUploadDataStream(element_readers
.Pass(), 0));
543 post_request_
.method
= "POST";
544 post_request_
.url
= GURL(GetDefaultUrl());
545 post_request_
.upload_data_stream
= upload_data_stream_
.get();
546 post_request_initialized_
= true;
548 return post_request_
;
551 const HttpRequestInfo
& CreateChunkedPostRequest() {
552 if (!chunked_post_request_initialized_
) {
553 upload_chunked_data_stream_
.reset(new ChunkedUploadDataStream(0));
554 chunked_post_request_
.method
= "POST";
555 chunked_post_request_
.url
= GURL(GetDefaultUrl());
556 chunked_post_request_
.upload_data_stream
=
557 upload_chunked_data_stream_
.get();
558 chunked_post_request_initialized_
= true;
560 return chunked_post_request_
;
563 // Read the result of a particular transaction, knowing that we've got
564 // multiple transactions in the read pipeline; so as we read, we may have
565 // to skip over data destined for other transactions while we consume
566 // the data for |trans|.
567 int ReadResult(HttpNetworkTransaction
* trans
,
568 StaticSocketDataProvider
* data
,
569 std::string
* result
) {
570 const int kSize
= 3000;
573 scoped_refptr
<IOBufferWithSize
> buf(new IOBufferWithSize(kSize
));
574 TestCompletionCallback callback
;
576 int rv
= trans
->Read(buf
.get(), kSize
, callback
.callback());
577 if (rv
== ERR_IO_PENDING
) {
578 // Multiple transactions may be in the data set. Keep pulling off
579 // reads until we complete our callback.
580 while (!callback
.have_result()) {
581 data
->CompleteRead();
582 base::RunLoop().RunUntilIdle();
584 rv
= callback
.WaitForResult();
585 } else if (rv
<= 0) {
588 result
->append(buf
->data(), rv
);
594 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
595 // This lengthy block is reaching into the pool to dig out the active
596 // session. Once we have the session, we verify that the streams are
597 // all closed and not leaked at this point.
598 const GURL
& url
= helper
.request().url
;
599 HostPortPair
host_port_pair(url
.host(), 443);
600 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
601 PRIVACY_MODE_DISABLED
);
603 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
604 base::WeakPtr
<SpdySession
> spdy_session
=
605 session
->spdy_session_pool()->FindAvailableSession(key
, log
);
606 ASSERT_TRUE(spdy_session
!= NULL
);
607 EXPECT_EQ(0u, spdy_session
->num_active_streams());
608 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
611 void RunServerPushTest(OrderedSocketData
* data
,
612 HttpResponseInfo
* response
,
613 HttpResponseInfo
* push_response
,
614 const std::string
& expected
) {
615 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
616 BoundNetLog(), GetParam(), NULL
);
617 helper
.RunPreTestSetup();
618 helper
.AddData(data
);
620 HttpNetworkTransaction
* trans
= helper
.trans();
622 // Start the transaction with basic parameters.
623 TestCompletionCallback callback
;
624 int rv
= trans
->Start(
625 &CreateGetRequest(), callback
.callback(), BoundNetLog());
626 EXPECT_EQ(ERR_IO_PENDING
, rv
);
627 rv
= callback
.WaitForResult();
629 // Request the pushed path.
630 scoped_ptr
<HttpNetworkTransaction
> trans2(
631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
633 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
634 EXPECT_EQ(ERR_IO_PENDING
, rv
);
635 base::RunLoop().RunUntilIdle();
637 // The data for the pushed path may be coming in more than 1 frame. Compile
638 // the results into a single string.
640 // Read the server push body.
642 ReadResult(trans2
.get(), data
, &result2
);
643 // Read the response body.
645 ReadResult(trans
, data
, &result
);
647 // Verify that we consumed all test data.
648 EXPECT_TRUE(data
->at_read_eof());
649 EXPECT_TRUE(data
->at_write_eof());
651 // Verify that the received push data is same as the expected push data.
652 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
654 << "||||| Expected data: "
657 // Verify the SYN_REPLY.
658 // Copy the response info, because trans goes away.
659 *response
= *trans
->GetResponseInfo();
660 *push_response
= *trans2
->GetResponseInfo();
662 VerifyStreamsClosed(helper
);
665 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
667 helper
->ResetTrans();
670 static void StartTransactionCallback(
671 const scoped_refptr
<HttpNetworkSession
>& session
,
674 scoped_ptr
<HttpNetworkTransaction
> trans(
675 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
676 TestCompletionCallback callback
;
677 HttpRequestInfo request
;
678 request
.method
= "GET";
680 request
.load_flags
= 0;
681 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
682 EXPECT_EQ(ERR_IO_PENDING
, rv
);
683 callback
.WaitForResult();
686 ChunkedUploadDataStream
* upload_chunked_data_stream() const {
687 return upload_chunked_data_stream_
.get();
690 const char* GetDefaultUrl() {
691 switch (GetParam().ssl_type
) {
692 case HTTP_SPDY_VIA_ALT_SVC
:
693 return "http://www.example.org";
694 case HTTPS_SPDY_VIA_NPN
:
695 return "https://www.example.org";
702 std::string
GetDefaultUrlWithPath(const char* path
) {
703 return std::string(GetDefaultUrl()) + path
;
706 SpdyTestUtil spdy_util_
;
709 scoped_ptr
<ChunkedUploadDataStream
> upload_chunked_data_stream_
;
710 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
711 bool get_request_initialized_
;
712 bool post_request_initialized_
;
713 bool chunked_post_request_initialized_
;
714 HttpRequestInfo get_request_
;
715 HttpRequestInfo post_request_
;
716 HttpRequestInfo chunked_post_request_
;
717 HttpRequestInfo get_push_request_
;
718 base::ScopedTempDir temp_dir_
;
721 //-----------------------------------------------------------------------------
722 // All tests are run with three different connection types: SPDY after NPN
723 // negotiation, SPDY without SSL, and SPDY with SSL.
725 // TODO(akalin): Use ::testing::Combine() when we are able to use
727 INSTANTIATE_TEST_CASE_P(
729 SpdyNetworkTransactionTest
,
731 SpdyNetworkTransactionTestParams(kProtoSPDY31
, HTTPS_SPDY_VIA_NPN
),
732 SpdyNetworkTransactionTestParams(kProtoSPDY31
, HTTP_SPDY_VIA_ALT_SVC
),
733 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, HTTPS_SPDY_VIA_NPN
),
734 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, HTTP_SPDY_VIA_ALT_SVC
),
735 SpdyNetworkTransactionTestParams(kProtoSPDY4
, HTTPS_SPDY_VIA_NPN
),
736 SpdyNetworkTransactionTestParams(kProtoSPDY4
, HTTP_SPDY_VIA_ALT_SVC
)));
738 // Verify HttpNetworkTransaction constructor.
739 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
740 scoped_ptr
<SpdySessionDependencies
> session_deps(
741 CreateSpdySessionDependencies(GetParam()));
742 scoped_refptr
<HttpNetworkSession
> session(
743 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
744 scoped_ptr
<HttpTransaction
> trans(
745 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
748 TEST_P(SpdyNetworkTransactionTest
, Get
) {
749 // Construct the request.
750 scoped_ptr
<SpdyFrame
> req(
751 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
752 MockWrite writes
[] = { CreateMockWrite(*req
) };
754 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
755 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
757 CreateMockRead(*resp
),
758 CreateMockRead(*body
),
759 MockRead(ASYNC
, 0, 0) // EOF
762 DelayedSocketData
data(1, reads
, arraysize(reads
),
763 writes
, arraysize(writes
));
764 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
765 BoundNetLog(), GetParam(), NULL
);
766 helper
.RunToCompletion(&data
);
767 TransactionHelperResult out
= helper
.output();
768 EXPECT_EQ(OK
, out
.rv
);
769 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
770 EXPECT_EQ("hello!", out
.response_data
);
773 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
774 for (RequestPriority p
= MINIMUM_PRIORITY
; p
<= MAXIMUM_PRIORITY
;
775 p
= RequestPriority(p
+ 1)) {
776 // Construct the request.
777 scoped_ptr
<SpdyFrame
> req(
778 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
779 MockWrite writes
[] = { CreateMockWrite(*req
) };
781 SpdyPriority spdy_prio
= 0;
782 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
783 // this repeats the RequestPriority-->SpdyPriority mapping from
784 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
785 // sure it's being done right.
786 if (spdy_util_
.spdy_version() < SPDY3
) {
789 EXPECT_EQ(0, spdy_prio
);
792 EXPECT_EQ(1, spdy_prio
);
796 EXPECT_EQ(2, spdy_prio
);
799 EXPECT_EQ(3, spdy_prio
);
807 EXPECT_EQ(0, spdy_prio
);
810 EXPECT_EQ(1, spdy_prio
);
813 EXPECT_EQ(2, spdy_prio
);
816 EXPECT_EQ(3, spdy_prio
);
819 EXPECT_EQ(4, spdy_prio
);
826 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
827 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
829 CreateMockRead(*resp
),
830 CreateMockRead(*body
),
831 MockRead(ASYNC
, 0, 0) // EOF
834 DelayedSocketData
data(1, reads
, arraysize(reads
),
835 writes
, arraysize(writes
));
836 HttpRequestInfo http_req
= CreateGetRequest();
838 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
840 helper
.RunToCompletion(&data
);
841 TransactionHelperResult out
= helper
.output();
842 EXPECT_EQ(OK
, out
.rv
);
843 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
844 EXPECT_EQ("hello!", out
.response_data
);
848 // Start three gets simultaniously; making sure that multiplexed
849 // streams work properly.
851 // This can't use the TransactionHelper method, since it only
852 // handles a single transaction, and finishes them as soon
853 // as it launches them.
855 // TODO(gavinp): create a working generalized TransactionHelper that
856 // can allow multiple streams in flight.
858 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
859 scoped_ptr
<SpdyFrame
> req(
860 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
861 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
862 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
863 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
865 scoped_ptr
<SpdyFrame
> req2(
866 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
867 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
868 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
869 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
871 scoped_ptr
<SpdyFrame
> req3(
872 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
873 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
874 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
875 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
877 MockWrite writes
[] = {
878 CreateMockWrite(*req
),
879 CreateMockWrite(*req2
),
880 CreateMockWrite(*req3
),
883 CreateMockRead(*resp
, 1),
884 CreateMockRead(*body
),
885 CreateMockRead(*resp2
, 4),
886 CreateMockRead(*body2
),
887 CreateMockRead(*resp3
, 7),
888 CreateMockRead(*body3
),
890 CreateMockRead(*fbody
),
891 CreateMockRead(*fbody2
),
892 CreateMockRead(*fbody3
),
894 MockRead(ASYNC
, 0, 0), // EOF
896 OrderedSocketData
data(reads
, arraysize(reads
),
897 writes
, arraysize(writes
));
898 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
901 TransactionHelperResult out
;
902 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
903 BoundNetLog(), GetParam(), NULL
);
904 helper
.RunPreTestSetup();
905 helper
.AddData(&data
);
906 // We require placeholder data because three get requests are sent out at
907 // the same time which results in three sockets being connected. The first
908 // on will negotiate SPDY and will be used for all requests.
909 helper
.AddData(&data_placeholder
);
910 helper
.AddData(&data_placeholder
);
911 scoped_ptr
<HttpNetworkTransaction
> trans1(
912 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
913 scoped_ptr
<HttpNetworkTransaction
> trans2(
914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
915 scoped_ptr
<HttpNetworkTransaction
> trans3(
916 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
918 TestCompletionCallback callback1
;
919 TestCompletionCallback callback2
;
920 TestCompletionCallback callback3
;
922 HttpRequestInfo httpreq1
= CreateGetRequest();
923 HttpRequestInfo httpreq2
= CreateGetRequest();
924 HttpRequestInfo httpreq3
= CreateGetRequest();
926 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
927 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
928 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
929 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
930 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
931 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
933 out
.rv
= callback1
.WaitForResult();
934 ASSERT_EQ(OK
, out
.rv
);
935 out
.rv
= callback3
.WaitForResult();
936 ASSERT_EQ(OK
, out
.rv
);
938 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
939 EXPECT_TRUE(response1
->headers
.get() != NULL
);
940 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
941 out
.status_line
= response1
->headers
->GetStatusLine();
942 out
.response_info
= *response1
;
944 trans2
->GetResponseInfo();
946 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
947 helper
.VerifyDataConsumed();
948 EXPECT_EQ(OK
, out
.rv
);
950 EXPECT_EQ(OK
, out
.rv
);
951 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
952 EXPECT_EQ("hello!hello!", out
.response_data
);
955 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
956 scoped_ptr
<SpdyFrame
> req(
957 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
958 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
959 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
960 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
962 scoped_ptr
<SpdyFrame
> req2(
963 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
964 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
965 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
966 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
968 MockWrite writes
[] = {
969 CreateMockWrite(*req
),
970 CreateMockWrite(*req2
),
973 CreateMockRead(*resp
, 1),
974 CreateMockRead(*body
),
975 CreateMockRead(*resp2
, 4),
976 CreateMockRead(*body2
),
977 CreateMockRead(*fbody
),
978 CreateMockRead(*fbody2
),
979 MockRead(ASYNC
, 0, 0), // EOF
981 OrderedSocketData
data(reads
, arraysize(reads
),
982 writes
, arraysize(writes
));
984 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
985 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
986 data_placeholder
.set_connect_data(never_finishing_connect
);
989 TransactionHelperResult out
;
990 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
991 BoundNetLog(), GetParam(), NULL
);
992 helper
.RunPreTestSetup();
993 helper
.AddData(&data
);
994 // We require placeholder data because two requests are sent out at
995 // the same time which results in two sockets being connected. The first
996 // on will negotiate SPDY and will be used for all requests.
997 helper
.AddData(&data_placeholder
);
998 scoped_ptr
<HttpNetworkTransaction
> trans1(
999 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1000 scoped_ptr
<HttpNetworkTransaction
> trans2(
1001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1003 TestCompletionCallback callback1
;
1004 TestCompletionCallback callback2
;
1006 HttpRequestInfo httpreq1
= CreateGetRequest();
1007 HttpRequestInfo httpreq2
= CreateGetRequest();
1009 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1010 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1011 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1012 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1014 out
.rv
= callback1
.WaitForResult();
1015 ASSERT_EQ(OK
, out
.rv
);
1016 out
.rv
= callback2
.WaitForResult();
1017 ASSERT_EQ(OK
, out
.rv
);
1019 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1020 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1021 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1022 out
.status_line
= response1
->headers
->GetStatusLine();
1023 out
.response_info
= *response1
;
1024 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1025 EXPECT_EQ(OK
, out
.rv
);
1026 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1027 EXPECT_EQ("hello!hello!", out
.response_data
);
1029 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1030 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1031 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1032 out
.status_line
= response2
->headers
->GetStatusLine();
1033 out
.response_info
= *response2
;
1034 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1035 EXPECT_EQ(OK
, out
.rv
);
1036 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1037 EXPECT_EQ("hello!hello!", out
.response_data
);
1039 helper
.VerifyDataConsumed();
1042 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
1043 scoped_ptr
<SpdyFrame
> req(
1044 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1045 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1046 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1047 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1049 scoped_ptr
<SpdyFrame
> req2(
1050 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1051 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1052 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1053 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1055 MockWrite writes
[] = {
1056 CreateMockWrite(*req
),
1057 CreateMockWrite(*req2
),
1059 MockRead reads
[] = {
1060 CreateMockRead(*resp
, 1),
1061 CreateMockRead(*body
),
1062 CreateMockRead(*resp2
, 4),
1063 CreateMockRead(*body2
),
1064 CreateMockRead(*fbody
),
1065 CreateMockRead(*fbody2
),
1066 MockRead(ASYNC
, 0, 0), // EOF
1068 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
1069 writes
, arraysize(writes
));
1071 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1073 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1074 data_placeholder
.set_connect_data(never_finishing_connect
);
1077 TransactionHelperResult out
;
1078 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1079 BoundNetLog(), GetParam(), NULL
);
1080 helper
.RunPreTestSetup();
1081 helper
.AddData(&preconnect_data
);
1082 // We require placeholder data because 3 connections are attempted (first is
1083 // the preconnect, 2nd and 3rd are the never finished connections.
1084 helper
.AddData(&data_placeholder
);
1085 helper
.AddData(&data_placeholder
);
1087 scoped_ptr
<HttpNetworkTransaction
> trans1(
1088 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1089 scoped_ptr
<HttpNetworkTransaction
> trans2(
1090 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1092 TestCompletionCallback callback1
;
1093 TestCompletionCallback callback2
;
1095 HttpRequestInfo httpreq
= CreateGetRequest();
1097 // Preconnect the first.
1098 SSLConfig preconnect_ssl_config
;
1099 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1100 HttpStreamFactory
* http_stream_factory
=
1101 helper
.session()->http_stream_factory();
1102 helper
.session()->GetNextProtos(&preconnect_ssl_config
.next_protos
);
1104 http_stream_factory
->PreconnectStreams(
1105 1, httpreq
, DEFAULT_PRIORITY
,
1106 preconnect_ssl_config
, preconnect_ssl_config
);
1108 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1109 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1110 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1111 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1113 out
.rv
= callback1
.WaitForResult();
1114 ASSERT_EQ(OK
, out
.rv
);
1115 out
.rv
= callback2
.WaitForResult();
1116 ASSERT_EQ(OK
, out
.rv
);
1118 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1119 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1120 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1121 out
.status_line
= response1
->headers
->GetStatusLine();
1122 out
.response_info
= *response1
;
1123 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1124 EXPECT_EQ(OK
, out
.rv
);
1125 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1126 EXPECT_EQ("hello!hello!", out
.response_data
);
1128 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1129 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1130 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1131 out
.status_line
= response2
->headers
->GetStatusLine();
1132 out
.response_info
= *response2
;
1133 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1134 EXPECT_EQ(OK
, out
.rv
);
1135 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1136 EXPECT_EQ("hello!hello!", out
.response_data
);
1138 helper
.VerifyDataConsumed();
1141 // Similar to ThreeGets above, however this test adds a SETTINGS
1142 // frame. The SETTINGS frame is read during the IO loop waiting on
1143 // the first transaction completion, and sets a maximum concurrent
1144 // stream limit of 1. This means that our IO loop exists after the
1145 // second transaction completes, so we can assert on read_index().
1146 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1147 // Construct the request.
1148 scoped_ptr
<SpdyFrame
> req(
1149 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1150 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1151 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1152 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1154 scoped_ptr
<SpdyFrame
> req2(
1155 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1156 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1157 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1158 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1160 scoped_ptr
<SpdyFrame
> req3(
1161 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1162 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1163 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1164 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1166 SettingsMap settings
;
1167 const uint32 max_concurrent_streams
= 1;
1168 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1169 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1170 scoped_ptr
<SpdyFrame
> settings_frame(
1171 spdy_util_
.ConstructSpdySettings(settings
));
1172 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1174 MockWrite writes
[] = {
1175 CreateMockWrite(*req
),
1176 CreateMockWrite(*settings_ack
, 2),
1177 CreateMockWrite(*req2
),
1178 CreateMockWrite(*req3
),
1181 MockRead reads
[] = {
1182 CreateMockRead(*settings_frame
, 1),
1183 CreateMockRead(*resp
),
1184 CreateMockRead(*body
),
1185 CreateMockRead(*fbody
),
1186 CreateMockRead(*resp2
, 8),
1187 CreateMockRead(*body2
),
1188 CreateMockRead(*fbody2
),
1189 CreateMockRead(*resp3
, 13),
1190 CreateMockRead(*body3
),
1191 CreateMockRead(*fbody3
),
1193 MockRead(ASYNC
, 0, 0), // EOF
1196 OrderedSocketData
data(reads
, arraysize(reads
),
1197 writes
, arraysize(writes
));
1200 TransactionHelperResult out
;
1202 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1203 BoundNetLog(), GetParam(), NULL
);
1204 helper
.RunPreTestSetup();
1205 helper
.AddData(&data
);
1206 scoped_ptr
<HttpNetworkTransaction
> trans1(
1207 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1208 scoped_ptr
<HttpNetworkTransaction
> trans2(
1209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1210 scoped_ptr
<HttpNetworkTransaction
> trans3(
1211 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1213 TestCompletionCallback callback1
;
1214 TestCompletionCallback callback2
;
1215 TestCompletionCallback callback3
;
1217 HttpRequestInfo httpreq1
= CreateGetRequest();
1218 HttpRequestInfo httpreq2
= CreateGetRequest();
1219 HttpRequestInfo httpreq3
= CreateGetRequest();
1221 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1222 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1223 // Run transaction 1 through quickly to force a read of our SETTINGS
1225 out
.rv
= callback1
.WaitForResult();
1226 ASSERT_EQ(OK
, out
.rv
);
1228 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1229 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1230 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1231 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1232 out
.rv
= callback2
.WaitForResult();
1233 ASSERT_EQ(OK
, out
.rv
);
1234 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1236 out
.rv
= callback3
.WaitForResult();
1237 ASSERT_EQ(OK
, out
.rv
);
1239 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1240 ASSERT_TRUE(response1
!= NULL
);
1241 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1242 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1243 out
.status_line
= response1
->headers
->GetStatusLine();
1244 out
.response_info
= *response1
;
1245 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1246 EXPECT_EQ(OK
, out
.rv
);
1247 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1248 EXPECT_EQ("hello!hello!", out
.response_data
);
1250 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1251 out
.status_line
= response2
->headers
->GetStatusLine();
1252 out
.response_info
= *response2
;
1253 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1254 EXPECT_EQ(OK
, out
.rv
);
1255 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1256 EXPECT_EQ("hello!hello!", out
.response_data
);
1258 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1259 out
.status_line
= response3
->headers
->GetStatusLine();
1260 out
.response_info
= *response3
;
1261 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1262 EXPECT_EQ(OK
, out
.rv
);
1263 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1264 EXPECT_EQ("hello!hello!", out
.response_data
);
1266 helper
.VerifyDataConsumed();
1268 EXPECT_EQ(OK
, out
.rv
);
1271 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1272 // a fourth transaction. The third and fourth transactions have
1273 // different data ("hello!" vs "hello!hello!") and because of the
1274 // user specified priority, we expect to see them inverted in
1275 // the response from the server.
1276 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1277 // Construct the request.
1278 scoped_ptr
<SpdyFrame
> req(
1279 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1280 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1281 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1282 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1284 scoped_ptr
<SpdyFrame
> req2(
1285 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1286 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1287 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1288 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1290 scoped_ptr
<SpdyFrame
> req4(
1291 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1292 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1293 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1295 scoped_ptr
<SpdyFrame
> req3(
1296 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1297 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1298 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1299 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1301 SettingsMap settings
;
1302 const uint32 max_concurrent_streams
= 1;
1303 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1304 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1305 scoped_ptr
<SpdyFrame
> settings_frame(
1306 spdy_util_
.ConstructSpdySettings(settings
));
1307 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1309 MockWrite writes
[] = { CreateMockWrite(*req
),
1310 CreateMockWrite(*settings_ack
, 2),
1311 CreateMockWrite(*req2
),
1312 CreateMockWrite(*req4
),
1313 CreateMockWrite(*req3
),
1315 MockRead reads
[] = {
1316 CreateMockRead(*settings_frame
, 1),
1317 CreateMockRead(*resp
),
1318 CreateMockRead(*body
),
1319 CreateMockRead(*fbody
),
1320 CreateMockRead(*resp2
, 8),
1321 CreateMockRead(*body2
),
1322 CreateMockRead(*fbody2
),
1323 CreateMockRead(*resp4
, 14),
1324 CreateMockRead(*fbody4
),
1325 CreateMockRead(*resp3
, 17),
1326 CreateMockRead(*body3
),
1327 CreateMockRead(*fbody3
),
1329 MockRead(ASYNC
, 0, 0), // EOF
1332 OrderedSocketData
data(reads
, arraysize(reads
),
1333 writes
, arraysize(writes
));
1336 TransactionHelperResult out
;
1337 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1338 BoundNetLog(), GetParam(), NULL
);
1339 helper
.RunPreTestSetup();
1340 helper
.AddData(&data
);
1341 scoped_ptr
<HttpNetworkTransaction
> trans1(
1342 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1343 scoped_ptr
<HttpNetworkTransaction
> trans2(
1344 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1345 scoped_ptr
<HttpNetworkTransaction
> trans3(
1346 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1347 scoped_ptr
<HttpNetworkTransaction
> trans4(
1348 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1350 TestCompletionCallback callback1
;
1351 TestCompletionCallback callback2
;
1352 TestCompletionCallback callback3
;
1353 TestCompletionCallback callback4
;
1355 HttpRequestInfo httpreq1
= CreateGetRequest();
1356 HttpRequestInfo httpreq2
= CreateGetRequest();
1357 HttpRequestInfo httpreq3
= CreateGetRequest();
1358 HttpRequestInfo httpreq4
= CreateGetRequest();
1360 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1361 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1362 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1363 out
.rv
= callback1
.WaitForResult();
1364 ASSERT_EQ(OK
, out
.rv
);
1366 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1367 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1368 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1369 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1370 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1371 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1373 out
.rv
= callback2
.WaitForResult();
1374 ASSERT_EQ(OK
, out
.rv
);
1375 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1377 out
.rv
= callback3
.WaitForResult();
1378 ASSERT_EQ(OK
, out
.rv
);
1380 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1381 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1382 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1383 out
.status_line
= response1
->headers
->GetStatusLine();
1384 out
.response_info
= *response1
;
1385 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1386 EXPECT_EQ(OK
, out
.rv
);
1387 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1388 EXPECT_EQ("hello!hello!", out
.response_data
);
1390 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1391 out
.status_line
= response2
->headers
->GetStatusLine();
1392 out
.response_info
= *response2
;
1393 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1394 EXPECT_EQ(OK
, out
.rv
);
1395 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1396 EXPECT_EQ("hello!hello!", out
.response_data
);
1398 // notice: response3 gets two hellos, response4 gets one
1399 // hello, so we know dequeuing priority was respected.
1400 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1401 out
.status_line
= response3
->headers
->GetStatusLine();
1402 out
.response_info
= *response3
;
1403 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1404 EXPECT_EQ(OK
, out
.rv
);
1405 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1406 EXPECT_EQ("hello!hello!", out
.response_data
);
1408 out
.rv
= callback4
.WaitForResult();
1409 EXPECT_EQ(OK
, out
.rv
);
1410 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1411 out
.status_line
= response4
->headers
->GetStatusLine();
1412 out
.response_info
= *response4
;
1413 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1414 EXPECT_EQ(OK
, out
.rv
);
1415 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1416 EXPECT_EQ("hello!", out
.response_data
);
1417 helper
.VerifyDataConsumed();
1418 EXPECT_EQ(OK
, out
.rv
);
1421 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1422 // deletes a session in the middle of the transaction to insure
1423 // that we properly remove pendingcreatestream objects from
1425 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1426 // Construct the request.
1427 scoped_ptr
<SpdyFrame
> req(
1428 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1429 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1430 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1431 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1433 scoped_ptr
<SpdyFrame
> req2(
1434 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1435 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1436 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1437 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1439 SettingsMap settings
;
1440 const uint32 max_concurrent_streams
= 1;
1441 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1442 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1443 scoped_ptr
<SpdyFrame
> settings_frame(
1444 spdy_util_
.ConstructSpdySettings(settings
));
1445 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1447 MockWrite writes
[] = {
1448 CreateMockWrite(*req
),
1449 CreateMockWrite(*settings_ack
, 2),
1450 CreateMockWrite(*req2
),
1452 MockRead reads
[] = {
1453 CreateMockRead(*settings_frame
, 1),
1454 CreateMockRead(*resp
),
1455 CreateMockRead(*body
),
1456 CreateMockRead(*fbody
),
1457 CreateMockRead(*resp2
, 8),
1458 CreateMockRead(*body2
),
1459 CreateMockRead(*fbody2
),
1460 MockRead(ASYNC
, 0, 0), // EOF
1463 OrderedSocketData
data(reads
, arraysize(reads
),
1464 writes
, arraysize(writes
));
1467 TransactionHelperResult out
;
1468 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1469 BoundNetLog(), GetParam(), NULL
);
1470 helper
.RunPreTestSetup();
1471 helper
.AddData(&data
);
1472 scoped_ptr
<HttpNetworkTransaction
> trans1(
1473 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1474 scoped_ptr
<HttpNetworkTransaction
> trans2(
1475 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1476 scoped_ptr
<HttpNetworkTransaction
> trans3(
1477 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1479 TestCompletionCallback callback1
;
1480 TestCompletionCallback callback2
;
1481 TestCompletionCallback callback3
;
1483 HttpRequestInfo httpreq1
= CreateGetRequest();
1484 HttpRequestInfo httpreq2
= CreateGetRequest();
1485 HttpRequestInfo httpreq3
= CreateGetRequest();
1487 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1488 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1489 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1490 out
.rv
= callback1
.WaitForResult();
1491 ASSERT_EQ(OK
, out
.rv
);
1493 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1494 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1495 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1496 delete trans3
.release();
1497 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1498 out
.rv
= callback2
.WaitForResult();
1499 ASSERT_EQ(OK
, out
.rv
);
1501 EXPECT_EQ(8U, data
.read_index());
1503 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1504 ASSERT_TRUE(response1
!= NULL
);
1505 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1506 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1507 out
.status_line
= response1
->headers
->GetStatusLine();
1508 out
.response_info
= *response1
;
1509 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1510 EXPECT_EQ(OK
, out
.rv
);
1511 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1512 EXPECT_EQ("hello!hello!", out
.response_data
);
1514 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1515 ASSERT_TRUE(response2
!= NULL
);
1516 out
.status_line
= response2
->headers
->GetStatusLine();
1517 out
.response_info
= *response2
;
1518 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1519 EXPECT_EQ(OK
, out
.rv
);
1520 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1521 EXPECT_EQ("hello!hello!", out
.response_data
);
1522 helper
.VerifyDataConsumed();
1523 EXPECT_EQ(OK
, out
.rv
);
1528 // The KillerCallback will delete the transaction on error as part of the
1530 class KillerCallback
: public TestCompletionCallbackBase
{
1532 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1533 : transaction_(transaction
),
1534 callback_(base::Bind(&KillerCallback::OnComplete
,
1535 base::Unretained(this))) {
1538 ~KillerCallback() override
{}
1540 const CompletionCallback
& callback() const { return callback_
; }
1543 void OnComplete(int result
) {
1545 delete transaction_
;
1550 HttpNetworkTransaction
* transaction_
;
1551 CompletionCallback callback_
;
1556 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1557 // closes the socket while we have a pending transaction waiting for
1558 // a pending stream creation. http://crbug.com/52901
1559 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1560 // Construct the request.
1561 scoped_ptr
<SpdyFrame
> req(
1562 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1563 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1564 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1565 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1567 scoped_ptr
<SpdyFrame
> req2(
1568 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1569 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1571 SettingsMap settings
;
1572 const uint32 max_concurrent_streams
= 1;
1573 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1574 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1575 scoped_ptr
<SpdyFrame
> settings_frame(
1576 spdy_util_
.ConstructSpdySettings(settings
));
1577 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1579 MockWrite writes
[] = {
1580 CreateMockWrite(*req
),
1581 CreateMockWrite(*settings_ack
, 2),
1582 CreateMockWrite(*req2
),
1584 MockRead reads
[] = {
1585 CreateMockRead(*settings_frame
, 1),
1586 CreateMockRead(*resp
),
1587 CreateMockRead(*body
),
1588 CreateMockRead(*fin_body
),
1589 CreateMockRead(*resp2
, 8),
1590 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1593 OrderedSocketData
data(reads
, arraysize(reads
),
1594 writes
, arraysize(writes
));
1595 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1598 TransactionHelperResult out
;
1599 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1600 BoundNetLog(), GetParam(), NULL
);
1601 helper
.RunPreTestSetup();
1602 helper
.AddData(&data
);
1603 // We require placeholder data because three get requests are sent out, so
1604 // there needs to be three sets of SSL connection data.
1605 helper
.AddData(&data_placeholder
);
1606 helper
.AddData(&data_placeholder
);
1607 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1608 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1609 HttpNetworkTransaction
* trans3(
1610 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1612 TestCompletionCallback callback1
;
1613 TestCompletionCallback callback2
;
1614 KillerCallback
callback3(trans3
);
1616 HttpRequestInfo httpreq1
= CreateGetRequest();
1617 HttpRequestInfo httpreq2
= CreateGetRequest();
1618 HttpRequestInfo httpreq3
= CreateGetRequest();
1620 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1621 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1622 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1623 out
.rv
= callback1
.WaitForResult();
1624 ASSERT_EQ(OK
, out
.rv
);
1626 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1627 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1628 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1629 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1630 out
.rv
= callback3
.WaitForResult();
1631 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1633 EXPECT_EQ(6U, data
.read_index());
1635 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1636 ASSERT_TRUE(response1
!= NULL
);
1637 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1638 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1639 out
.status_line
= response1
->headers
->GetStatusLine();
1640 out
.response_info
= *response1
;
1641 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1642 EXPECT_EQ(OK
, out
.rv
);
1644 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1645 ASSERT_TRUE(response2
!= NULL
);
1646 out
.status_line
= response2
->headers
->GetStatusLine();
1647 out
.response_info
= *response2
;
1648 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1649 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1651 helper
.VerifyDataConsumed();
1654 // Test that a simple PUT request works.
1655 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1656 // Setup the request
1657 HttpRequestInfo request
;
1658 request
.method
= "PUT";
1659 request
.url
= GURL(GetDefaultUrl());
1661 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1662 spdy_util_
.ConstructPutHeaderBlock(GetDefaultUrl(), 0));
1663 scoped_ptr
<SpdyFrame
> req(
1664 spdy_util_
.ConstructSpdySyn(1, *put_headers
, LOWEST
, false, true));
1665 MockWrite writes
[] = {
1666 CreateMockWrite(*req
),
1669 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1670 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1671 MockRead reads
[] = {
1672 CreateMockRead(*resp
),
1673 CreateMockRead(*body
),
1674 MockRead(ASYNC
, 0, 0) // EOF
1677 DelayedSocketData
data(1, reads
, arraysize(reads
),
1678 writes
, arraysize(writes
));
1679 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1680 BoundNetLog(), GetParam(), NULL
);
1681 helper
.RunToCompletion(&data
);
1682 TransactionHelperResult out
= helper
.output();
1684 EXPECT_EQ(OK
, out
.rv
);
1685 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1688 // Test that a simple HEAD request works.
1689 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1690 // Setup the request
1691 HttpRequestInfo request
;
1692 request
.method
= "HEAD";
1693 request
.url
= GURL(GetDefaultUrl());
1695 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1696 spdy_util_
.ConstructHeadHeaderBlock(GetDefaultUrl(), 0));
1697 scoped_ptr
<SpdyFrame
> req(
1698 spdy_util_
.ConstructSpdySyn(1, *head_headers
, LOWEST
, false, true));
1699 MockWrite writes
[] = {
1700 CreateMockWrite(*req
),
1703 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1704 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1705 MockRead reads
[] = {
1706 CreateMockRead(*resp
),
1707 CreateMockRead(*body
),
1708 MockRead(ASYNC
, 0, 0) // EOF
1711 DelayedSocketData
data(1, reads
, arraysize(reads
),
1712 writes
, arraysize(writes
));
1713 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1714 BoundNetLog(), GetParam(), NULL
);
1715 helper
.RunToCompletion(&data
);
1716 TransactionHelperResult out
= helper
.output();
1718 EXPECT_EQ(OK
, out
.rv
);
1719 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1722 // Test that a simple POST works.
1723 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1724 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
1725 GetDefaultUrl(), 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1726 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1727 MockWrite writes
[] = {
1728 CreateMockWrite(*req
),
1729 CreateMockWrite(*body
), // POST upload frame
1732 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1733 MockRead reads
[] = {
1734 CreateMockRead(*resp
),
1735 CreateMockRead(*body
),
1736 MockRead(ASYNC
, 0, 0) // EOF
1739 DelayedSocketData
data(2, reads
, arraysize(reads
),
1740 writes
, arraysize(writes
));
1741 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
1742 BoundNetLog(), GetParam(), NULL
);
1743 helper
.RunToCompletion(&data
);
1744 TransactionHelperResult out
= helper
.output();
1745 EXPECT_EQ(OK
, out
.rv
);
1746 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1747 EXPECT_EQ("hello!", out
.response_data
);
1750 // Test that a POST with a file works.
1751 TEST_P(SpdyNetworkTransactionTest
, FilePost
) {
1752 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
1753 GetDefaultUrl(), 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1754 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1755 MockWrite writes
[] = {
1756 CreateMockWrite(*req
),
1757 CreateMockWrite(*body
), // POST upload frame
1760 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1761 MockRead reads
[] = {
1762 CreateMockRead(*resp
),
1763 CreateMockRead(*body
),
1764 MockRead(ASYNC
, 0, 0) // EOF
1767 DelayedSocketData
data(2, reads
, arraysize(reads
),
1768 writes
, arraysize(writes
));
1769 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(), DEFAULT_PRIORITY
,
1770 BoundNetLog(), GetParam(), NULL
);
1771 helper
.RunToCompletion(&data
);
1772 TransactionHelperResult out
= helper
.output();
1773 EXPECT_EQ(OK
, out
.rv
);
1774 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1775 EXPECT_EQ("hello!", out
.response_data
);
1778 // Test that a POST with a unreadable file fails.
1779 TEST_P(SpdyNetworkTransactionTest
, UnreadableFilePost
) {
1780 MockWrite writes
[] = {
1781 MockWrite(ASYNC
, 0, 0) // EOF
1783 MockRead reads
[] = {
1784 MockRead(ASYNC
, 0, 0) // EOF
1787 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1788 NormalSpdyTransactionHelper
helper(CreateUnreadableFilePostRequest(),
1790 BoundNetLog(), GetParam(), NULL
);
1791 helper
.RunPreTestSetup();
1792 helper
.AddData(&data
);
1793 helper
.RunDefaultTest();
1795 base::RunLoop().RunUntilIdle();
1796 helper
.VerifyDataNotConsumed();
1797 EXPECT_EQ(ERR_ACCESS_DENIED
, helper
.output().rv
);
1800 // Test that a complex POST works.
1801 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1802 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
1803 GetDefaultUrl(), 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1804 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1805 MockWrite writes
[] = {
1806 CreateMockWrite(*req
),
1807 CreateMockWrite(*body
), // POST upload frame
1810 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1811 MockRead reads
[] = {
1812 CreateMockRead(*resp
),
1813 CreateMockRead(*body
),
1814 MockRead(ASYNC
, 0, 0) // EOF
1817 DelayedSocketData
data(2, reads
, arraysize(reads
),
1818 writes
, arraysize(writes
));
1819 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1821 BoundNetLog(), GetParam(), NULL
);
1822 helper
.RunToCompletion(&data
);
1823 TransactionHelperResult out
= helper
.output();
1824 EXPECT_EQ(OK
, out
.rv
);
1825 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1826 EXPECT_EQ("hello!", out
.response_data
);
1829 // Test that a chunked POST works.
1830 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1831 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1832 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1833 MockWrite writes
[] = {
1834 CreateMockWrite(*req
),
1835 CreateMockWrite(*body
),
1838 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1839 MockRead reads
[] = {
1840 CreateMockRead(*resp
),
1841 CreateMockRead(*body
),
1842 MockRead(ASYNC
, 0, 0) // EOF
1845 DelayedSocketData
data(2, reads
, arraysize(reads
),
1846 writes
, arraysize(writes
));
1847 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1849 BoundNetLog(), GetParam(), NULL
);
1851 // These chunks get merged into a single frame when being sent.
1852 const int kFirstChunkSize
= kUploadDataSize
/2;
1853 upload_chunked_data_stream()->AppendData(kUploadData
, kFirstChunkSize
, false);
1854 upload_chunked_data_stream()->AppendData(
1855 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1857 helper
.RunToCompletion(&data
);
1858 TransactionHelperResult out
= helper
.output();
1859 EXPECT_EQ(OK
, out
.rv
);
1860 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1861 EXPECT_EQ(kUploadData
, out
.response_data
);
1864 // Test that a chunked POST works with chunks appended after transaction starts.
1865 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1866 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1867 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1868 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1869 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1870 MockWrite writes
[] = {
1871 CreateMockWrite(*req
),
1872 CreateMockWrite(*chunk1
),
1873 CreateMockWrite(*chunk2
),
1874 CreateMockWrite(*chunk3
),
1877 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1878 MockRead reads
[] = {
1879 CreateMockRead(*resp
),
1880 CreateMockRead(*chunk1
),
1881 CreateMockRead(*chunk2
),
1882 CreateMockRead(*chunk3
),
1883 MockRead(ASYNC
, 0, 0) // EOF
1886 DelayedSocketData
data(4, reads
, arraysize(reads
),
1887 writes
, arraysize(writes
));
1888 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1890 BoundNetLog(), GetParam(), NULL
);
1892 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1894 helper
.RunPreTestSetup();
1895 helper
.AddData(&data
);
1896 ASSERT_TRUE(helper
.StartDefaultTest());
1898 base::RunLoop().RunUntilIdle();
1899 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1900 base::RunLoop().RunUntilIdle();
1901 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
1903 helper
.FinishDefaultTest();
1904 helper
.VerifyDataConsumed();
1906 std::string expected_response
;
1907 expected_response
+= kUploadData
;
1908 expected_response
+= kUploadData
;
1909 expected_response
+= kUploadData
;
1911 TransactionHelperResult out
= helper
.output();
1912 EXPECT_EQ(OK
, out
.rv
);
1913 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1914 EXPECT_EQ(expected_response
, out
.response_data
);
1917 // Test that a POST without any post data works.
1918 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1919 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1920 // Setup the request
1921 HttpRequestInfo request
;
1922 request
.method
= "POST";
1923 request
.url
= GURL(GetDefaultUrl());
1924 // Create an empty UploadData.
1925 request
.upload_data_stream
= NULL
;
1927 // When request.upload_data_stream is NULL for post, content-length is
1928 // expected to be 0.
1929 scoped_ptr
<SpdyHeaderBlock
> req_block(
1930 spdy_util_
.ConstructPostHeaderBlock(GetDefaultUrl(), 0));
1931 scoped_ptr
<SpdyFrame
> req(
1932 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1934 MockWrite writes
[] = {
1935 CreateMockWrite(*req
),
1938 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1939 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1940 MockRead reads
[] = {
1941 CreateMockRead(*resp
),
1942 CreateMockRead(*body
),
1943 MockRead(ASYNC
, 0, 0) // EOF
1946 DelayedSocketData
data(1, reads
, arraysize(reads
),
1947 writes
, arraysize(writes
));
1949 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1950 BoundNetLog(), GetParam(), NULL
);
1951 helper
.RunToCompletion(&data
);
1952 TransactionHelperResult out
= helper
.output();
1953 EXPECT_EQ(OK
, out
.rv
);
1954 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1955 EXPECT_EQ("hello!", out
.response_data
);
1958 // Test that a simple POST works.
1959 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1960 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1961 // Create an empty UploadDataStream.
1962 ScopedVector
<UploadElementReader
> element_readers
;
1963 ElementsUploadDataStream
stream(element_readers
.Pass(), 0);
1965 // Setup the request
1966 HttpRequestInfo request
;
1967 request
.method
= "POST";
1968 request
.url
= GURL(GetDefaultUrl());
1969 request
.upload_data_stream
= &stream
;
1971 const uint64 kContentLength
= 0;
1973 scoped_ptr
<SpdyHeaderBlock
> req_block(
1974 spdy_util_
.ConstructPostHeaderBlock(GetDefaultUrl(), kContentLength
));
1975 scoped_ptr
<SpdyFrame
> req(
1976 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1978 MockWrite writes
[] = {
1979 CreateMockWrite(*req
),
1982 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1983 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1984 MockRead reads
[] = {
1985 CreateMockRead(*resp
),
1986 CreateMockRead(*body
),
1987 MockRead(ASYNC
, 0, 0) // EOF
1990 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1992 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1993 BoundNetLog(), GetParam(), NULL
);
1994 helper
.RunToCompletion(&data
);
1995 TransactionHelperResult out
= helper
.output();
1996 EXPECT_EQ(OK
, out
.rv
);
1997 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1998 EXPECT_EQ("hello!", out
.response_data
);
2001 // While we're doing a post, the server sends the reply before upload completes.
2002 TEST_P(SpdyNetworkTransactionTest
, ResponseBeforePostCompletes
) {
2003 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
2004 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2005 MockWrite writes
[] = {
2006 CreateMockWrite(*req
, 0),
2007 CreateMockWrite(*body
, 3),
2009 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2010 MockRead reads
[] = {
2011 CreateMockRead(*resp
, 1),
2012 CreateMockRead(*body
, 2),
2013 MockRead(ASYNC
, 0, 4) // EOF
2016 // Write the request headers, and read the complete response
2017 // while still waiting for chunked request data.
2018 DeterministicSocketData
data(reads
, arraysize(reads
),
2019 writes
, arraysize(writes
));
2020 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
2022 BoundNetLog(), GetParam(), NULL
);
2023 helper
.SetDeterministic();
2024 helper
.RunPreTestSetup();
2025 helper
.AddDeterministicData(&data
);
2027 ASSERT_TRUE(helper
.StartDefaultTest());
2029 // Process the request headers, SYN_REPLY, and response body.
2030 // The request body is still in flight.
2033 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
2034 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2036 // Finish sending the request body.
2037 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
2040 std::string response_body
;
2041 EXPECT_EQ(OK
, ReadTransaction(helper
.trans(), &response_body
));
2042 EXPECT_EQ(kUploadData
, response_body
);
2043 helper
.VerifyDataConsumed();
2046 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2047 // socket causes the TCP write to return zero. This test checks that the client
2048 // tries to queue up the RST_STREAM frame again.
2049 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2050 scoped_ptr
<SpdyFrame
> req(
2051 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2052 scoped_ptr
<SpdyFrame
> rst(
2053 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2054 MockWrite writes
[] = {
2055 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2056 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2057 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2060 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2061 MockRead reads
[] = {
2062 CreateMockRead(*resp
.get(), 1, ASYNC
),
2063 MockRead(ASYNC
, 0, 0, 4) // EOF
2066 DeterministicSocketData
data(reads
, arraysize(reads
),
2067 writes
, arraysize(writes
));
2068 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2069 BoundNetLog(), GetParam(), NULL
);
2070 helper
.SetDeterministic();
2071 helper
.RunPreTestSetup();
2072 helper
.AddDeterministicData(&data
);
2073 HttpNetworkTransaction
* trans
= helper
.trans();
2075 TestCompletionCallback callback
;
2076 int rv
= trans
->Start(
2077 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2078 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2082 helper
.ResetTrans();
2086 helper
.VerifyDataConsumed();
2089 // Test that the transaction doesn't crash when we don't have a reply.
2090 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2091 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2092 MockRead reads
[] = {
2093 CreateMockRead(*body
),
2094 MockRead(ASYNC
, 0, 0) // EOF
2097 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2098 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2099 BoundNetLog(), GetParam(), NULL
);
2100 helper
.RunToCompletion(&data
);
2101 TransactionHelperResult out
= helper
.output();
2102 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2105 // Test that the transaction doesn't crash when we get two replies on the same
2106 // stream ID. See http://crbug.com/45639.
2107 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2108 scoped_ptr
<SpdyFrame
> req(
2109 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2110 scoped_ptr
<SpdyFrame
> rst(
2111 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2112 MockWrite writes
[] = {
2113 CreateMockWrite(*req
),
2114 CreateMockWrite(*rst
),
2117 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2118 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2119 MockRead reads
[] = {
2120 CreateMockRead(*resp
),
2121 CreateMockRead(*resp
),
2122 CreateMockRead(*body
),
2123 MockRead(ASYNC
, 0, 0) // EOF
2126 DelayedSocketData
data(1, reads
, arraysize(reads
),
2127 writes
, arraysize(writes
));
2129 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2130 BoundNetLog(), GetParam(), NULL
);
2131 helper
.RunPreTestSetup();
2132 helper
.AddData(&data
);
2134 HttpNetworkTransaction
* trans
= helper
.trans();
2136 TestCompletionCallback callback
;
2137 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2138 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2139 rv
= callback
.WaitForResult();
2142 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2143 ASSERT_TRUE(response
!= NULL
);
2144 EXPECT_TRUE(response
->headers
.get() != NULL
);
2145 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2146 std::string response_data
;
2147 rv
= ReadTransaction(trans
, &response_data
);
2148 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2150 helper
.VerifyDataConsumed();
2153 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2154 // Construct the request.
2155 scoped_ptr
<SpdyFrame
> req(
2156 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2157 scoped_ptr
<SpdyFrame
> rst(
2158 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2159 MockWrite writes
[] = {
2160 CreateMockWrite(*req
),
2161 CreateMockWrite(*rst
),
2164 const char* const headers
[] = {
2165 "transfer-encoding", "chunked"
2167 scoped_ptr
<SpdyFrame
> resp(
2168 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2169 scoped_ptr
<SpdyFrame
> body(
2170 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2171 MockRead reads
[] = {
2172 CreateMockRead(*resp
),
2173 CreateMockRead(*body
),
2174 MockRead(ASYNC
, 0, 0) // EOF
2177 DelayedSocketData
data(1, reads
, arraysize(reads
),
2178 writes
, arraysize(writes
));
2179 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2180 BoundNetLog(), GetParam(), NULL
);
2181 helper
.RunToCompletion(&data
);
2182 TransactionHelperResult out
= helper
.output();
2183 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2185 helper
.session()->spdy_session_pool()->CloseAllSessions();
2186 helper
.VerifyDataConsumed();
2189 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2190 // Construct the request.
2191 scoped_ptr
<SpdyFrame
> req(
2192 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2193 scoped_ptr
<SpdyFrame
> rst(
2194 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2195 MockWrite writes
[] = {
2196 CreateMockWrite(*req
),
2197 CreateMockWrite(*rst
),
2200 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2201 const char* const headers
[] = {
2202 "transfer-encoding", "chunked"
2204 scoped_ptr
<SpdyFrame
> push(
2205 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2, 2, 1,
2206 GetDefaultUrlWithPath("/1").c_str()));
2207 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2208 MockRead reads
[] = {
2209 CreateMockRead(*resp
),
2210 CreateMockRead(*push
),
2211 CreateMockRead(*body
),
2212 MockRead(ASYNC
, 0, 0) // EOF
2215 DelayedSocketData
data(1, reads
, arraysize(reads
),
2216 writes
, arraysize(writes
));
2217 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2218 BoundNetLog(), GetParam(), NULL
);
2219 helper
.RunToCompletion(&data
);
2220 TransactionHelperResult out
= helper
.output();
2221 EXPECT_EQ(OK
, out
.rv
);
2222 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2223 EXPECT_EQ("hello!", out
.response_data
);
2225 helper
.session()->spdy_session_pool()->CloseAllSessions();
2226 helper
.VerifyDataConsumed();
2229 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2230 // Construct the request.
2231 scoped_ptr
<SpdyFrame
> req(
2232 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2233 MockWrite writes
[] = {
2234 CreateMockWrite(*req
),
2237 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2238 MockRead reads
[] = {
2239 CreateMockRead(*resp
),
2240 // This following read isn't used by the test, except during the
2241 // RunUntilIdle() call at the end since the SpdySession survives the
2242 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2243 // MockRead will do here.
2244 MockRead(ASYNC
, 0, 0) // EOF
2247 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2248 writes
, arraysize(writes
));
2250 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2251 BoundNetLog(), GetParam(), NULL
);
2252 helper
.RunPreTestSetup();
2253 helper
.AddData(&data
);
2254 HttpNetworkTransaction
* trans
= helper
.trans();
2256 TestCompletionCallback callback
;
2257 int rv
= trans
->Start(
2258 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2259 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2260 helper
.ResetTrans(); // Cancel the transaction.
2262 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2263 // MockClientSocketFactory) are still alive.
2264 base::RunLoop().RunUntilIdle();
2265 helper
.VerifyDataNotConsumed();
2268 // Verify that the client sends a Rst Frame upon cancelling the stream.
2269 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2270 scoped_ptr
<SpdyFrame
> req(
2271 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2272 scoped_ptr
<SpdyFrame
> rst(
2273 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2274 MockWrite writes
[] = {
2275 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2276 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2279 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2280 MockRead reads
[] = {
2281 CreateMockRead(*resp
, 1, ASYNC
),
2282 MockRead(ASYNC
, 0, 0, 3) // EOF
2285 DeterministicSocketData
data(reads
, arraysize(reads
),
2286 writes
, arraysize(writes
));
2288 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2291 helper
.SetDeterministic();
2292 helper
.RunPreTestSetup();
2293 helper
.AddDeterministicData(&data
);
2294 HttpNetworkTransaction
* trans
= helper
.trans();
2296 TestCompletionCallback callback
;
2298 int rv
= trans
->Start(
2299 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2300 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2304 helper
.ResetTrans();
2308 helper
.VerifyDataConsumed();
2311 // Verify that the client can correctly deal with the user callback attempting
2312 // to start another transaction on a session that is closing down. See
2313 // http://crbug.com/47455
2314 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2315 scoped_ptr
<SpdyFrame
> req(
2316 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2317 MockWrite writes
[] = { CreateMockWrite(*req
) };
2318 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2320 // The indicated length of this frame is longer than its actual length. When
2321 // the session receives an empty frame after this one, it shuts down the
2322 // session, and calls the read callback with the incomplete data.
2323 const uint8 kGetBodyFrame2
[] = {
2324 0x00, 0x00, 0x00, 0x01,
2325 0x01, 0x00, 0x00, 0x07,
2326 'h', 'e', 'l', 'l', 'o', '!',
2329 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2330 MockRead reads
[] = {
2331 CreateMockRead(*resp
, 2),
2332 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2333 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2334 arraysize(kGetBodyFrame2
), 4),
2335 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2336 MockRead(ASYNC
, 0, 0, 6), // EOF
2338 MockRead reads2
[] = {
2339 CreateMockRead(*resp
, 2),
2340 MockRead(ASYNC
, 0, 0, 3), // EOF
2343 OrderedSocketData
data(reads
, arraysize(reads
),
2344 writes
, arraysize(writes
));
2345 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2346 writes2
, arraysize(writes2
));
2348 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2349 BoundNetLog(), GetParam(), NULL
);
2350 helper
.RunPreTestSetup();
2351 helper
.AddData(&data
);
2352 helper
.AddData(&data2
);
2353 HttpNetworkTransaction
* trans
= helper
.trans();
2355 // Start the transaction with basic parameters.
2356 TestCompletionCallback callback
;
2357 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2358 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2359 rv
= callback
.WaitForResult();
2361 const int kSize
= 3000;
2362 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSize
));
2365 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2366 helper
.session(), GURL(GetDefaultUrl())));
2367 // This forces an err_IO_pending, which sets the callback.
2368 data
.CompleteRead();
2369 // This finishes the read.
2370 data
.CompleteRead();
2371 helper
.VerifyDataConsumed();
2374 // Verify that the client can correctly deal with the user callback deleting the
2375 // transaction. Failures will usually be valgrind errors. See
2376 // http://crbug.com/46925
2377 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2378 scoped_ptr
<SpdyFrame
> req(
2379 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2380 MockWrite writes
[] = { CreateMockWrite(*req
) };
2382 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2383 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2384 MockRead reads
[] = {
2385 CreateMockRead(*resp
.get(), 2),
2386 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2387 CreateMockRead(*body
.get(), 4),
2388 MockRead(ASYNC
, 0, 0, 5), // EOF
2391 OrderedSocketData
data(reads
, arraysize(reads
),
2392 writes
, arraysize(writes
));
2394 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2395 BoundNetLog(), GetParam(), NULL
);
2396 helper
.RunPreTestSetup();
2397 helper
.AddData(&data
);
2398 HttpNetworkTransaction
* trans
= helper
.trans();
2400 // Start the transaction with basic parameters.
2401 TestCompletionCallback callback
;
2402 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2403 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2404 rv
= callback
.WaitForResult();
2406 // Setup a user callback which will delete the session, and clear out the
2407 // memory holding the stream object. Note that the callback deletes trans.
2408 const int kSize
= 3000;
2409 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSize
));
2413 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2414 base::Unretained(&helper
)));
2415 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2416 data
.CompleteRead();
2418 // Finish running rest of tasks.
2419 base::RunLoop().RunUntilIdle();
2420 helper
.VerifyDataConsumed();
2423 // Send a spdy request to www.example.org that gets redirected to www.foo.com.
2424 TEST_P(SpdyNetworkTransactionTest
, DISABLED_RedirectGetRequest
) {
2425 scoped_ptr
<SpdyHeaderBlock
> headers(
2426 spdy_util_
.ConstructGetHeaderBlock(GetDefaultUrl()));
2427 (*headers
)["user-agent"] = "";
2428 (*headers
)["accept-encoding"] = "gzip, deflate";
2429 scoped_ptr
<SpdyHeaderBlock
> headers2(
2430 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2431 (*headers2
)["user-agent"] = "";
2432 (*headers2
)["accept-encoding"] = "gzip, deflate";
2434 // Setup writes/reads to www.example.org
2435 scoped_ptr
<SpdyFrame
> req(
2436 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2437 scoped_ptr
<SpdyFrame
> req2(
2438 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2439 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2440 MockWrite writes
[] = {
2441 CreateMockWrite(*req
, 1),
2443 MockRead reads
[] = {
2444 CreateMockRead(*resp
, 2),
2445 MockRead(ASYNC
, 0, 0, 3) // EOF
2448 // Setup writes/reads to www.foo.com
2449 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2450 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2451 MockWrite writes2
[] = {
2452 CreateMockWrite(*req2
, 1),
2454 MockRead reads2
[] = {
2455 CreateMockRead(*resp2
, 2),
2456 CreateMockRead(*body2
, 3),
2457 MockRead(ASYNC
, 0, 0, 4) // EOF
2459 OrderedSocketData
data(reads
, arraysize(reads
),
2460 writes
, arraysize(writes
));
2461 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2462 writes2
, arraysize(writes2
));
2464 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2467 SpdyURLRequestContext
spdy_url_request_context(GetParam().protocol
);
2468 scoped_ptr
<URLRequest
> r(spdy_url_request_context
.CreateRequest(
2469 GURL(GetDefaultUrl()), DEFAULT_PRIORITY
, &d
));
2470 spdy_url_request_context
.socket_factory().
2471 AddSocketDataProvider(&data
);
2472 spdy_url_request_context
.socket_factory().
2473 AddSocketDataProvider(&data2
);
2475 d
.set_quit_on_redirect(true);
2477 base::RunLoop().Run();
2479 EXPECT_EQ(1, d
.received_redirect_count());
2481 r
->FollowDeferredRedirect();
2482 base::RunLoop().Run();
2483 EXPECT_EQ(1, d
.response_started_count());
2484 EXPECT_FALSE(d
.received_data_before_response());
2485 EXPECT_EQ(URLRequestStatus::SUCCESS
, r
->status().status());
2486 std::string
contents("hello!");
2487 EXPECT_EQ(contents
, d
.data_received());
2489 EXPECT_TRUE(data
.at_read_eof());
2490 EXPECT_TRUE(data
.at_write_eof());
2491 EXPECT_TRUE(data2
.at_read_eof());
2492 EXPECT_TRUE(data2
.at_write_eof());
2495 // Send a spdy request to www.example.org. Get a pushed stream that redirects to
2497 TEST_P(SpdyNetworkTransactionTest
, DISABLED_RedirectServerPush
) {
2498 scoped_ptr
<SpdyHeaderBlock
> headers(
2499 spdy_util_
.ConstructGetHeaderBlock(GetDefaultUrl()));
2500 (*headers
)["user-agent"] = "";
2501 (*headers
)["accept-encoding"] = "gzip, deflate";
2503 // Setup writes/reads to www.example.org
2504 scoped_ptr
<SpdyFrame
> req(
2505 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2506 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2507 scoped_ptr
<SpdyFrame
> rep(spdy_util_
.ConstructSpdyPush(
2508 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2509 "301 Moved Permanently", "http://www.foo.com/index.php"));
2510 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2511 scoped_ptr
<SpdyFrame
> rst(
2512 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
2513 MockWrite writes
[] = {
2514 CreateMockWrite(*req
, 1),
2515 CreateMockWrite(*rst
, 6),
2517 MockRead reads
[] = {
2518 CreateMockRead(*resp
, 2),
2519 CreateMockRead(*rep
, 3),
2520 CreateMockRead(*body
, 4),
2521 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2522 MockRead(ASYNC
, 0, 0, 7) // EOF
2525 // Setup writes/reads to www.foo.com
2526 scoped_ptr
<SpdyHeaderBlock
> headers2(
2527 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2528 (*headers2
)["user-agent"] = "";
2529 (*headers2
)["accept-encoding"] = "gzip, deflate";
2530 scoped_ptr
<SpdyFrame
> req2(
2531 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2532 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2533 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2534 MockWrite writes2
[] = {
2535 CreateMockWrite(*req2
, 1),
2537 MockRead reads2
[] = {
2538 CreateMockRead(*resp2
, 2),
2539 CreateMockRead(*body2
, 3),
2540 MockRead(ASYNC
, 0, 0, 5) // EOF
2542 OrderedSocketData
data(reads
, arraysize(reads
),
2543 writes
, arraysize(writes
));
2544 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2545 writes2
, arraysize(writes2
));
2547 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2550 SpdyURLRequestContext
spdy_url_request_context(GetParam().protocol
);
2552 scoped_ptr
<URLRequest
> r(spdy_url_request_context
.CreateRequest(
2553 GURL(GetDefaultUrl()), DEFAULT_PRIORITY
, &d
));
2554 spdy_url_request_context
.socket_factory().
2555 AddSocketDataProvider(&data
);
2558 base::RunLoop().Run();
2560 EXPECT_EQ(0, d
.received_redirect_count());
2561 std::string
contents("hello!");
2562 EXPECT_EQ(contents
, d
.data_received());
2564 scoped_ptr
<URLRequest
> r2(spdy_url_request_context
.CreateRequest(
2565 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY
, &d2
));
2566 spdy_url_request_context
.socket_factory().
2567 AddSocketDataProvider(&data2
);
2569 d2
.set_quit_on_redirect(true);
2571 base::RunLoop().Run();
2572 EXPECT_EQ(1, d2
.received_redirect_count());
2574 r2
->FollowDeferredRedirect();
2575 base::RunLoop().Run();
2576 EXPECT_EQ(1, d2
.response_started_count());
2577 EXPECT_FALSE(d2
.received_data_before_response());
2578 EXPECT_EQ(URLRequestStatus::SUCCESS
, r2
->status().status());
2579 std::string
contents2("hello!");
2580 EXPECT_EQ(contents2
, d2
.data_received());
2582 data
.CompleteRead();
2583 data2
.CompleteRead();
2584 EXPECT_TRUE(data
.at_read_eof());
2585 EXPECT_TRUE(data
.at_write_eof());
2586 EXPECT_TRUE(data2
.at_read_eof());
2587 EXPECT_TRUE(data2
.at_write_eof());
2590 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2591 scoped_ptr
<SpdyFrame
> stream1_syn(
2592 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2593 scoped_ptr
<SpdyFrame
> stream1_body(
2594 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2595 MockWrite writes
[] = {
2596 CreateMockWrite(*stream1_syn
, 1),
2599 scoped_ptr
<SpdyFrame
>
2600 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2601 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2602 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2603 const char kPushedData
[] = "pushed";
2604 scoped_ptr
<SpdyFrame
> stream2_body(
2605 spdy_util_
.ConstructSpdyBodyFrame(
2606 2, kPushedData
, strlen(kPushedData
), true));
2607 MockRead reads
[] = {
2608 CreateMockRead(*stream1_reply
, 2),
2609 CreateMockRead(*stream2_syn
, 3),
2610 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2611 CreateMockRead(*stream2_body
, 5),
2612 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2615 HttpResponseInfo response
;
2616 HttpResponseInfo response2
;
2617 std::string
expected_push_result("pushed");
2618 OrderedSocketData
data(reads
, arraysize(reads
),
2619 writes
, arraysize(writes
));
2620 RunServerPushTest(&data
,
2623 expected_push_result
);
2625 // Verify the SYN_REPLY.
2626 EXPECT_TRUE(response
.headers
.get() != NULL
);
2627 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2629 // Verify the pushed stream.
2630 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2631 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2634 TEST_P(SpdyNetworkTransactionTest
, ServerPushBeforeSynReply
) {
2635 scoped_ptr
<SpdyFrame
> stream1_syn(
2636 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2637 scoped_ptr
<SpdyFrame
> stream1_body(
2638 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2639 MockWrite writes
[] = {
2640 CreateMockWrite(*stream1_syn
, 1),
2643 scoped_ptr
<SpdyFrame
>
2644 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2645 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2646 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2647 const char kPushedData
[] = "pushed";
2648 scoped_ptr
<SpdyFrame
> stream2_body(
2649 spdy_util_
.ConstructSpdyBodyFrame(
2650 2, kPushedData
, strlen(kPushedData
), true));
2651 MockRead reads
[] = {
2652 CreateMockRead(*stream2_syn
, 2),
2653 CreateMockRead(*stream1_reply
, 3),
2654 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2655 CreateMockRead(*stream2_body
, 5),
2656 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2659 HttpResponseInfo response
;
2660 HttpResponseInfo response2
;
2661 std::string
expected_push_result("pushed");
2662 OrderedSocketData
data(reads
, arraysize(reads
),
2663 writes
, arraysize(writes
));
2664 RunServerPushTest(&data
,
2667 expected_push_result
);
2669 // Verify the SYN_REPLY.
2670 EXPECT_TRUE(response
.headers
.get() != NULL
);
2671 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2673 // Verify the pushed stream.
2674 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2675 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2678 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2679 scoped_ptr
<SpdyFrame
> stream1_syn(
2680 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2681 MockWrite writes
[] = { CreateMockWrite(*stream1_syn
, 1), };
2683 scoped_ptr
<SpdyFrame
>
2684 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2685 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2686 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2687 const char kPushedData
[] = "pushed";
2688 scoped_ptr
<SpdyFrame
> stream2_body(
2689 spdy_util_
.ConstructSpdyBodyFrame(
2690 2, kPushedData
, strlen(kPushedData
), true));
2691 scoped_ptr
<SpdyFrame
>
2692 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2693 MockRead reads
[] = {
2694 CreateMockRead(*stream1_reply
, 2),
2695 CreateMockRead(*stream2_syn
, 3),
2696 CreateMockRead(*stream2_body
, 4),
2697 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2698 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2701 HttpResponseInfo response
;
2702 HttpResponseInfo response2
;
2703 std::string
expected_push_result("pushed");
2704 OrderedSocketData
data(reads
, arraysize(reads
),
2705 writes
, arraysize(writes
));
2706 RunServerPushTest(&data
,
2709 expected_push_result
);
2711 // Verify the SYN_REPLY.
2712 EXPECT_TRUE(response
.headers
.get() != NULL
);
2713 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2715 // Verify the pushed stream.
2716 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2717 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2720 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2721 scoped_ptr
<SpdyFrame
> stream1_syn(
2722 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2723 scoped_ptr
<SpdyFrame
> stream1_body(
2724 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2725 MockWrite writes
[] = {
2726 CreateMockWrite(*stream1_syn
, 1),
2729 scoped_ptr
<SpdyFrame
>
2730 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2731 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2732 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2733 scoped_ptr
<SpdyFrame
> stream2_rst(
2734 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2735 MockRead reads
[] = {
2736 CreateMockRead(*stream1_reply
, 2),
2737 CreateMockRead(*stream2_syn
, 3),
2738 CreateMockRead(*stream2_rst
, 4),
2739 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2740 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2743 OrderedSocketData
data(reads
, arraysize(reads
),
2744 writes
, arraysize(writes
));
2745 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2746 BoundNetLog(), GetParam(), NULL
);
2748 helper
.RunPreTestSetup();
2749 helper
.AddData(&data
);
2751 HttpNetworkTransaction
* trans
= helper
.trans();
2753 // Start the transaction with basic parameters.
2754 TestCompletionCallback callback
;
2755 int rv
= trans
->Start(
2756 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2757 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2758 rv
= callback
.WaitForResult();
2761 // Verify that we consumed all test data.
2762 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2763 << data
.read_count()
2765 << data
.read_index();
2766 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2767 << data
.write_count()
2769 << data
.write_index();
2771 // Verify the SYN_REPLY.
2772 HttpResponseInfo response
= *trans
->GetResponseInfo();
2773 EXPECT_TRUE(response
.headers
.get() != NULL
);
2774 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2777 // Verify that we don't leak streams and that we properly send a reset
2778 // if the server pushes the same stream twice.
2779 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2780 scoped_ptr
<SpdyFrame
> stream1_syn(
2781 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2782 scoped_ptr
<SpdyFrame
> stream1_body(
2783 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2784 scoped_ptr
<SpdyFrame
> stream3_rst(
2785 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR
));
2786 MockWrite writes
[] = {
2787 CreateMockWrite(*stream1_syn
, 1),
2788 CreateMockWrite(*stream3_rst
, 5),
2791 scoped_ptr
<SpdyFrame
>
2792 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2793 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2794 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2795 const char kPushedData
[] = "pushed";
2796 scoped_ptr
<SpdyFrame
> stream2_body(
2797 spdy_util_
.ConstructSpdyBodyFrame(
2798 2, kPushedData
, strlen(kPushedData
), true));
2799 scoped_ptr
<SpdyFrame
> stream3_syn(spdy_util_
.ConstructSpdyPush(
2800 NULL
, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2801 MockRead reads
[] = {
2802 CreateMockRead(*stream1_reply
, 2),
2803 CreateMockRead(*stream2_syn
, 3),
2804 CreateMockRead(*stream3_syn
, 4),
2805 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
2806 CreateMockRead(*stream2_body
, 7),
2807 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
2810 HttpResponseInfo response
;
2811 HttpResponseInfo response2
;
2812 std::string
expected_push_result("pushed");
2813 OrderedSocketData
data(reads
, arraysize(reads
),
2814 writes
, arraysize(writes
));
2815 RunServerPushTest(&data
,
2818 expected_push_result
);
2820 // Verify the SYN_REPLY.
2821 EXPECT_TRUE(response
.headers
.get() != NULL
);
2822 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2824 // Verify the pushed stream.
2825 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2826 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2829 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2830 scoped_ptr
<SpdyFrame
> stream1_syn(
2831 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2832 scoped_ptr
<SpdyFrame
> stream1_body(
2833 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2834 MockWrite writes
[] = {
2835 CreateMockWrite(*stream1_syn
, 1),
2838 scoped_ptr
<SpdyFrame
>
2839 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2840 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2841 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2842 static const char kPushedData
[] = "pushed my darling hello my baby";
2843 scoped_ptr
<SpdyFrame
> stream2_body_base(
2844 spdy_util_
.ConstructSpdyBodyFrame(
2845 2, kPushedData
, strlen(kPushedData
), true));
2846 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2847 scoped_ptr
<SpdyFrame
> stream2_body1(
2848 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2849 scoped_ptr
<SpdyFrame
> stream2_body2(
2850 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2851 scoped_ptr
<SpdyFrame
> stream2_body3(
2852 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2853 kChunkSize
, false));
2854 scoped_ptr
<SpdyFrame
> stream2_body4(
2855 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2856 stream2_body_base
->size() - 3 * kChunkSize
, false));
2857 MockRead reads
[] = {
2858 CreateMockRead(*stream1_reply
, 2),
2859 CreateMockRead(*stream2_syn
, 3),
2860 CreateMockRead(*stream2_body1
, 4),
2861 CreateMockRead(*stream2_body2
, 5),
2862 CreateMockRead(*stream2_body3
, 6),
2863 CreateMockRead(*stream2_body4
, 7),
2864 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
2865 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
2868 HttpResponseInfo response
;
2869 HttpResponseInfo response2
;
2870 std::string
expected_push_result("pushed my darling hello my baby");
2871 OrderedSocketData
data(reads
, arraysize(reads
),
2872 writes
, arraysize(writes
));
2873 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2875 // Verify the SYN_REPLY.
2876 EXPECT_TRUE(response
.headers
.get() != NULL
);
2877 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2879 // Verify the pushed stream.
2880 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2881 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2884 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2885 scoped_ptr
<SpdyFrame
> stream1_syn(
2886 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2887 scoped_ptr
<SpdyFrame
> stream1_body(
2888 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2889 MockWrite writes
[] = {
2890 CreateMockWrite(*stream1_syn
, 1),
2893 scoped_ptr
<SpdyFrame
>
2894 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2895 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2896 NULL
, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
2897 static const char kPushedData
[] = "pushed my darling hello my baby";
2898 scoped_ptr
<SpdyFrame
> stream2_body_base(
2899 spdy_util_
.ConstructSpdyBodyFrame(
2900 2, kPushedData
, strlen(kPushedData
), true));
2901 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2902 scoped_ptr
<SpdyFrame
> stream2_body1(
2903 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2904 scoped_ptr
<SpdyFrame
> stream2_body2(
2905 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2906 scoped_ptr
<SpdyFrame
> stream2_body3(
2907 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2908 kChunkSize
, false));
2909 scoped_ptr
<SpdyFrame
> stream2_body4(
2910 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2911 stream2_body_base
->size() - 3 * kChunkSize
, false));
2912 MockRead reads
[] = {
2913 CreateMockRead(*stream1_reply
, 2),
2914 CreateMockRead(*stream2_syn
, 3),
2915 CreateMockRead(*stream2_body1
, 4),
2916 CreateMockRead(*stream2_body2
, 5),
2917 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2918 CreateMockRead(*stream2_body3
, 7),
2919 CreateMockRead(*stream2_body4
, 8),
2920 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
2921 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
2924 HttpResponseInfo response
;
2925 HttpResponseInfo response2
;
2926 OrderedSocketData
data(reads
, arraysize(reads
),
2927 writes
, arraysize(writes
));
2928 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2930 // Verify the SYN_REPLY.
2931 EXPECT_TRUE(response
.headers
.get() != NULL
);
2932 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2934 // Verify the pushed stream.
2935 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2936 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2939 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
2940 if (spdy_util_
.spdy_version() == SPDY4
) {
2941 // PUSH_PROMISE with stream id 0 is connection-level error.
2942 // TODO(baranovich): Test session going away.
2946 scoped_ptr
<SpdyFrame
> stream1_syn(
2947 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2948 scoped_ptr
<SpdyFrame
> stream1_body(
2949 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2950 scoped_ptr
<SpdyFrame
> stream2_rst(
2951 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
2952 MockWrite writes
[] = {
2953 CreateMockWrite(*stream1_syn
, 1),
2954 CreateMockWrite(*stream2_rst
, 4),
2957 scoped_ptr
<SpdyFrame
>
2958 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2959 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
2960 NULL
, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
2961 MockRead reads
[] = {
2962 CreateMockRead(*stream1_reply
, 2),
2963 CreateMockRead(*stream2_syn
, 3),
2964 CreateMockRead(*stream1_body
, 4),
2965 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
2968 OrderedSocketData
data(reads
, arraysize(reads
),
2969 writes
, arraysize(writes
));
2970 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2971 BoundNetLog(), GetParam(), NULL
);
2973 helper
.RunPreTestSetup();
2974 helper
.AddData(&data
);
2976 HttpNetworkTransaction
* trans
= helper
.trans();
2978 // Start the transaction with basic parameters.
2979 TestCompletionCallback callback
;
2980 int rv
= trans
->Start(
2981 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2982 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2983 rv
= callback
.WaitForResult();
2986 // Verify that we consumed all test data.
2987 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2988 << data
.read_count()
2990 << data
.read_index();
2991 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2992 << data
.write_count()
2994 << data
.write_index();
2996 // Verify the SYN_REPLY.
2997 HttpResponseInfo response
= *trans
->GetResponseInfo();
2998 EXPECT_TRUE(response
.headers
.get() != NULL
);
2999 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3002 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3003 scoped_ptr
<SpdyFrame
> stream1_syn(
3004 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3005 scoped_ptr
<SpdyFrame
> stream1_body(
3006 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3007 scoped_ptr
<SpdyFrame
> stream2_rst(
3008 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM
));
3009 MockWrite writes
[] = {
3010 CreateMockWrite(*stream1_syn
, 1),
3011 CreateMockWrite(*stream2_rst
, 4),
3014 scoped_ptr
<SpdyFrame
>
3015 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3016 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructSpdyPush(
3017 NULL
, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
3018 MockRead reads
[] = {
3019 CreateMockRead(*stream1_reply
, 2),
3020 CreateMockRead(*stream2_syn
, 3),
3021 CreateMockRead(*stream1_body
, 4),
3022 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3025 OrderedSocketData
data(reads
, arraysize(reads
),
3026 writes
, arraysize(writes
));
3027 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3028 BoundNetLog(), GetParam(), NULL
);
3030 helper
.RunPreTestSetup();
3031 helper
.AddData(&data
);
3033 HttpNetworkTransaction
* trans
= helper
.trans();
3035 // Start the transaction with basic parameters.
3036 TestCompletionCallback callback
;
3037 int rv
= trans
->Start(
3038 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3039 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3040 rv
= callback
.WaitForResult();
3043 // Verify that we consumed all test data.
3044 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3045 << data
.read_count()
3047 << data
.read_index();
3048 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3049 << data
.write_count()
3051 << data
.write_index();
3053 // Verify the SYN_REPLY.
3054 HttpResponseInfo response
= *trans
->GetResponseInfo();
3055 EXPECT_TRUE(response
.headers
.get() != NULL
);
3056 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3059 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3060 scoped_ptr
<SpdyFrame
> stream1_syn(
3061 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3062 scoped_ptr
<SpdyFrame
> stream1_body(
3063 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3064 scoped_ptr
<SpdyFrame
> stream2_rst(
3065 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
3066 MockWrite writes
[] = {
3067 CreateMockWrite(*stream1_syn
, 1),
3068 CreateMockWrite(*stream2_rst
, 4),
3071 scoped_ptr
<SpdyFrame
>
3072 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3073 scoped_ptr
<SpdyHeaderBlock
> incomplete_headers(new SpdyHeaderBlock());
3074 (*incomplete_headers
)["hello"] = "bye";
3075 (*incomplete_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
3076 (*incomplete_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
3077 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructInitialSpdyPushFrame(
3078 incomplete_headers
.Pass(), 2, 1));
3079 MockRead reads
[] = {
3080 CreateMockRead(*stream1_reply
, 2),
3081 CreateMockRead(*stream2_syn
, 3),
3082 CreateMockRead(*stream1_body
, 4),
3083 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3086 OrderedSocketData
data(reads
, arraysize(reads
),
3087 writes
, arraysize(writes
));
3088 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3089 BoundNetLog(), GetParam(), NULL
);
3091 helper
.RunPreTestSetup();
3092 helper
.AddData(&data
);
3094 HttpNetworkTransaction
* trans
= helper
.trans();
3096 // Start the transaction with basic parameters.
3097 TestCompletionCallback callback
;
3098 int rv
= trans
->Start(
3099 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3100 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3101 rv
= callback
.WaitForResult();
3103 // Verify that we consumed all test data.
3104 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3105 << data
.read_count()
3107 << data
.read_index();
3108 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3109 << data
.write_count()
3111 << data
.write_index();
3113 // Verify the SYN_REPLY.
3114 HttpResponseInfo response
= *trans
->GetResponseInfo();
3115 EXPECT_TRUE(response
.headers
.get() != NULL
);
3116 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3119 // Verify that various SynReply headers parse correctly through the
3121 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3122 struct SynReplyHeadersTests
{
3124 const char* extra_headers
[5];
3125 SpdyHeaderBlock expected_headers
;
3127 // This uses a multi-valued cookie header.
3130 "cookie", "val2", // will get appended separated by NULL
3134 // This is the minimalist set of headers.
3138 // Headers with a comma separated list.
3140 { "cookie", "val1,val2",
3146 test_cases
[0].expected_headers
["cookie"] = "val1";
3147 test_cases
[0].expected_headers
["cookie"] += '\0';
3148 test_cases
[0].expected_headers
["cookie"] += "val2";
3149 test_cases
[0].expected_headers
["hello"] = "bye";
3150 test_cases
[0].expected_headers
["status"] = "200";
3152 test_cases
[1].expected_headers
["hello"] = "bye";
3153 test_cases
[1].expected_headers
["status"] = "200";
3155 test_cases
[2].expected_headers
["cookie"] = "val1,val2";
3156 test_cases
[2].expected_headers
["hello"] = "bye";
3157 test_cases
[2].expected_headers
["status"] = "200";
3159 if (spdy_util_
.spdy_version() < SPDY4
) {
3160 // SPDY4/HTTP2 eliminates use of the :version header.
3161 test_cases
[0].expected_headers
["version"] = "HTTP/1.1";
3162 test_cases
[1].expected_headers
["version"] = "HTTP/1.1";
3163 test_cases
[2].expected_headers
["version"] = "HTTP/1.1";
3166 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3167 scoped_ptr
<SpdyFrame
> req(
3168 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3169 MockWrite writes
[] = { CreateMockWrite(*req
) };
3171 scoped_ptr
<SpdyFrame
> resp(
3172 spdy_util_
.ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3173 test_cases
[i
].num_headers
,
3175 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3176 MockRead reads
[] = {
3177 CreateMockRead(*resp
),
3178 CreateMockRead(*body
),
3179 MockRead(ASYNC
, 0, 0) // EOF
3182 DelayedSocketData
data(1, reads
, arraysize(reads
),
3183 writes
, arraysize(writes
));
3184 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3185 BoundNetLog(), GetParam(), NULL
);
3186 helper
.RunToCompletion(&data
);
3187 TransactionHelperResult out
= helper
.output();
3189 EXPECT_EQ(OK
, out
.rv
);
3190 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3191 EXPECT_EQ("hello!", out
.response_data
);
3193 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3194 EXPECT_TRUE(headers
.get() != NULL
);
3196 std::string name
, value
;
3197 SpdyHeaderBlock header_block
;
3198 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3199 if (header_block
[name
].empty()) {
3200 header_block
[name
] = value
;
3202 header_block
[name
] += '\0';
3203 header_block
[name
] += value
;
3206 EXPECT_EQ(test_cases
[i
].expected_headers
, header_block
);
3210 // Verify that various SynReply headers parse vary fields correctly
3211 // through the HTTP layer, and the response matches the request.
3212 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3213 // Modify the following data to change/add test cases:
3214 struct SynReplyTests
{
3217 const char* extra_headers
[2][16];
3219 // Test the case of a multi-valued cookie. When the value is delimited
3220 // with NUL characters, it needs to be unfolded into multiple headers.
3224 { { "cookie", "val1,val2",
3228 spdy_util_
.GetStatusKey(), "200",
3229 spdy_util_
.GetPathKey(), "/index.php",
3230 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3234 }, { // Multiple vary fields.
3237 { { "friend", "barney",
3238 "enemy", "snaggletooth",
3243 spdy_util_
.GetStatusKey(), "200",
3244 spdy_util_
.GetPathKey(), "/index.php",
3245 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3249 }, { // Test a '*' vary field.
3252 { { "cookie", "val1,val2",
3256 spdy_util_
.GetStatusKey(), "200",
3257 spdy_util_
.GetPathKey(), "/index.php",
3258 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3262 }, { // Multiple comma-separated vary fields.
3265 { { "friend", "barney",
3266 "enemy", "snaggletooth",
3269 { "vary", "friend,enemy",
3270 spdy_util_
.GetStatusKey(), "200",
3271 spdy_util_
.GetPathKey(), "/index.php",
3272 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3279 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3280 // Construct the request.
3281 scoped_ptr
<SpdyFrame
> frame_req(
3282 spdy_util_
.ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3283 test_cases
[i
].num_headers
[0],
3284 false, 1, LOWEST
, true));
3286 MockWrite writes
[] = {
3287 CreateMockWrite(*frame_req
),
3290 // Construct the reply.
3291 SpdyHeaderBlock reply_headers
;
3292 AppendToHeaderBlock(test_cases
[i
].extra_headers
[1],
3293 test_cases
[i
].num_headers
[1],
3295 scoped_ptr
<SpdyFrame
> frame_reply(
3296 spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3298 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3299 MockRead reads
[] = {
3300 CreateMockRead(*frame_reply
),
3301 CreateMockRead(*body
),
3302 MockRead(ASYNC
, 0, 0) // EOF
3305 // Attach the headers to the request.
3306 int header_count
= test_cases
[i
].num_headers
[0];
3308 HttpRequestInfo request
= CreateGetRequest();
3309 for (int ct
= 0; ct
< header_count
; ct
++) {
3310 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3311 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3312 request
.extra_headers
.SetHeader(header_key
, header_value
);
3315 DelayedSocketData
data(1, reads
, arraysize(reads
),
3316 writes
, arraysize(writes
));
3317 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
3318 BoundNetLog(), GetParam(), NULL
);
3319 helper
.RunToCompletion(&data
);
3320 TransactionHelperResult out
= helper
.output();
3322 EXPECT_EQ(OK
, out
.rv
) << i
;
3323 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3324 EXPECT_EQ("hello!", out
.response_data
) << i
;
3326 // Test the response information.
3327 EXPECT_TRUE(out
.response_info
.response_time
>
3328 out
.response_info
.request_time
) << i
;
3329 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3330 out
.response_info
.request_time
;
3331 base::TimeDelta min_expected_delay
;
3332 min_expected_delay
.FromMilliseconds(10);
3333 EXPECT_GT(test_delay
.InMillisecondsF(),
3334 min_expected_delay
.InMillisecondsF()) << i
;
3335 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3336 test_cases
[i
].vary_matches
) << i
;
3338 // Check the headers.
3339 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3340 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3342 std::string name
, value
, lines
;
3343 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3346 lines
.append(value
);
3350 // Construct the expected header reply string.
3351 std::string expected_reply
=
3352 spdy_util_
.ConstructSpdyReplyString(reply_headers
);
3353 EXPECT_EQ(expected_reply
, lines
) << i
;
3357 // Verify that we don't crash on invalid SynReply responses.
3358 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3359 struct InvalidSynReplyTests
{
3361 const char* headers
[10];
3363 // SYN_REPLY missing status header
3367 spdy_util_
.GetPathKey(), "/index.php",
3368 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3372 // SYN_REPLY missing version header
3375 spdy_util_
.GetPathKey(), "/index.php",
3379 // SYN_REPLY with no headers
3383 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3384 scoped_ptr
<SpdyFrame
> req(
3385 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3386 scoped_ptr
<SpdyFrame
> rst(
3387 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3388 MockWrite writes
[] = {
3389 CreateMockWrite(*req
),
3390 CreateMockWrite(*rst
),
3393 // Construct the reply.
3394 SpdyHeaderBlock reply_headers
;
3395 AppendToHeaderBlock(
3396 test_cases
[i
].headers
, test_cases
[i
].num_headers
, &reply_headers
);
3397 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3398 MockRead reads
[] = {
3399 CreateMockRead(*resp
),
3400 MockRead(ASYNC
, 0, 0) // EOF
3403 DelayedSocketData
data(1, reads
, arraysize(reads
),
3404 writes
, arraysize(writes
));
3405 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3406 BoundNetLog(), GetParam(), NULL
);
3407 helper
.RunToCompletion(&data
);
3408 TransactionHelperResult out
= helper
.output();
3409 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3413 // Verify that we don't crash on some corrupt frames.
3414 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3415 // connection error. I'd like to backport this behavior to SPDY3 as well.
3416 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3417 if (spdy_util_
.spdy_version() >= SPDY4
) {
3420 // This is the length field that's too short.
3421 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3422 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3423 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3425 (spdy_util_
.spdy_version() < SPDY4
) ?
3426 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize() :
3427 syn_reply_wrong_length
->size();
3428 size_t wrong_size
= right_size
- 4;
3429 test::SetFrameLength(syn_reply_wrong_length
.get(),
3431 spdy_util_
.spdy_version());
3433 struct SynReplyTests
{
3434 const SpdyFrame
* syn_reply
;
3436 { syn_reply_wrong_length
.get(), },
3439 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3440 scoped_ptr
<SpdyFrame
> req(
3441 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3442 scoped_ptr
<SpdyFrame
> rst(
3443 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3444 MockWrite writes
[] = {
3445 CreateMockWrite(*req
),
3446 CreateMockWrite(*rst
),
3449 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3450 MockRead reads
[] = {
3451 MockRead(ASYNC
, test_cases
[i
].syn_reply
->data(), wrong_size
),
3452 CreateMockRead(*body
),
3453 MockRead(ASYNC
, 0, 0) // EOF
3456 DelayedSocketData
data(1, reads
, arraysize(reads
),
3457 writes
, arraysize(writes
));
3458 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3459 BoundNetLog(), GetParam(), NULL
);
3460 helper
.RunToCompletion(&data
);
3461 TransactionHelperResult out
= helper
.output();
3462 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3466 // SPDY4 treats a header decompression failure as a connection-level error.
3467 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionErrorSpdy4
) {
3468 if (spdy_util_
.spdy_version() < SPDY4
) {
3471 // This is the length field that's too short.
3472 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3473 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3474 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3476 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize();
3477 size_t wrong_size
= right_size
- 4;
3478 test::SetFrameLength(syn_reply_wrong_length
.get(),
3480 spdy_util_
.spdy_version());
3482 scoped_ptr
<SpdyFrame
> req(
3483 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3484 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3485 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3486 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3488 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3489 MockRead reads
[] = {
3490 MockRead(ASYNC
, syn_reply_wrong_length
->data(),
3491 syn_reply_wrong_length
->size() - 4),
3494 DelayedSocketData
data(1, reads
, arraysize(reads
),
3495 writes
, arraysize(writes
));
3496 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3497 BoundNetLog(), GetParam(), NULL
);
3498 helper
.RunToCompletion(&data
);
3499 TransactionHelperResult out
= helper
.output();
3500 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3503 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnDecompressionFailure
) {
3504 if (GetParam().protocol
< kProtoSPDY4MinimumVersion
) {
3505 // Decompression failures are a stream error in SPDY3 and above.
3508 scoped_ptr
<SpdyFrame
> req(
3509 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3510 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3511 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3512 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3514 // Read HEADERS with corrupted payload.
3515 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3516 memset(resp
->data() + 12, 0xff, resp
->size() - 12);
3517 MockRead reads
[] = {CreateMockRead(*resp
)};
3519 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3520 NormalSpdyTransactionHelper
helper(
3521 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3522 helper
.RunToCompletion(&data
);
3523 TransactionHelperResult out
= helper
.output();
3524 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3527 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnFrameSizeError
) {
3528 scoped_ptr
<SpdyFrame
> req(
3529 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3530 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3531 0, GOAWAY_PROTOCOL_ERROR
, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3532 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3534 // Read WINDOW_UPDATE with incorrectly-sized payload.
3535 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3536 // which is mapped to a protocol error, and not a frame size error.
3537 scoped_ptr
<SpdyFrame
> bad_window_update(
3538 spdy_util_
.ConstructSpdyWindowUpdate(1, 1));
3539 test::SetFrameLength(bad_window_update
.get(),
3540 bad_window_update
->size() - 1,
3541 spdy_util_
.spdy_version());
3542 MockRead reads
[] = {CreateMockRead(*bad_window_update
)};
3544 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3545 NormalSpdyTransactionHelper
helper(
3546 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3547 helper
.RunToCompletion(&data
);
3548 TransactionHelperResult out
= helper
.output();
3549 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3552 // Test that we shutdown correctly on write errors.
3553 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3554 scoped_ptr
<SpdyFrame
> req(
3555 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3556 MockWrite writes
[] = {
3557 // We'll write 10 bytes successfully
3558 MockWrite(ASYNC
, req
->data(), 10, 0),
3559 // Followed by ERROR!
3560 MockWrite(ASYNC
, ERR_FAILED
, 1),
3561 // Session drains and attempts to write a GOAWAY: Another ERROR!
3562 MockWrite(ASYNC
, ERR_FAILED
, 2),
3565 MockRead reads
[] = {
3566 MockRead(ASYNC
, 0, 3) // EOF
3569 DeterministicSocketData
data(reads
, arraysize(reads
),
3570 writes
, arraysize(writes
));
3572 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3573 BoundNetLog(), GetParam(), NULL
);
3574 helper
.SetDeterministic();
3575 helper
.RunPreTestSetup();
3576 helper
.AddDeterministicData(&data
);
3577 EXPECT_TRUE(helper
.StartDefaultTest());
3579 helper
.FinishDefaultTest();
3580 EXPECT_TRUE(data
.at_write_eof());
3581 EXPECT_TRUE(!data
.at_read_eof());
3582 TransactionHelperResult out
= helper
.output();
3583 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3586 // Test that partial writes work.
3587 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3588 // Chop the SYN_STREAM frame into 5 chunks.
3589 scoped_ptr
<SpdyFrame
> req(
3590 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3591 const int kChunks
= 5;
3592 scoped_ptr
<MockWrite
[]> writes(ChopWriteFrame(*req
.get(), kChunks
));
3594 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3595 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3596 MockRead reads
[] = {
3597 CreateMockRead(*resp
),
3598 CreateMockRead(*body
),
3599 MockRead(ASYNC
, 0, 0) // EOF
3602 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
3603 writes
.get(), kChunks
);
3604 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3605 BoundNetLog(), GetParam(), NULL
);
3606 helper
.RunToCompletion(&data
);
3607 TransactionHelperResult out
= helper
.output();
3608 EXPECT_EQ(OK
, out
.rv
);
3609 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3610 EXPECT_EQ("hello!", out
.response_data
);
3613 // In this test, we enable compression, but get a uncompressed SynReply from
3614 // the server. Verify that teardown is all clean.
3615 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3616 if (spdy_util_
.spdy_version() >= SPDY4
) {
3617 // HPACK doesn't use deflate compression.
3620 scoped_ptr
<SpdyFrame
> compressed(
3621 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
, true));
3622 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3623 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3624 MockWrite writes
[] = {CreateMockWrite(*compressed
), CreateMockWrite(*goaway
)};
3626 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3627 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3628 MockRead reads
[] = {
3629 CreateMockRead(*resp
),
3632 DelayedSocketData
data(1, reads
, arraysize(reads
),
3633 writes
, arraysize(writes
));
3634 SpdySessionDependencies
* session_deps
=
3635 CreateSpdySessionDependencies(GetParam());
3636 session_deps
->enable_compression
= true;
3637 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3638 BoundNetLog(), GetParam(), session_deps
);
3639 helper
.RunToCompletion(&data
);
3640 TransactionHelperResult out
= helper
.output();
3641 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3645 // Test that the NetLog contains good data for a simple GET request.
3646 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3647 static const char* const kExtraHeaders
[] = {
3648 "user-agent", "Chrome",
3650 scoped_ptr
<SpdyFrame
> req(
3651 spdy_util_
.ConstructSpdyGet(kExtraHeaders
, 1, false, 1, LOWEST
, true));
3652 MockWrite writes
[] = { CreateMockWrite(*req
) };
3654 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3655 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3656 MockRead reads
[] = {
3657 CreateMockRead(*resp
),
3658 CreateMockRead(*body
),
3659 MockRead(ASYNC
, 0, 0) // EOF
3662 BoundTestNetLog log
;
3664 DelayedSocketData
data(1, reads
, arraysize(reads
),
3665 writes
, arraysize(writes
));
3666 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3668 log
.bound(), GetParam(), NULL
);
3669 helper
.RunToCompletion(&data
);
3670 TransactionHelperResult out
= helper
.output();
3671 EXPECT_EQ(OK
, out
.rv
);
3672 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3673 EXPECT_EQ("hello!", out
.response_data
);
3675 // Check that the NetLog was filled reasonably.
3676 // This test is intentionally non-specific about the exact ordering of the
3677 // log; instead we just check to make sure that certain events exist, and that
3678 // they are in the right order.
3679 TestNetLog::CapturedEntryList entries
;
3680 log
.GetEntries(&entries
);
3682 EXPECT_LT(0u, entries
.size());
3684 pos
= ExpectLogContainsSomewhere(entries
, 0,
3685 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3686 NetLog::PHASE_BEGIN
);
3687 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3688 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3690 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3691 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3692 NetLog::PHASE_BEGIN
);
3693 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3694 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3696 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3697 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3698 NetLog::PHASE_BEGIN
);
3699 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3700 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3703 // Check that we logged all the headers correctly
3704 const NetLog::EventType type
= (GetParam().protocol
<= kProtoSPDY31
)
3705 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3706 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS
;
3707 pos
= ExpectLogContainsSomewhere(entries
, 0, type
, NetLog::PHASE_NONE
);
3709 base::ListValue
* header_list
;
3710 ASSERT_TRUE(entries
[pos
].params
.get());
3711 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3713 std::vector
<std::string
> expected
;
3714 expected
.push_back(std::string(spdy_util_
.GetHostKey()) +
3715 ": www.example.org");
3716 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3717 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": " +
3718 spdy_util_
.default_url().scheme());
3719 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3720 expected
.push_back("user-agent: Chrome");
3721 if (spdy_util_
.spdy_version() < SPDY4
) {
3722 // SPDY4/HTTP2 eliminates use of the :version header.
3723 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3725 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3726 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3727 it
!= expected
.end();
3729 base::StringValue
header(*it
);
3730 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3731 "Header not found: " << *it
;
3735 // Since we buffer the IO from the stream to the renderer, this test verifies
3736 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3737 // on the network, but issued a Read for only 5 of those bytes) that the data
3738 // flow still works correctly.
3739 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3740 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3742 scoped_ptr
<SpdyFrame
> req(
3743 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3744 MockWrite writes
[] = { CreateMockWrite(*req
) };
3746 // 2 data frames in a single read.
3747 scoped_ptr
<SpdyFrame
> data_frame_1(
3748 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3749 scoped_ptr
<SpdyFrame
> data_frame_2(
3750 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3751 const SpdyFrame
* data_frames
[2] = {
3755 char combined_data_frames
[100];
3756 int combined_data_frames_len
=
3757 CombineFrames(data_frames
, arraysize(data_frames
),
3758 combined_data_frames
, arraysize(combined_data_frames
));
3759 scoped_ptr
<SpdyFrame
> last_frame(
3760 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3762 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3763 MockRead reads
[] = {
3764 CreateMockRead(*resp
),
3765 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3766 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3767 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3768 CreateMockRead(*last_frame
),
3769 MockRead(ASYNC
, 0, 0) // EOF
3772 DelayedSocketData
data(1, reads
, arraysize(reads
),
3773 writes
, arraysize(writes
));
3775 TestCompletionCallback callback
;
3777 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3778 BoundNetLog(), GetParam(), NULL
);
3779 helper
.RunPreTestSetup();
3780 helper
.AddData(&data
);
3781 HttpNetworkTransaction
* trans
= helper
.trans();
3782 int rv
= trans
->Start(
3783 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3784 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3786 TransactionHelperResult out
= helper
.output();
3787 out
.rv
= callback
.WaitForResult();
3788 EXPECT_EQ(out
.rv
, OK
);
3790 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3791 EXPECT_TRUE(response
->headers
.get() != NULL
);
3792 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3793 out
.status_line
= response
->headers
->GetStatusLine();
3794 out
.response_info
= *response
; // Make a copy so we can verify.
3797 TestCompletionCallback read_callback
;
3799 std::string content
;
3801 // Read small chunks at a time.
3802 const int kSmallReadSize
= 3;
3803 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
3804 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3805 if (rv
== ERR_IO_PENDING
) {
3806 data
.CompleteRead();
3807 rv
= read_callback
.WaitForResult();
3810 content
.append(buf
->data(), rv
);
3811 } else if (rv
< 0) {
3816 out
.response_data
.swap(content
);
3818 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3819 // MockClientSocketFactory) are still alive.
3820 base::RunLoop().RunUntilIdle();
3822 // Verify that we consumed all test data.
3823 helper
.VerifyDataConsumed();
3825 EXPECT_EQ(OK
, out
.rv
);
3826 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3827 EXPECT_EQ("goodbye world", out
.response_data
);
3830 // Verify that basic buffering works; when multiple data frames arrive
3831 // at the same time, ensure that we don't notify a read completion for
3832 // each data frame individually.
3833 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3834 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3836 scoped_ptr
<SpdyFrame
> req(
3837 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3838 MockWrite writes
[] = { CreateMockWrite(*req
) };
3840 // 4 data frames in a single read.
3841 scoped_ptr
<SpdyFrame
> data_frame(
3842 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3843 scoped_ptr
<SpdyFrame
> data_frame_fin(
3844 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3845 const SpdyFrame
* data_frames
[4] = {
3849 data_frame_fin
.get()
3851 char combined_data_frames
[100];
3852 int combined_data_frames_len
=
3853 CombineFrames(data_frames
, arraysize(data_frames
),
3854 combined_data_frames
, arraysize(combined_data_frames
));
3856 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3857 MockRead reads
[] = {
3858 CreateMockRead(*resp
),
3859 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3860 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3861 MockRead(ASYNC
, 0, 0) // EOF
3864 DelayedSocketData
data(1, reads
, arraysize(reads
),
3865 writes
, arraysize(writes
));
3867 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3868 BoundNetLog(), GetParam(), NULL
);
3869 helper
.RunPreTestSetup();
3870 helper
.AddData(&data
);
3871 HttpNetworkTransaction
* trans
= helper
.trans();
3873 TestCompletionCallback callback
;
3874 int rv
= trans
->Start(
3875 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3878 TransactionHelperResult out
= helper
.output();
3879 out
.rv
= callback
.WaitForResult();
3880 EXPECT_EQ(out
.rv
, OK
);
3882 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3883 EXPECT_TRUE(response
->headers
.get() != NULL
);
3884 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3885 out
.status_line
= response
->headers
->GetStatusLine();
3886 out
.response_info
= *response
; // Make a copy so we can verify.
3889 TestCompletionCallback read_callback
;
3891 std::string content
;
3892 int reads_completed
= 0;
3894 // Read small chunks at a time.
3895 const int kSmallReadSize
= 14;
3896 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
3897 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3898 if (rv
== ERR_IO_PENDING
) {
3899 data
.CompleteRead();
3900 rv
= read_callback
.WaitForResult();
3903 EXPECT_EQ(kSmallReadSize
, rv
);
3904 content
.append(buf
->data(), rv
);
3905 } else if (rv
< 0) {
3906 FAIL() << "Unexpected read error: " << rv
;
3911 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3913 out
.response_data
.swap(content
);
3915 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3916 // MockClientSocketFactory) are still alive.
3917 base::RunLoop().RunUntilIdle();
3919 // Verify that we consumed all test data.
3920 helper
.VerifyDataConsumed();
3922 EXPECT_EQ(OK
, out
.rv
);
3923 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3924 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
3927 // Verify the case where we buffer data but read it after it has been buffered.
3928 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
3929 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3931 scoped_ptr
<SpdyFrame
> req(
3932 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3933 MockWrite writes
[] = { CreateMockWrite(*req
) };
3935 // 5 data frames in a single read.
3936 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3937 scoped_ptr
<SpdyFrame
> data_frame(
3938 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3939 scoped_ptr
<SpdyFrame
> data_frame_fin(
3940 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3941 const SpdyFrame
* frames
[5] = {reply
.get(), data_frame
.get(), data_frame
.get(),
3942 data_frame
.get(), data_frame_fin
.get()};
3943 char combined_frames
[200];
3944 int combined_frames_len
=
3945 CombineFrames(frames
, arraysize(frames
),
3946 combined_frames
, arraysize(combined_frames
));
3948 MockRead reads
[] = {
3949 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
3950 MockRead(ASYNC
, 0, 0) // EOF
3953 DelayedSocketData
data(1, reads
, arraysize(reads
),
3954 writes
, arraysize(writes
));
3956 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3957 BoundNetLog(), GetParam(), NULL
);
3958 helper
.RunPreTestSetup();
3959 helper
.AddData(&data
);
3960 HttpNetworkTransaction
* trans
= helper
.trans();
3962 TestCompletionCallback callback
;
3963 int rv
= trans
->Start(
3964 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3965 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3967 TransactionHelperResult out
= helper
.output();
3968 out
.rv
= callback
.WaitForResult();
3969 EXPECT_EQ(out
.rv
, OK
);
3971 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3972 EXPECT_TRUE(response
->headers
.get() != NULL
);
3973 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3974 out
.status_line
= response
->headers
->GetStatusLine();
3975 out
.response_info
= *response
; // Make a copy so we can verify.
3978 TestCompletionCallback read_callback
;
3980 std::string content
;
3981 int reads_completed
= 0;
3983 // Read small chunks at a time.
3984 const int kSmallReadSize
= 14;
3985 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
3986 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3988 EXPECT_EQ(kSmallReadSize
, rv
);
3989 content
.append(buf
->data(), rv
);
3990 } else if (rv
< 0) {
3991 FAIL() << "Unexpected read error: " << rv
;
3996 EXPECT_EQ(3, reads_completed
);
3998 out
.response_data
.swap(content
);
4000 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4001 // MockClientSocketFactory) are still alive.
4002 base::RunLoop().RunUntilIdle();
4004 // Verify that we consumed all test data.
4005 helper
.VerifyDataConsumed();
4007 EXPECT_EQ(OK
, out
.rv
);
4008 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4009 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4012 // Verify the case where we buffer data and close the connection.
4013 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4014 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4016 scoped_ptr
<SpdyFrame
> req(
4017 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4018 MockWrite writes
[] = { CreateMockWrite(*req
) };
4020 // All data frames in a single read.
4021 // NOTE: We don't FIN the stream.
4022 scoped_ptr
<SpdyFrame
> data_frame(
4023 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4024 const SpdyFrame
* data_frames
[4] = {
4030 char combined_data_frames
[100];
4031 int combined_data_frames_len
=
4032 CombineFrames(data_frames
, arraysize(data_frames
),
4033 combined_data_frames
, arraysize(combined_data_frames
));
4034 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4035 MockRead reads
[] = {
4036 CreateMockRead(*resp
),
4037 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4038 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4039 MockRead(ASYNC
, 0, 0) // EOF
4042 DelayedSocketData
data(1, reads
, arraysize(reads
),
4043 writes
, arraysize(writes
));
4045 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4046 BoundNetLog(), GetParam(), NULL
);
4047 helper
.RunPreTestSetup();
4048 helper
.AddData(&data
);
4049 HttpNetworkTransaction
* trans
= helper
.trans();
4051 TestCompletionCallback callback
;
4053 int rv
= trans
->Start(
4054 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4055 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4057 TransactionHelperResult out
= helper
.output();
4058 out
.rv
= callback
.WaitForResult();
4059 EXPECT_EQ(out
.rv
, OK
);
4061 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4062 EXPECT_TRUE(response
->headers
.get() != NULL
);
4063 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4064 out
.status_line
= response
->headers
->GetStatusLine();
4065 out
.response_info
= *response
; // Make a copy so we can verify.
4068 TestCompletionCallback read_callback
;
4070 std::string content
;
4071 int reads_completed
= 0;
4073 // Read small chunks at a time.
4074 const int kSmallReadSize
= 14;
4075 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
4076 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4077 if (rv
== ERR_IO_PENDING
) {
4078 data
.CompleteRead();
4079 rv
= read_callback
.WaitForResult();
4082 content
.append(buf
->data(), rv
);
4083 } else if (rv
< 0) {
4084 // This test intentionally closes the connection, and will get an error.
4085 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4091 EXPECT_EQ(0, reads_completed
);
4093 out
.response_data
.swap(content
);
4095 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4096 // MockClientSocketFactory) are still alive.
4097 base::RunLoop().RunUntilIdle();
4099 // Verify that we consumed all test data.
4100 helper
.VerifyDataConsumed();
4103 // Verify the case where we buffer data and cancel the transaction.
4104 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4105 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4107 scoped_ptr
<SpdyFrame
> req(
4108 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4109 scoped_ptr
<SpdyFrame
> rst(
4110 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
4111 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*rst
)};
4113 // NOTE: We don't FIN the stream.
4114 scoped_ptr
<SpdyFrame
> data_frame(
4115 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4117 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4118 MockRead reads
[] = {
4119 CreateMockRead(*resp
),
4120 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4121 CreateMockRead(*data_frame
),
4122 MockRead(ASYNC
, 0, 0) // EOF
4125 DelayedSocketData
data(1, reads
, arraysize(reads
),
4126 writes
, arraysize(writes
));
4128 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4129 BoundNetLog(), GetParam(), NULL
);
4130 helper
.RunPreTestSetup();
4131 helper
.AddData(&data
);
4132 HttpNetworkTransaction
* trans
= helper
.trans();
4133 TestCompletionCallback callback
;
4135 int rv
= trans
->Start(
4136 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4137 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4139 TransactionHelperResult out
= helper
.output();
4140 out
.rv
= callback
.WaitForResult();
4141 EXPECT_EQ(out
.rv
, OK
);
4143 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4144 EXPECT_TRUE(response
->headers
.get() != NULL
);
4145 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4146 out
.status_line
= response
->headers
->GetStatusLine();
4147 out
.response_info
= *response
; // Make a copy so we can verify.
4150 TestCompletionCallback read_callback
;
4152 const int kReadSize
= 256;
4153 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kReadSize
));
4154 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4155 ASSERT_EQ(ERR_IO_PENDING
, rv
) << "Unexpected read: " << rv
;
4157 // Complete the read now, which causes buffering to start.
4158 data
.CompleteRead();
4159 // Destroy the transaction, causing the stream to get cancelled
4160 // and orphaning the buffered IO task.
4161 helper
.ResetTrans();
4163 // Flush the MessageLoop; this will cause the buffered IO task
4164 // to run for the final time.
4165 base::RunLoop().RunUntilIdle();
4167 // Verify that we consumed all test data.
4168 helper
.VerifyDataConsumed();
4171 // Test that if the server requests persistence of settings, that we save
4172 // the settings in the HttpServerProperties.
4173 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4174 if (spdy_util_
.spdy_version() >= SPDY4
) {
4175 // SPDY4 doesn't support settings persistence.
4178 static const SpdyHeaderInfo kSynReplyInfo
= {
4179 SYN_REPLY
, // Syn Reply
4181 0, // Associated Stream ID
4182 ConvertRequestPriorityToSpdyPriority(
4183 LOWEST
, spdy_util_
.spdy_version()),
4184 kSpdyCredentialSlotUnused
,
4185 CONTROL_FLAG_NONE
, // Control Flags
4186 false, // Compressed
4187 RST_STREAM_INVALID
, // Status
4190 DATA_FLAG_NONE
// Data Flags
4193 BoundNetLog net_log
;
4194 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4195 net_log
, GetParam(), NULL
);
4196 helper
.RunPreTestSetup();
4198 // Verify that no settings exist initially.
4199 HostPortPair
host_port_pair("www.example.org", helper
.port());
4200 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4201 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4202 host_port_pair
).empty());
4204 // Construct the request.
4205 scoped_ptr
<SpdyFrame
> req(
4206 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4207 MockWrite writes
[] = { CreateMockWrite(*req
) };
4209 // Construct the reply.
4210 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4211 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4212 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4213 scoped_ptr
<SpdyFrame
> reply(
4214 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4216 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4217 unsigned int kSampleValue1
= 0x0a0a0a0a;
4218 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4219 unsigned int kSampleValue2
= 0x0b0b0b0b;
4220 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4221 unsigned int kSampleValue3
= 0x0c0c0c0c;
4222 scoped_ptr
<SpdyFrame
> settings_frame
;
4224 // Construct the SETTINGS frame.
4225 SettingsMap settings
;
4226 // First add a persisted setting.
4227 settings
[kSampleId1
] =
4228 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4229 // Next add a non-persisted setting.
4230 settings
[kSampleId2
] =
4231 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4232 // Next add another persisted setting.
4233 settings
[kSampleId3
] =
4234 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4235 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4238 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4239 MockRead reads
[] = {
4240 CreateMockRead(*reply
),
4241 CreateMockRead(*body
),
4242 CreateMockRead(*settings_frame
),
4243 MockRead(ASYNC
, 0, 0) // EOF
4246 DelayedSocketData
data(1, reads
, arraysize(reads
),
4247 writes
, arraysize(writes
));
4248 helper
.AddData(&data
);
4249 helper
.RunDefaultTest();
4250 helper
.VerifyDataConsumed();
4251 TransactionHelperResult out
= helper
.output();
4252 EXPECT_EQ(OK
, out
.rv
);
4253 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4254 EXPECT_EQ("hello!", out
.response_data
);
4257 // Verify we had two persisted settings.
4258 const SettingsMap
& settings_map
=
4259 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4261 ASSERT_EQ(2u, settings_map
.size());
4263 // Verify the first persisted setting.
4264 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4265 EXPECT_TRUE(it1
!= settings_map
.end());
4266 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4267 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4268 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4270 // Verify the second persisted setting.
4271 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4272 EXPECT_TRUE(it3
!= settings_map
.end());
4273 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4274 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4275 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4279 // Test that when there are settings saved that they are sent back to the
4280 // server upon session establishment.
4281 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4282 if (spdy_util_
.spdy_version() >= SPDY4
) {
4283 // SPDY4 doesn't support settings persistence.
4286 static const SpdyHeaderInfo kSynReplyInfo
= {
4287 SYN_REPLY
, // Syn Reply
4289 0, // Associated Stream ID
4290 ConvertRequestPriorityToSpdyPriority(
4291 LOWEST
, spdy_util_
.spdy_version()),
4292 kSpdyCredentialSlotUnused
,
4293 CONTROL_FLAG_NONE
, // Control Flags
4294 false, // Compressed
4295 RST_STREAM_INVALID
, // Status
4298 DATA_FLAG_NONE
// Data Flags
4301 BoundNetLog net_log
;
4302 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4303 net_log
, GetParam(), NULL
);
4304 helper
.RunPreTestSetup();
4306 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4308 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4309 pool_peer
.SetEnableSendingInitialData(true);
4311 // Verify that no settings exist initially.
4312 HostPortPair
host_port_pair("www.example.org", helper
.port());
4313 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4314 host_port_pair
).empty());
4316 const SpdySettingsIds kSampleId1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
4317 unsigned int kSampleValue1
= 0x0a0a0a0a;
4318 const SpdySettingsIds kSampleId2
= SETTINGS_INITIAL_WINDOW_SIZE
;
4319 unsigned int kSampleValue2
= 0x0c0c0c0c;
4321 // First add a persisted setting.
4322 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4325 SETTINGS_FLAG_PLEASE_PERSIST
,
4328 // Next add another persisted setting.
4329 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4332 SETTINGS_FLAG_PLEASE_PERSIST
,
4335 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4336 host_port_pair
).size());
4338 // Construct the initial SETTINGS frame.
4339 SettingsMap initial_settings
;
4340 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4341 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4342 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4343 spdy_util_
.ConstructSpdySettings(initial_settings
));
4345 // Construct the persisted SETTINGS frame.
4346 const SettingsMap
& settings
=
4347 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4349 scoped_ptr
<SpdyFrame
> settings_frame(
4350 spdy_util_
.ConstructSpdySettings(settings
));
4352 // Construct the request.
4353 scoped_ptr
<SpdyFrame
> req(
4354 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4356 std::vector
<MockWrite
> writes
;
4357 if ((GetParam().protocol
>= kProtoSPDY4MinimumVersion
) &&
4358 (GetParam().protocol
<= kProtoSPDY4MaximumVersion
)) {
4361 kHttp2ConnectionHeaderPrefix
,
4362 kHttp2ConnectionHeaderPrefixSize
));
4364 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4365 writes
.push_back(CreateMockWrite(*settings_frame
));
4366 writes
.push_back(CreateMockWrite(*req
));
4368 // Construct the reply.
4369 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4370 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4371 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4372 scoped_ptr
<SpdyFrame
> reply(
4373 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4375 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4376 MockRead reads
[] = {
4377 CreateMockRead(*reply
),
4378 CreateMockRead(*body
),
4379 MockRead(ASYNC
, 0, 0) // EOF
4382 DelayedSocketData
data(2, reads
, arraysize(reads
),
4383 vector_as_array(&writes
), writes
.size());
4384 helper
.AddData(&data
);
4385 helper
.RunDefaultTest();
4386 helper
.VerifyDataConsumed();
4387 TransactionHelperResult out
= helper
.output();
4388 EXPECT_EQ(OK
, out
.rv
);
4389 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4390 EXPECT_EQ("hello!", out
.response_data
);
4393 // Verify we had two persisted settings.
4394 const SettingsMap
& settings_map
=
4395 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4397 ASSERT_EQ(2u, settings_map
.size());
4399 // Verify the first persisted setting.
4400 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4401 EXPECT_TRUE(it1
!= settings_map
.end());
4402 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4403 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4404 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4406 // Verify the second persisted setting.
4407 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4408 EXPECT_TRUE(it2
!= settings_map
.end());
4409 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4410 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4411 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4415 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4416 scoped_ptr
<SpdyFrame
> req(
4417 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4418 MockWrite writes
[] = { CreateMockWrite(*req
) };
4420 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4421 MockRead reads
[] = {
4422 CreateMockRead(*go_away
),
4425 DelayedSocketData
data(1, reads
, arraysize(reads
),
4426 writes
, arraysize(writes
));
4427 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4428 BoundNetLog(), GetParam(), NULL
);
4429 helper
.AddData(&data
);
4430 helper
.RunToCompletion(&data
);
4431 TransactionHelperResult out
= helper
.output();
4432 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4435 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4436 scoped_ptr
<SpdyFrame
> req(
4437 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4438 MockWrite writes
[] = { CreateMockWrite(*req
) };
4440 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4441 MockRead reads
[] = {
4442 CreateMockRead(*resp
),
4443 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4446 DelayedSocketData
data(1, reads
, arraysize(reads
),
4447 writes
, arraysize(writes
));
4449 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4450 log
, GetParam(), NULL
);
4451 helper
.RunPreTestSetup();
4452 helper
.AddData(&data
);
4453 HttpNetworkTransaction
* trans
= helper
.trans();
4455 TestCompletionCallback callback
;
4456 TransactionHelperResult out
;
4457 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4459 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4460 out
.rv
= callback
.WaitForResult();
4461 EXPECT_EQ(out
.rv
, OK
);
4463 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4464 EXPECT_TRUE(response
->headers
.get() != NULL
);
4465 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4466 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4467 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4469 // Verify that we consumed all test data.
4470 helper
.VerifyDataConsumed();
4473 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4474 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredError
) {
4475 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4476 if (spdy_util_
.spdy_version() < SPDY4
)
4479 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4480 BoundNetLog(), GetParam(), nullptr);
4482 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4483 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4484 MockRead reads
[] = {
4485 CreateMockRead(*go_away
),
4487 DelayedSocketData
data(0, reads
, arraysize(reads
), nullptr, 0);
4489 helper
.RunToCompletion(&data
);
4490 TransactionHelperResult out
= helper
.output();
4491 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED
, out
.rv
);
4494 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4495 // protocol negotiation happens, instead this test forces protocols for both
4497 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredRetry
) {
4498 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4499 if (spdy_util_
.spdy_version() < SPDY4
)
4501 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4502 // only spoken over SSL.
4503 if (GetParam().ssl_type
!= HTTPS_SPDY_VIA_NPN
)
4506 HttpRequestInfo request
;
4507 request
.method
= "GET";
4508 request
.url
= GURL("https://www.example.org/");
4509 scoped_ptr
<SpdySessionDependencies
> session_deps(
4510 CreateSpdySessionDependencies(GetParam()));
4511 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4512 session_deps
->next_protos
= SpdyNextProtos();
4513 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4514 GetParam(), session_deps
.release());
4516 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4517 const char* url
= request
.url
.spec().c_str();
4518 scoped_ptr
<SpdyHeaderBlock
> headers(spdy_util_
.ConstructGetHeaderBlock(url
));
4519 scoped_ptr
<SpdyFrame
> req(
4520 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4521 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4522 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4523 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4524 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4525 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4526 arraysize(writes0
));
4528 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4529 new SSLSocketDataProvider(ASYNC
, OK
));
4530 // Expect HTTP/2 protocols too in SSLConfig.
4531 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4532 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4533 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4534 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4
);
4536 ssl_provider0
->SetNextProto(GetParam().protocol
);
4537 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4539 // Second socket: falling back to HTTP/1.1.
4540 MockWrite writes1
[] = {MockWrite(
4541 "GET / HTTP/1.1\r\n"
4542 "Host: www.example.org\r\n"
4543 "Connection: keep-alive\r\n\r\n")};
4544 MockRead reads1
[] = {MockRead(
4545 "HTTP/1.1 200 OK\r\n"
4546 "Content-Length: 5\r\n\r\n"
4548 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4549 arraysize(writes1
));
4551 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4552 new SSLSocketDataProvider(ASYNC
, OK
));
4553 // Expect only HTTP/1.1 protocol in SSLConfig.
4554 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4556 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4557 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4559 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4560 helper
.session()->spdy_session_pool()->http_server_properties();
4561 const HostPortPair host_port_pair
= HostPortPair::FromURL(GURL(url
));
4562 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4564 helper
.RunPreTestSetup();
4565 helper
.StartDefaultTest();
4566 helper
.FinishDefaultTestWithoutVerification();
4567 helper
.VerifyDataConsumed();
4568 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4570 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4571 ASSERT_TRUE(response
!= nullptr);
4572 ASSERT_TRUE(response
->headers
.get() != nullptr);
4573 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4574 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4575 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4576 EXPECT_TRUE(response
->was_npn_negotiated
);
4577 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4578 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4579 EXPECT_EQ(443, response
->socket_address
.port());
4580 std::string response_data
;
4581 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4582 EXPECT_EQ("hello", response_data
);
4585 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4586 // proxy. Note that no actual protocol negotiation happens, instead this test
4587 // forces protocols for both sockets.
4588 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredProxyRetry
) {
4589 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4590 if (spdy_util_
.spdy_version() < SPDY4
)
4592 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4593 // only spoken over SSL.
4594 if (GetParam().ssl_type
!= HTTPS_SPDY_VIA_NPN
)
4597 HttpRequestInfo request
;
4598 request
.method
= "GET";
4599 request
.url
= GURL("https://www.example.org/");
4600 scoped_ptr
<SpdySessionDependencies
> session_deps(
4601 CreateSpdySessionDependencies(
4603 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4604 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4605 session_deps
->next_protos
= SpdyNextProtos();
4606 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4607 GetParam(), session_deps
.release());
4609 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4610 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
4611 nullptr, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
4612 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4613 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4614 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4615 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4616 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4617 arraysize(writes0
));
4619 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4620 new SSLSocketDataProvider(ASYNC
, OK
));
4621 // Expect HTTP/2 protocols too in SSLConfig.
4622 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4623 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4624 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4625 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4
);
4627 ssl_provider0
->SetNextProto(GetParam().protocol
);
4628 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4630 // Second socket: retry using HTTP/1.1.
4631 MockWrite writes1
[] = {
4633 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4634 "Host: www.example.org\r\n"
4635 "Proxy-Connection: keep-alive\r\n\r\n"),
4637 "GET / HTTP/1.1\r\n"
4638 "Host: www.example.org\r\n"
4639 "Connection: keep-alive\r\n\r\n"),
4642 MockRead reads1
[] = {
4643 MockRead(ASYNC
, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4645 "HTTP/1.1 200 OK\r\n"
4646 "Content-Length: 5\r\n\r\n"
4649 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4650 arraysize(writes1
));
4652 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4653 new SSLSocketDataProvider(ASYNC
, OK
));
4654 // Expect only HTTP/1.1 protocol in SSLConfig.
4655 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4657 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4658 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4660 // A third socket is needed for the tunnelled connection.
4661 scoped_ptr
<SSLSocketDataProvider
> ssl_provider2(
4662 new SSLSocketDataProvider(ASYNC
, OK
));
4663 helper
.session_deps()->socket_factory
->AddSSLSocketDataProvider(
4664 ssl_provider2
.get());
4666 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4667 helper
.session()->spdy_session_pool()->http_server_properties();
4668 const HostPortPair proxy_host_port_pair
= HostPortPair("myproxy", 70);
4669 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4671 helper
.RunPreTestSetup();
4672 helper
.StartDefaultTest();
4673 helper
.FinishDefaultTestWithoutVerification();
4674 helper
.VerifyDataConsumed();
4675 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4677 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4678 ASSERT_TRUE(response
!= nullptr);
4679 ASSERT_TRUE(response
->headers
.get() != nullptr);
4680 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4681 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4682 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4683 EXPECT_FALSE(response
->was_npn_negotiated
);
4684 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4685 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4686 EXPECT_EQ(70, response
->socket_address
.port());
4687 std::string response_data
;
4688 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4689 EXPECT_EQ("hello", response_data
);
4692 // Test to make sure we can correctly connect through a proxy.
4693 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4694 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4695 BoundNetLog(), GetParam(), NULL
);
4696 helper
.session_deps().reset(CreateSpdySessionDependencies(
4698 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4699 helper
.SetSession(make_scoped_refptr(
4700 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4701 helper
.RunPreTestSetup();
4702 HttpNetworkTransaction
* trans
= helper
.trans();
4704 const char kConnect443
[] = {
4705 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4706 "Host: www.example.org\r\n"
4707 "Proxy-Connection: keep-alive\r\n\r\n"};
4708 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4709 scoped_ptr
<SpdyFrame
> req(
4710 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4711 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4712 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4714 MockWrite writes
[] = {
4715 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4716 CreateMockWrite(*req
, 2),
4718 MockRead reads
[] = {
4719 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4720 CreateMockRead(*resp
, 3),
4721 CreateMockRead(*body
.get(), 4),
4722 MockRead(ASYNC
, 0, 0, 5),
4724 scoped_ptr
<OrderedSocketData
> data(new OrderedSocketData(
4725 reads
, arraysize(reads
), writes
, arraysize(writes
)));
4727 helper
.AddData(data
.get());
4728 TestCompletionCallback callback
;
4730 int rv
= trans
->Start(
4731 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4734 rv
= callback
.WaitForResult();
4737 // Verify the SYN_REPLY.
4738 HttpResponseInfo response
= *trans
->GetResponseInfo();
4739 EXPECT_TRUE(response
.headers
.get() != NULL
);
4740 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4742 std::string response_data
;
4743 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4744 EXPECT_EQ("hello!", response_data
);
4745 helper
.VerifyDataConsumed();
4748 // Test to make sure we can correctly connect through a proxy to
4749 // www.example.org, if there already exists a direct spdy connection to
4750 // www.example.org. See https://crbug.com/49874.
4751 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4752 // When setting up the first transaction, we store the SpdySessionPool so that
4753 // we can use the same pool in the second transaction.
4754 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4755 BoundNetLog(), GetParam(), NULL
);
4757 // Use a proxy service which returns a proxy fallback list from DIRECT to
4758 // myproxy:70. For this test there will be no fallback, so it is equivalent
4759 // to simply DIRECT. The reason for appending the second proxy is to verify
4760 // that the session pool key used does is just "DIRECT".
4761 helper
.session_deps().reset(CreateSpdySessionDependencies(
4763 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4764 helper
.SetSession(make_scoped_refptr(
4765 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4767 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4768 helper
.RunPreTestSetup();
4770 // Construct and send a simple GET request.
4771 scoped_ptr
<SpdyFrame
> req(
4772 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4773 MockWrite writes
[] = {
4774 CreateMockWrite(*req
, 1),
4777 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4778 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4779 MockRead reads
[] = {
4780 CreateMockRead(*resp
, 2),
4781 CreateMockRead(*body
, 3),
4782 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4783 MockRead(ASYNC
, 0, 5) // EOF
4785 OrderedSocketData
data(reads
, arraysize(reads
),
4786 writes
, arraysize(writes
));
4787 helper
.AddData(&data
);
4788 HttpNetworkTransaction
* trans
= helper
.trans();
4790 TestCompletionCallback callback
;
4791 TransactionHelperResult out
;
4792 out
.rv
= trans
->Start(
4793 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4795 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4796 out
.rv
= callback
.WaitForResult();
4797 EXPECT_EQ(out
.rv
, OK
);
4799 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4800 EXPECT_TRUE(response
->headers
.get() != NULL
);
4801 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4802 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4803 EXPECT_EQ(OK
, out
.rv
);
4804 out
.status_line
= response
->headers
->GetStatusLine();
4805 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4806 EXPECT_EQ("hello!", out
.response_data
);
4808 // Check that the SpdySession is still in the SpdySessionPool.
4809 HostPortPair
host_port_pair("www.example.org", helper
.port());
4810 SpdySessionKey
session_pool_key_direct(
4811 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4812 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4813 SpdySessionKey
session_pool_key_proxy(
4815 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4816 PRIVACY_MODE_DISABLED
);
4817 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4819 // Set up data for the proxy connection.
4820 const char kConnect443
[] = {
4821 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4822 "Host: www.example.org\r\n"
4823 "Proxy-Connection: keep-alive\r\n\r\n"};
4824 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4825 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4826 GetDefaultUrlWithPath("/foo.dat").c_str(), false, 1, LOWEST
));
4827 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4828 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4830 MockWrite writes2
[] = {
4831 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4832 CreateMockWrite(*req2
, 2),
4834 MockRead reads2
[] = {
4835 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4836 CreateMockRead(*resp2
, 3),
4837 CreateMockRead(*body2
, 4),
4838 MockRead(ASYNC
, 0, 5) // EOF
4841 scoped_ptr
<OrderedSocketData
> data_proxy(new OrderedSocketData(
4842 reads2
, arraysize(reads2
), writes2
, arraysize(writes2
)));
4844 // Create another request to www.example.org, but this time through a proxy.
4845 HttpRequestInfo request_proxy
;
4846 request_proxy
.method
= "GET";
4847 request_proxy
.url
= GURL(GetDefaultUrlWithPath("/foo.dat"));
4848 request_proxy
.load_flags
= 0;
4849 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
4850 CreateSpdySessionDependencies(GetParam()));
4851 // Ensure that this transaction uses the same SpdySessionPool.
4852 scoped_refptr
<HttpNetworkSession
> session_proxy(
4853 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4854 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
4855 BoundNetLog(), GetParam(), NULL
);
4856 HttpNetworkSessionPeer
session_peer(session_proxy
);
4857 scoped_ptr
<ProxyService
> proxy_service(
4858 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4859 session_peer
.SetProxyService(proxy_service
.get());
4860 helper_proxy
.session_deps().swap(ssd_proxy
);
4861 helper_proxy
.SetSession(session_proxy
);
4862 helper_proxy
.RunPreTestSetup();
4863 helper_proxy
.AddData(data_proxy
.get());
4865 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4866 TestCompletionCallback callback_proxy
;
4867 int rv
= trans_proxy
->Start(
4868 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
4869 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4870 rv
= callback_proxy
.WaitForResult();
4873 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4874 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
4875 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4877 std::string response_data
;
4878 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4879 EXPECT_EQ("hello!", response_data
);
4881 data
.CompleteRead();
4882 helper_proxy
.VerifyDataConsumed();
4885 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4886 // on a new connection, if the connection was previously known to be good.
4887 // This can happen when a server reboots without saying goodbye, or when
4888 // we're behind a NAT that masked the RST.
4889 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4890 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4891 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4892 MockRead reads
[] = {
4893 CreateMockRead(*resp
),
4894 CreateMockRead(*body
),
4895 MockRead(ASYNC
, ERR_IO_PENDING
),
4896 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
4899 MockRead reads2
[] = {
4900 CreateMockRead(*resp
),
4901 CreateMockRead(*body
),
4902 MockRead(ASYNC
, 0, 0) // EOF
4905 // This test has a couple of variants.
4907 // Induce the RST while waiting for our transaction to send.
4908 VARIANT_RST_DURING_SEND_COMPLETION
,
4909 // Induce the RST while waiting for our transaction to read.
4910 // In this case, the send completed - everything copied into the SNDBUF.
4911 VARIANT_RST_DURING_READ_COMPLETION
4914 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4915 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4917 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
4919 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
4921 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4922 BoundNetLog(), GetParam(), NULL
);
4923 helper
.AddData(&data1
);
4924 helper
.AddData(&data2
);
4925 helper
.RunPreTestSetup();
4927 for (int i
= 0; i
< 2; ++i
) {
4928 scoped_ptr
<HttpNetworkTransaction
> trans(
4929 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
4931 TestCompletionCallback callback
;
4932 int rv
= trans
->Start(
4933 &helper
.request(), callback
.callback(), BoundNetLog());
4934 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4935 // On the second transaction, we trigger the RST.
4937 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4938 // Writes to the socket complete asynchronously on SPDY by running
4939 // through the message loop. Complete the write here.
4940 base::RunLoop().RunUntilIdle();
4943 // Now schedule the ERR_CONNECTION_RESET.
4944 EXPECT_EQ(3u, data1
.read_index());
4945 data1
.CompleteRead();
4946 EXPECT_EQ(4u, data1
.read_index());
4948 rv
= callback
.WaitForResult();
4951 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4952 ASSERT_TRUE(response
!= NULL
);
4953 EXPECT_TRUE(response
->headers
.get() != NULL
);
4954 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4955 std::string response_data
;
4956 rv
= ReadTransaction(trans
.get(), &response_data
);
4958 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4959 EXPECT_EQ("hello!", response_data
);
4962 helper
.VerifyDataConsumed();
4966 // Test that turning SPDY on and off works properly.
4967 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4968 HttpStreamFactory::set_spdy_enabled(true);
4969 scoped_ptr
<SpdyFrame
> req(
4970 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4971 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4973 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4974 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4975 MockRead spdy_reads
[] = {
4976 CreateMockRead(*resp
),
4977 CreateMockRead(*body
),
4978 MockRead(ASYNC
, 0, 0) // EOF
4981 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
4982 spdy_writes
, arraysize(spdy_writes
));
4983 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4984 BoundNetLog(), GetParam(), NULL
);
4985 helper
.RunToCompletion(&data
);
4986 TransactionHelperResult out
= helper
.output();
4987 EXPECT_EQ(OK
, out
.rv
);
4988 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4989 EXPECT_EQ("hello!", out
.response_data
);
4991 HttpStreamFactory::set_spdy_enabled(false);
4992 MockRead http_reads
[] = {
4993 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4994 MockRead("hello from http"),
4995 MockRead(SYNCHRONOUS
, OK
),
4997 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
4998 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
4999 BoundNetLog(), GetParam(), NULL
);
5000 helper2
.SetSpdyDisabled();
5001 helper2
.RunToCompletion(&data2
);
5002 TransactionHelperResult out2
= helper2
.output();
5003 EXPECT_EQ(OK
, out2
.rv
);
5004 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
5005 EXPECT_EQ("hello from http", out2
.response_data
);
5007 HttpStreamFactory::set_spdy_enabled(true);
5010 // Tests that Basic authentication works over SPDY
5011 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
5012 HttpStreamFactory::set_spdy_enabled(true);
5014 // The first request will be a bare GET, the second request will be a
5015 // GET with an Authorization header.
5016 scoped_ptr
<SpdyFrame
> req_get(
5017 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5018 const char* const kExtraAuthorizationHeaders
[] = {
5019 "authorization", "Basic Zm9vOmJhcg=="
5021 scoped_ptr
<SpdyFrame
> req_get_authorization(
5022 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
5023 arraysize(kExtraAuthorizationHeaders
) / 2,
5024 false, 3, LOWEST
, true));
5025 MockWrite spdy_writes
[] = {
5026 CreateMockWrite(*req_get
, 1),
5027 CreateMockWrite(*req_get_authorization
, 4),
5030 // The first response is a 401 authentication challenge, and the second
5031 // response will be a 200 response since the second request includes a valid
5032 // Authorization header.
5033 const char* const kExtraAuthenticationHeaders
[] = {
5035 "Basic realm=\"MyRealm\""
5037 scoped_ptr
<SpdyFrame
> resp_authentication(
5038 spdy_util_
.ConstructSpdySynReplyError(
5039 "401 Authentication Required",
5040 kExtraAuthenticationHeaders
,
5041 arraysize(kExtraAuthenticationHeaders
) / 2,
5043 scoped_ptr
<SpdyFrame
> body_authentication(
5044 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5045 scoped_ptr
<SpdyFrame
> resp_data(
5046 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5047 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5048 MockRead spdy_reads
[] = {
5049 CreateMockRead(*resp_authentication
, 2),
5050 CreateMockRead(*body_authentication
, 3),
5051 CreateMockRead(*resp_data
, 5),
5052 CreateMockRead(*body_data
, 6),
5053 MockRead(ASYNC
, 0, 7),
5056 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5057 spdy_writes
, arraysize(spdy_writes
));
5058 HttpRequestInfo
request(CreateGetRequest());
5059 BoundNetLog net_log
;
5060 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5061 net_log
, GetParam(), NULL
);
5063 helper
.RunPreTestSetup();
5064 helper
.AddData(&data
);
5065 HttpNetworkTransaction
* trans
= helper
.trans();
5066 TestCompletionCallback callback
;
5067 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5068 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5069 const int rv_start_complete
= callback
.WaitForResult();
5070 EXPECT_EQ(OK
, rv_start_complete
);
5072 // Make sure the response has an auth challenge.
5073 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5074 ASSERT_TRUE(response_start
!= NULL
);
5075 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5076 EXPECT_EQ(401, response_start
->headers
->response_code());
5077 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5078 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5079 ASSERT_TRUE(auth_challenge
!= NULL
);
5080 EXPECT_FALSE(auth_challenge
->is_proxy
);
5081 EXPECT_EQ("basic", auth_challenge
->scheme
);
5082 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5084 // Restart with a username/password.
5085 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5086 base::ASCIIToUTF16("bar"));
5087 TestCompletionCallback callback_restart
;
5088 const int rv_restart
= trans
->RestartWithAuth(
5089 credentials
, callback_restart
.callback());
5090 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5091 const int rv_restart_complete
= callback_restart
.WaitForResult();
5092 EXPECT_EQ(OK
, rv_restart_complete
);
5093 // TODO(cbentzel): This is actually the same response object as before, but
5094 // data has changed.
5095 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5096 ASSERT_TRUE(response_restart
!= NULL
);
5097 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5098 EXPECT_EQ(200, response_restart
->headers
->response_code());
5099 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5102 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5103 scoped_ptr
<SpdyFrame
> stream1_syn(
5104 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5105 scoped_ptr
<SpdyFrame
> stream1_body(
5106 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5107 MockWrite writes
[] = {
5108 CreateMockWrite(*stream1_syn
, 1),
5111 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5112 spdy_util_
.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5113 initial_headers
.get());
5114 scoped_ptr
<SpdyFrame
> stream2_syn(
5115 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5117 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5118 (*late_headers
)["hello"] = "bye";
5119 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5120 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5121 scoped_ptr
<SpdyFrame
> stream2_headers(
5122 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5130 scoped_ptr
<SpdyFrame
>
5131 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5132 const char kPushedData
[] = "pushed";
5133 scoped_ptr
<SpdyFrame
> stream2_body(
5134 spdy_util_
.ConstructSpdyBodyFrame(
5135 2, kPushedData
, strlen(kPushedData
), true));
5136 MockRead reads
[] = {
5137 CreateMockRead(*stream1_reply
, 2),
5138 CreateMockRead(*stream2_syn
, 3),
5139 CreateMockRead(*stream2_headers
, 4),
5140 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5141 CreateMockRead(*stream2_body
, 5),
5142 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5145 HttpResponseInfo response
;
5146 HttpResponseInfo response2
;
5147 std::string
expected_push_result("pushed");
5148 OrderedSocketData
data(reads
, arraysize(reads
),
5149 writes
, arraysize(writes
));
5150 RunServerPushTest(&data
,
5153 expected_push_result
);
5155 // Verify the SYN_REPLY.
5156 EXPECT_TRUE(response
.headers
.get() != NULL
);
5157 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5159 // Verify the pushed stream.
5160 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5161 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5164 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5165 // We push a stream and attempt to claim it before the headers come down.
5166 scoped_ptr
<SpdyFrame
> stream1_syn(
5167 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5168 scoped_ptr
<SpdyFrame
> stream1_body(
5169 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5170 MockWrite writes
[] = {
5171 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5174 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5175 spdy_util_
.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5176 initial_headers
.get());
5177 scoped_ptr
<SpdyFrame
> stream2_syn(
5178 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5180 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5181 (*late_headers
)["hello"] = "bye";
5182 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5183 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5184 scoped_ptr
<SpdyFrame
> stream2_headers(
5185 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5193 scoped_ptr
<SpdyFrame
>
5194 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5195 const char kPushedData
[] = "pushed";
5196 scoped_ptr
<SpdyFrame
> stream2_body(
5197 spdy_util_
.ConstructSpdyBodyFrame(
5198 2, kPushedData
, strlen(kPushedData
), true));
5199 MockRead reads
[] = {
5200 CreateMockRead(*stream1_reply
, 1),
5201 CreateMockRead(*stream2_syn
, 2),
5202 CreateMockRead(*stream1_body
, 3),
5203 CreateMockRead(*stream2_headers
, 4),
5204 CreateMockRead(*stream2_body
, 5),
5205 MockRead(ASYNC
, 0, 6), // EOF
5208 HttpResponseInfo response
;
5209 HttpResponseInfo response2
;
5210 std::string
expected_push_result("pushed");
5211 DeterministicSocketData
data(reads
, arraysize(reads
),
5212 writes
, arraysize(writes
));
5214 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5215 BoundNetLog(), GetParam(), NULL
);
5216 helper
.SetDeterministic();
5217 helper
.AddDeterministicData(&data
);
5218 helper
.RunPreTestSetup();
5220 HttpNetworkTransaction
* trans
= helper
.trans();
5222 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5223 // and the body of the primary stream, but before we've received the HEADERS
5224 // for the pushed stream.
5227 // Start the transaction.
5228 TestCompletionCallback callback
;
5229 int rv
= trans
->Start(
5230 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5231 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5233 rv
= callback
.WaitForResult();
5236 // Request the pushed path. At this point, we've received the push, but the
5237 // headers are not yet complete.
5238 scoped_ptr
<HttpNetworkTransaction
> trans2(
5239 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5241 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5242 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5244 base::RunLoop().RunUntilIdle();
5246 // Read the server push body.
5247 std::string result2
;
5248 ReadResult(trans2
.get(), &data
, &result2
);
5249 // Read the response body.
5251 ReadResult(trans
, &data
, &result
);
5253 // Verify that the received push data is same as the expected push data.
5254 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5255 << "Received data: "
5257 << "||||| Expected data: "
5258 << expected_push_result
;
5260 // Verify the SYN_REPLY.
5261 // Copy the response info, because trans goes away.
5262 response
= *trans
->GetResponseInfo();
5263 response2
= *trans2
->GetResponseInfo();
5265 VerifyStreamsClosed(helper
);
5267 // Verify the SYN_REPLY.
5268 EXPECT_TRUE(response
.headers
.get() != NULL
);
5269 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5271 // Verify the pushed stream.
5272 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5273 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5275 // Read the final EOF (which will close the session)
5278 // Verify that we consumed all test data.
5279 EXPECT_TRUE(data
.at_read_eof());
5280 EXPECT_TRUE(data
.at_write_eof());
5283 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5284 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5285 // We push a stream and attempt to claim it before the headers come down.
5286 scoped_ptr
<SpdyFrame
> stream1_syn(
5287 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5288 scoped_ptr
<SpdyFrame
> stream1_body(
5289 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5290 MockWrite writes
[] = {
5291 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5294 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5295 if (spdy_util_
.spdy_version() < SPDY4
) {
5296 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5297 (*initial_headers
)["alpha"] = "beta";
5299 spdy_util_
.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5300 initial_headers
.get());
5301 scoped_ptr
<SpdyFrame
> stream2_syn(
5302 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5304 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5305 (*middle_headers
)["hello"] = "bye";
5306 scoped_ptr
<SpdyFrame
> stream2_headers1(
5307 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5315 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5316 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5317 if (spdy_util_
.spdy_version() < SPDY4
) {
5318 // SPDY4/HTTP2 eliminates use of the :version header.
5319 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5321 scoped_ptr
<SpdyFrame
> stream2_headers2(
5322 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5330 scoped_ptr
<SpdyFrame
>
5331 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5332 const char kPushedData
[] = "pushed";
5333 scoped_ptr
<SpdyFrame
> stream2_body(
5334 spdy_util_
.ConstructSpdyBodyFrame(
5335 2, kPushedData
, strlen(kPushedData
), true));
5336 MockRead reads
[] = {
5337 CreateMockRead(*stream1_reply
, 1),
5338 CreateMockRead(*stream2_syn
, 2),
5339 CreateMockRead(*stream1_body
, 3),
5340 CreateMockRead(*stream2_headers1
, 4),
5341 CreateMockRead(*stream2_headers2
, 5),
5342 CreateMockRead(*stream2_body
, 6),
5343 MockRead(ASYNC
, 0, 7), // EOF
5346 HttpResponseInfo response
;
5347 HttpResponseInfo response2
;
5348 std::string
expected_push_result("pushed");
5349 DeterministicSocketData
data(reads
, arraysize(reads
),
5350 writes
, arraysize(writes
));
5352 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5353 BoundNetLog(), GetParam(), NULL
);
5354 helper
.SetDeterministic();
5355 helper
.AddDeterministicData(&data
);
5356 helper
.RunPreTestSetup();
5358 HttpNetworkTransaction
* trans
= helper
.trans();
5360 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5361 // the first HEADERS frame, and the body of the primary stream, but before
5362 // we've received the final HEADERS for the pushed stream.
5365 // Start the transaction.
5366 TestCompletionCallback callback
;
5367 int rv
= trans
->Start(
5368 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5371 rv
= callback
.WaitForResult();
5374 // Request the pushed path. At this point, we've received the push, but the
5375 // headers are not yet complete.
5376 scoped_ptr
<HttpNetworkTransaction
> trans2(
5377 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5379 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5380 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5382 base::RunLoop().RunUntilIdle();
5384 // Read the server push body.
5385 std::string result2
;
5386 ReadResult(trans2
.get(), &data
, &result2
);
5387 // Read the response body.
5389 ReadResult(trans
, &data
, &result
);
5391 // Verify that the received push data is same as the expected push data.
5392 EXPECT_EQ(expected_push_result
, result2
);
5394 // Verify the SYN_REPLY.
5395 // Copy the response info, because trans goes away.
5396 response
= *trans
->GetResponseInfo();
5397 response2
= *trans2
->GetResponseInfo();
5399 VerifyStreamsClosed(helper
);
5401 // Verify the SYN_REPLY.
5402 EXPECT_TRUE(response
.headers
.get() != NULL
);
5403 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5405 // Verify the pushed stream.
5406 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5407 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5409 // Verify we got all the headers from all header blocks.
5410 if (spdy_util_
.spdy_version() < SPDY4
)
5411 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5412 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5413 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5415 // Read the final EOF (which will close the session)
5418 // Verify that we consumed all test data.
5419 EXPECT_TRUE(data
.at_read_eof());
5420 EXPECT_TRUE(data
.at_write_eof());
5423 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5424 // We push a stream and attempt to claim it before the headers come down.
5425 scoped_ptr
<SpdyFrame
> stream1_syn(
5426 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5427 scoped_ptr
<SpdyFrame
> stream1_body(
5428 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5429 MockWrite writes
[] = {
5430 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5433 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5434 spdy_util_
.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5435 initial_headers
.get());
5436 scoped_ptr
<SpdyFrame
> stream2_syn(
5437 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5439 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5440 (*middle_headers
)["hello"] = "bye";
5441 scoped_ptr
<SpdyFrame
> stream2_headers1(
5442 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5450 scoped_ptr
<SpdyFrame
>
5451 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5452 const char kPushedData
[] = "pushed";
5453 scoped_ptr
<SpdyFrame
> stream2_body(
5454 spdy_util_
.ConstructSpdyBodyFrame(
5455 2, kPushedData
, strlen(kPushedData
), true));
5456 MockRead reads
[] = {
5457 CreateMockRead(*stream1_reply
, 1),
5458 CreateMockRead(*stream2_syn
, 2),
5459 CreateMockRead(*stream1_body
, 3),
5460 CreateMockRead(*stream2_headers1
, 4),
5461 CreateMockRead(*stream2_body
, 5),
5462 MockRead(ASYNC
, 0, 6), // EOF
5465 DeterministicSocketData
data(reads
, arraysize(reads
),
5466 writes
, arraysize(writes
));
5468 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5469 BoundNetLog(), GetParam(), NULL
);
5470 helper
.SetDeterministic();
5471 helper
.AddDeterministicData(&data
);
5472 helper
.RunPreTestSetup();
5474 HttpNetworkTransaction
* trans
= helper
.trans();
5476 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5477 // the first HEADERS frame, and the body of the primary stream, but before
5478 // we've received the final HEADERS for the pushed stream.
5481 // Start the transaction.
5482 TestCompletionCallback callback
;
5483 int rv
= trans
->Start(
5484 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5485 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5487 rv
= callback
.WaitForResult();
5490 // Request the pushed path. At this point, we've received the push, but the
5491 // headers are not yet complete.
5492 scoped_ptr
<HttpNetworkTransaction
> trans2(
5493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5495 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5496 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5498 base::RunLoop().RunUntilIdle();
5500 // Read the server push body.
5501 std::string result2
;
5502 ReadResult(trans2
.get(), &data
, &result2
);
5503 // Read the response body.
5505 ReadResult(trans
, &data
, &result
);
5506 EXPECT_EQ("hello!", result
);
5508 // Verify that we haven't received any push data.
5509 EXPECT_EQ("", result2
);
5511 // Verify the SYN_REPLY.
5512 // Copy the response info, because trans goes away.
5513 HttpResponseInfo response
= *trans
->GetResponseInfo();
5514 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5516 VerifyStreamsClosed(helper
);
5518 // Verify the SYN_REPLY.
5519 EXPECT_TRUE(response
.headers
.get() != NULL
);
5520 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5522 // Read the final EOF (which will close the session).
5525 // Verify that we consumed all test data.
5526 EXPECT_TRUE(data
.at_read_eof());
5527 EXPECT_TRUE(data
.at_write_eof());
5530 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5531 scoped_ptr
<SpdyFrame
> req(
5532 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5533 scoped_ptr
<SpdyFrame
> rst(
5534 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5535 MockWrite writes
[] = {
5536 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5539 scoped_ptr
<SpdyFrame
> stream1_reply(
5540 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5542 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5543 (*late_headers
)["hello"] = "bye";
5544 scoped_ptr
<SpdyFrame
> stream1_headers(
5545 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5552 scoped_ptr
<SpdyFrame
> stream1_body(
5553 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5554 MockRead reads
[] = {
5555 CreateMockRead(*stream1_reply
),
5556 CreateMockRead(*stream1_headers
),
5557 CreateMockRead(*stream1_body
),
5558 MockRead(ASYNC
, 0, 0) // EOF
5561 DelayedSocketData
data(1, reads
, arraysize(reads
),
5562 writes
, arraysize(writes
));
5563 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5564 BoundNetLog(), GetParam(), NULL
);
5565 helper
.RunToCompletion(&data
);
5566 TransactionHelperResult out
= helper
.output();
5567 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5570 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5571 scoped_ptr
<SpdyFrame
> req(
5572 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5573 scoped_ptr
<SpdyFrame
> rst(
5574 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5575 MockWrite writes
[] = {
5576 CreateMockWrite(*req
),
5577 CreateMockWrite(*rst
),
5580 scoped_ptr
<SpdyFrame
> stream1_reply(
5581 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5583 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5584 (*late_headers
)["hello"] = "bye";
5585 scoped_ptr
<SpdyFrame
> stream1_headers(
5586 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5593 scoped_ptr
<SpdyFrame
> stream1_body(
5594 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5595 scoped_ptr
<SpdyFrame
> stream1_body2(
5596 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5597 MockRead reads
[] = {
5598 CreateMockRead(*stream1_reply
),
5599 CreateMockRead(*stream1_body
),
5600 CreateMockRead(*stream1_headers
),
5601 CreateMockRead(*stream1_body2
),
5602 MockRead(ASYNC
, 0, 0) // EOF
5605 DelayedSocketData
data(1, reads
, arraysize(reads
),
5606 writes
, arraysize(writes
));
5607 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5608 BoundNetLog(), GetParam(), NULL
);
5609 helper
.RunToCompletion(&data
);
5610 TransactionHelperResult out
= helper
.output();
5611 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5614 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5615 // Running these tests via Alt-Svc is too complicated to be worthwhile.
5616 if (GetParam().ssl_type
!= HTTPS_SPDY_VIA_NPN
)
5619 // In this test we want to verify that we can't accidentally push content
5620 // which can't be pushed by this content server.
5621 // This test assumes that:
5622 // - if we're requesting http://www.foo.com/barbaz
5623 // - the browser has made a connection to "www.foo.com".
5625 // A list of the URL to fetch, followed by the URL being pushed.
5626 static const char* const kTestCases
[] = {
5627 "https://www.example.org/foo.html",
5628 "https://www.example.org:81/foo.js", // Bad port
5630 "https://www.example.org/foo.html",
5631 "http://www.example.org/foo.js", // Bad protocol
5633 "https://www.example.org/foo.html",
5634 "ftp://www.example.org/foo.js", // Invalid Protocol
5636 "https://www.example.org/foo.html",
5637 "https://blat.www.example.org/foo.js", // Cross subdomain
5639 "https://www.example.org/foo.html",
5640 "https://www.foo.com/foo.js", // Cross domain
5643 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5644 const char* url_to_fetch
= kTestCases
[index
];
5645 const char* url_to_push
= kTestCases
[index
+ 1];
5647 scoped_ptr
<SpdyFrame
> stream1_syn(
5648 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5649 scoped_ptr
<SpdyFrame
> stream1_body(
5650 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5651 scoped_ptr
<SpdyFrame
> push_rst(
5652 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5653 MockWrite writes
[] = {
5654 CreateMockWrite(*stream1_syn
, 1),
5655 CreateMockWrite(*push_rst
, 4),
5658 scoped_ptr
<SpdyFrame
>
5659 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5660 scoped_ptr
<SpdyFrame
>
5661 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5666 const char kPushedData
[] = "pushed";
5667 scoped_ptr
<SpdyFrame
> stream2_body(
5668 spdy_util_
.ConstructSpdyBodyFrame(
5669 2, kPushedData
, strlen(kPushedData
), true));
5670 scoped_ptr
<SpdyFrame
> rst(
5671 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5673 MockRead reads
[] = {
5674 CreateMockRead(*stream1_reply
, 2),
5675 CreateMockRead(*stream2_syn
, 3),
5676 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5677 CreateMockRead(*stream2_body
, 6),
5678 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5681 HttpResponseInfo response
;
5682 OrderedSocketData
data(reads
, arraysize(reads
),
5683 writes
, arraysize(writes
));
5685 HttpRequestInfo request
;
5686 request
.method
= "GET";
5687 request
.url
= GURL(url_to_fetch
);
5688 request
.load_flags
= 0;
5690 // Enable cross-origin push. Since we are not using a proxy, this should
5691 // not actually enable cross-origin SPDY push.
5692 scoped_ptr
<SpdySessionDependencies
> session_deps(
5693 CreateSpdySessionDependencies(GetParam()));
5694 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5695 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5696 BoundNetLog(), GetParam(),
5697 session_deps
.release());
5698 helper
.RunPreTestSetup();
5699 helper
.AddData(&data
);
5701 HttpNetworkTransaction
* trans
= helper
.trans();
5703 // Start the transaction with basic parameters.
5704 TestCompletionCallback callback
;
5706 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5707 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5708 rv
= callback
.WaitForResult();
5710 // Read the response body.
5712 ReadResult(trans
, &data
, &result
);
5714 // Verify that we consumed all test data.
5715 EXPECT_TRUE(data
.at_read_eof());
5716 EXPECT_TRUE(data
.at_write_eof());
5718 // Verify the SYN_REPLY.
5719 // Copy the response info, because trans goes away.
5720 response
= *trans
->GetResponseInfo();
5722 VerifyStreamsClosed(helper
);
5724 // Verify the SYN_REPLY.
5725 EXPECT_TRUE(response
.headers
.get() != NULL
);
5726 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5730 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5731 // Construct the request.
5732 scoped_ptr
<SpdyFrame
> req(
5733 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5734 scoped_ptr
<SpdyFrame
> req2(
5735 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5736 MockWrite writes
[] = {
5737 CreateMockWrite(*req
, 1),
5738 CreateMockWrite(*req2
, 3),
5741 scoped_ptr
<SpdyFrame
> refused(
5742 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5743 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5744 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5745 MockRead reads
[] = {
5746 CreateMockRead(*refused
, 2),
5747 CreateMockRead(*resp
, 4),
5748 CreateMockRead(*body
, 5),
5749 MockRead(ASYNC
, 0, 6) // EOF
5752 OrderedSocketData
data(reads
, arraysize(reads
),
5753 writes
, arraysize(writes
));
5754 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5755 BoundNetLog(), GetParam(), NULL
);
5757 helper
.RunPreTestSetup();
5758 helper
.AddData(&data
);
5760 HttpNetworkTransaction
* trans
= helper
.trans();
5762 // Start the transaction with basic parameters.
5763 TestCompletionCallback callback
;
5764 int rv
= trans
->Start(
5765 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5766 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5767 rv
= callback
.WaitForResult();
5770 // Verify that we consumed all test data.
5771 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5772 << data
.read_count()
5774 << data
.read_index();
5775 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5776 << data
.write_count()
5778 << data
.write_index();
5780 // Verify the SYN_REPLY.
5781 HttpResponseInfo response
= *trans
->GetResponseInfo();
5782 EXPECT_TRUE(response
.headers
.get() != NULL
);
5783 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5786 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5787 // This first request will start to establish the SpdySession.
5788 // Then we will start the second (MEDIUM priority) and then third
5789 // (HIGHEST priority) request in such a way that the third will actually
5790 // start before the second, causing the second to be numbered differently
5791 // than the order they were created.
5792 scoped_ptr
<SpdyFrame
> req1(
5793 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5794 scoped_ptr
<SpdyFrame
> req2(
5795 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5796 scoped_ptr
<SpdyFrame
> req3(
5797 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5798 MockWrite writes
[] = {
5799 CreateMockWrite(*req1
, 0),
5800 CreateMockWrite(*req2
, 3),
5801 CreateMockWrite(*req3
, 4),
5804 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5805 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5806 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5807 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5808 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5809 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5810 MockRead reads
[] = {
5811 CreateMockRead(*resp1
, 1),
5812 CreateMockRead(*body1
, 2),
5813 CreateMockRead(*resp2
, 5),
5814 CreateMockRead(*body2
, 6),
5815 CreateMockRead(*resp3
, 7),
5816 CreateMockRead(*body3
, 8),
5817 MockRead(ASYNC
, 0, 9) // EOF
5820 DeterministicSocketData
data(reads
, arraysize(reads
),
5821 writes
, arraysize(writes
));
5822 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5823 BoundNetLog(), GetParam(), NULL
);
5824 helper
.SetDeterministic();
5825 helper
.RunPreTestSetup();
5826 helper
.AddDeterministicData(&data
);
5828 // Start the first transaction to set up the SpdySession
5829 HttpNetworkTransaction
* trans
= helper
.trans();
5830 TestCompletionCallback callback
;
5831 HttpRequestInfo info1
= CreateGetRequest();
5832 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
5833 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5835 // Run the message loop, but do not allow the write to complete.
5836 // This leaves the SpdySession with a write pending, which prevents
5837 // SpdySession from attempting subsequent writes until this write completes.
5838 base::RunLoop().RunUntilIdle();
5840 // Now, start both new transactions
5841 HttpRequestInfo info2
= CreateGetRequest();
5842 TestCompletionCallback callback2
;
5843 scoped_ptr
<HttpNetworkTransaction
> trans2(
5844 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
5845 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
5846 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5847 base::RunLoop().RunUntilIdle();
5849 HttpRequestInfo info3
= CreateGetRequest();
5850 TestCompletionCallback callback3
;
5851 scoped_ptr
<HttpNetworkTransaction
> trans3(
5852 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
5853 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
5854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5855 base::RunLoop().RunUntilIdle();
5857 // We now have two SYN_STREAM frames queued up which will be
5858 // dequeued only once the first write completes, which we
5859 // now allow to happen.
5861 EXPECT_EQ(OK
, callback
.WaitForResult());
5863 // And now we can allow everything else to run to completion.
5866 EXPECT_EQ(OK
, callback2
.WaitForResult());
5867 EXPECT_EQ(OK
, callback3
.WaitForResult());
5869 helper
.VerifyDataConsumed();
5872 // The tests below are only for SPDY/3 and above.
5874 // Test that sent data frames and received WINDOW_UPDATE frames change
5875 // the send_window_size_ correctly.
5877 // WINDOW_UPDATE is different than most other frames in that it can arrive
5878 // while the client is still sending the request body. In order to enforce
5879 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5880 // socket data provider, so that initial read that is done as soon as the
5881 // stream is created, succeeds and schedules another read. This way reads
5882 // and writes are interleaved; after doing a full frame write, SpdyStream
5883 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5884 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5885 // since request has not been completely written, therefore we feed
5886 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5887 // write, leading to a complete write of request body; after that we send
5888 // a reply with a body, to cause a graceful shutdown.
5890 // TODO(agayev): develop a socket data provider where both, reads and
5891 // writes are ordered so that writing tests like these are easy and rewrite
5892 // all these tests using it. Right now we are working around the
5893 // limitations as described above and it's not deterministic, tests may
5894 // fail under specific circumstances.
5895 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
5896 static int kFrameCount
= 2;
5897 scoped_ptr
<std::string
> content(
5898 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
5899 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
5900 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
,
5902 scoped_ptr
<SpdyFrame
> body(
5903 spdy_util_
.ConstructSpdyBodyFrame(
5904 1, content
->c_str(), content
->size(), false));
5905 scoped_ptr
<SpdyFrame
> body_end(
5906 spdy_util_
.ConstructSpdyBodyFrame(
5907 1, content
->c_str(), content
->size(), true));
5909 MockWrite writes
[] = {
5910 CreateMockWrite(*req
, 0),
5911 CreateMockWrite(*body
, 1),
5912 CreateMockWrite(*body_end
, 2),
5915 static const int32 kDeltaWindowSize
= 0xff;
5916 static const int kDeltaCount
= 4;
5917 scoped_ptr
<SpdyFrame
> window_update(
5918 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
5919 scoped_ptr
<SpdyFrame
> window_update_dummy(
5920 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
5921 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
5922 MockRead reads
[] = {
5923 CreateMockRead(*window_update_dummy
, 3),
5924 CreateMockRead(*window_update_dummy
, 4),
5925 CreateMockRead(*window_update_dummy
, 5),
5926 CreateMockRead(*window_update
, 6), // Four updates, therefore window
5927 CreateMockRead(*window_update
, 7), // size should increase by
5928 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
5929 CreateMockRead(*window_update
, 9),
5930 CreateMockRead(*resp
, 10),
5931 CreateMockRead(*body_end
, 11),
5932 MockRead(ASYNC
, 0, 0, 12) // EOF
5935 DeterministicSocketData
data(reads
, arraysize(reads
),
5936 writes
, arraysize(writes
));
5938 ScopedVector
<UploadElementReader
> element_readers
;
5939 for (int i
= 0; i
< kFrameCount
; ++i
) {
5940 element_readers
.push_back(
5941 new UploadBytesElementReader(content
->c_str(), content
->size()));
5943 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5945 // Setup the request
5946 HttpRequestInfo request
;
5947 request
.method
= "POST";
5948 request
.url
= GURL(GetDefaultUrl());
5949 request
.upload_data_stream
= &upload_data_stream
;
5951 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5952 BoundNetLog(), GetParam(), NULL
);
5953 helper
.SetDeterministic();
5954 helper
.AddDeterministicData(&data
);
5955 helper
.RunPreTestSetup();
5957 HttpNetworkTransaction
* trans
= helper
.trans();
5959 TestCompletionCallback callback
;
5960 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5962 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5966 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5967 ASSERT_TRUE(stream
!= NULL
);
5968 ASSERT_TRUE(stream
->stream() != NULL
);
5969 EXPECT_EQ(static_cast<int>(
5970 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol
)) +
5971 kDeltaWindowSize
* kDeltaCount
-
5972 kMaxSpdyFrameChunkSize
* kFrameCount
,
5973 stream
->stream()->send_window_size());
5977 rv
= callback
.WaitForResult();
5980 helper
.VerifyDataConsumed();
5983 // Test that received data frames and sent WINDOW_UPDATE frames change
5984 // the recv_window_size_ correctly.
5985 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
5986 const int32 default_initial_window_size
=
5987 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol
);
5988 // Session level maximum window size that is more than twice the default
5989 // initial window size so that an initial window update is sent.
5990 const int32 session_max_recv_window_size
= 5 * 64 * 1024;
5991 ASSERT_LT(2 * default_initial_window_size
, session_max_recv_window_size
);
5992 // Stream level maximum window size that is less than the session level
5993 // maximum window size so that we test for confusion between the two.
5994 const int32 stream_max_recv_window_size
= 4 * 64 * 1024;
5995 ASSERT_GT(session_max_recv_window_size
, stream_max_recv_window_size
);
5996 // Size of body to be sent. Has to be less than or equal to both window sizes
5997 // so that we do not run out of receiving window. Also has to be greater than
5998 // half of them so that it triggers both a session level and a stream level
5999 // window update frame.
6000 const int32 kTargetSize
= 3 * 64 * 1024;
6001 ASSERT_GE(session_max_recv_window_size
, kTargetSize
);
6002 ASSERT_GE(stream_max_recv_window_size
, kTargetSize
);
6003 ASSERT_LT(session_max_recv_window_size
/ 2, kTargetSize
);
6004 ASSERT_LT(stream_max_recv_window_size
/ 2, kTargetSize
);
6005 // Size of each DATA frame.
6006 const int32 kChunkSize
= 4096;
6007 // Size of window updates.
6008 ASSERT_EQ(0, session_max_recv_window_size
/ 2 % kChunkSize
);
6009 const int32 session_window_update_delta
=
6010 session_max_recv_window_size
/ 2 + kChunkSize
;
6011 ASSERT_EQ(0, stream_max_recv_window_size
/ 2 % kChunkSize
);
6012 const int32 stream_window_update_delta
=
6013 stream_max_recv_window_size
/ 2 + kChunkSize
;
6015 SettingsMap initial_settings
;
6016 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
6017 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
6018 initial_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6019 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, stream_max_recv_window_size
);
6020 scoped_ptr
<SpdyFrame
> initial_settings_frame(
6021 spdy_util_
.ConstructSpdySettings(initial_settings
));
6022 scoped_ptr
<SpdyFrame
> initial_window_update(
6023 spdy_util_
.ConstructSpdyWindowUpdate(
6024 kSessionFlowControlStreamId
,
6025 session_max_recv_window_size
- default_initial_window_size
));
6026 scoped_ptr
<SpdyFrame
> req(
6027 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6028 scoped_ptr
<SpdyFrame
> session_window_update(
6029 spdy_util_
.ConstructSpdyWindowUpdate(0, session_window_update_delta
));
6030 scoped_ptr
<SpdyFrame
> stream_window_update(
6031 spdy_util_
.ConstructSpdyWindowUpdate(1, stream_window_update_delta
));
6033 std::vector
<MockWrite
> writes
;
6034 if ((GetParam().protocol
>= kProtoSPDY4MinimumVersion
) &&
6035 (GetParam().protocol
<= kProtoSPDY4MaximumVersion
)) {
6036 writes
.push_back(MockWrite(ASYNC
, kHttp2ConnectionHeaderPrefix
,
6037 kHttp2ConnectionHeaderPrefixSize
, 0));
6039 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
6040 writes
.push_back(CreateMockWrite(*initial_window_update
));
6041 writes
.push_back(CreateMockWrite(*req
));
6042 writes
.push_back(CreateMockWrite(*session_window_update
));
6043 writes
.push_back(CreateMockWrite(*stream_window_update
));
6045 std::vector
<MockRead
> reads
;
6046 scoped_ptr
<SpdyFrame
> resp(
6047 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6048 reads
.push_back(CreateMockRead(*resp
));
6050 ScopedVector
<SpdyFrame
> body_frames
;
6051 const std::string
body_data(kChunkSize
, 'x');
6052 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
6053 size_t frame_size
= std::min(remaining
, body_data
.size());
6054 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
6055 1, body_data
.data(), frame_size
, false));
6056 reads
.push_back(CreateMockRead(*body_frames
.back()));
6057 remaining
-= frame_size
;
6059 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
6061 DelayedSocketData
data(2, vector_as_array(&reads
), reads
.size(),
6062 vector_as_array(&writes
), writes
.size());
6064 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
6065 BoundNetLog(), GetParam(), NULL
);
6066 helper
.AddData(&data
);
6067 helper
.RunPreTestSetup();
6069 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
6070 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
6071 pool_peer
.SetEnableSendingInitialData(true);
6072 pool_peer
.SetSessionMaxRecvWindowSize(session_max_recv_window_size
);
6073 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
6075 HttpNetworkTransaction
* trans
= helper
.trans();
6076 TestCompletionCallback callback
;
6077 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6079 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6080 rv
= callback
.WaitForResult();
6083 SpdyHttpStream
* stream
=
6084 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6085 ASSERT_TRUE(stream
!= NULL
);
6086 ASSERT_TRUE(stream
->stream() != NULL
);
6088 // All data has been read, but not consumed. The window reflects this.
6089 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size
- kTargetSize
),
6090 stream
->stream()->recv_window_size());
6092 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6093 ASSERT_TRUE(response
!= NULL
);
6094 ASSERT_TRUE(response
->headers
.get() != NULL
);
6095 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
6096 EXPECT_TRUE(response
->was_fetched_via_spdy
);
6098 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6099 // size increased to default.
6100 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kTargetSize
));
6101 EXPECT_EQ(static_cast<int>(kTargetSize
),
6102 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
6103 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size
),
6104 stream
->stream()->recv_window_size());
6105 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6107 // Allow scheduled WINDOW_UPDATE frames to write.
6108 base::RunLoop().RunUntilIdle();
6109 helper
.VerifyDataConsumed();
6112 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6113 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6114 // Number of full frames we hope to write (but will not, used to
6115 // set content-length header correctly)
6116 static int kFrameCount
= 3;
6118 scoped_ptr
<std::string
> content(
6119 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6120 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6121 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
,
6123 scoped_ptr
<SpdyFrame
> body(
6124 spdy_util_
.ConstructSpdyBodyFrame(
6125 1, content
->c_str(), content
->size(), false));
6126 scoped_ptr
<SpdyFrame
> rst(
6127 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6129 // We're not going to write a data frame with FIN, we'll receive a bad
6130 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6131 MockWrite writes
[] = {
6132 CreateMockWrite(*req
, 0),
6133 CreateMockWrite(*body
, 2),
6134 CreateMockWrite(*rst
, 3),
6137 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6138 scoped_ptr
<SpdyFrame
> window_update(
6139 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6140 MockRead reads
[] = {
6141 CreateMockRead(*window_update
, 1),
6142 MockRead(ASYNC
, 0, 4) // EOF
6145 DeterministicSocketData
data(reads
, arraysize(reads
),
6146 writes
, arraysize(writes
));
6148 ScopedVector
<UploadElementReader
> element_readers
;
6149 for (int i
= 0; i
< kFrameCount
; ++i
) {
6150 element_readers
.push_back(
6151 new UploadBytesElementReader(content
->c_str(), content
->size()));
6153 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6155 // Setup the request
6156 HttpRequestInfo request
;
6157 request
.method
= "POST";
6158 request
.url
= GURL(GetDefaultUrl());
6159 request
.upload_data_stream
= &upload_data_stream
;
6161 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6162 BoundNetLog(), GetParam(), NULL
);
6163 helper
.SetDeterministic();
6164 helper
.RunPreTestSetup();
6165 helper
.AddDeterministicData(&data
);
6166 HttpNetworkTransaction
* trans
= helper
.trans();
6168 TestCompletionCallback callback
;
6169 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6170 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6173 ASSERT_TRUE(callback
.have_result());
6174 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6175 helper
.VerifyDataConsumed();
6178 // Test that after hitting a send window size of 0, the write process
6179 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6181 // This test constructs a POST request followed by enough data frames
6182 // containing 'a' that would make the window size 0, followed by another
6183 // data frame containing default content (which is "hello!") and this frame
6184 // also contains a FIN flag. DelayedSocketData is used to enforce all
6185 // writes go through before a read could happen. However, the last frame
6186 // ("hello!") is not supposed to go through since by the time its turn
6187 // arrives, window size is 0. At this point MessageLoop::Run() called via
6188 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6189 // which returns after performing all possible writes. We use DCHECKS to
6190 // ensure that last data frame is still there and stream has stalled.
6191 // After that, next read is artifically enforced, which causes a
6192 // WINDOW_UPDATE to be read and I/O process resumes.
6193 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6194 const int32 initial_window_size
=
6195 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol
);
6196 // Number of frames we need to send to zero out the window size: data
6197 // frames plus SYN_STREAM plus the last data frame; also we need another
6198 // data frame that we will send once the WINDOW_UPDATE is received,
6200 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6202 // Calculate last frame's size; 0 size data frame is legal.
6203 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6205 // Construct content for a data frame of maximum size.
6206 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6208 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6209 GetDefaultUrl(), 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
,
6213 scoped_ptr
<SpdyFrame
> body1(
6214 spdy_util_
.ConstructSpdyBodyFrame(
6215 1, content
.c_str(), content
.size(), false));
6217 // Last frame to zero out the window size.
6218 scoped_ptr
<SpdyFrame
> body2(
6219 spdy_util_
.ConstructSpdyBodyFrame(
6220 1, content
.c_str(), last_frame_size
, false));
6222 // Data frame to be sent once WINDOW_UPDATE frame is received.
6223 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6225 // Fill in mock writes.
6226 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6228 writes
[i
] = CreateMockWrite(*req
);
6229 for (i
= 1; i
< num_writes
- 2; i
++)
6230 writes
[i
] = CreateMockWrite(*body1
);
6231 writes
[i
++] = CreateMockWrite(*body2
);
6232 writes
[i
] = CreateMockWrite(*body3
);
6234 // Construct read frame, give enough space to upload the rest of the
6236 scoped_ptr
<SpdyFrame
> session_window_update(
6237 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6238 scoped_ptr
<SpdyFrame
> window_update(
6239 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6240 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6241 MockRead reads
[] = {
6242 CreateMockRead(*session_window_update
),
6243 CreateMockRead(*session_window_update
),
6244 CreateMockRead(*window_update
),
6245 CreateMockRead(*window_update
),
6246 CreateMockRead(*reply
),
6247 CreateMockRead(*body2
),
6248 CreateMockRead(*body3
),
6249 MockRead(ASYNC
, 0, 0) // EOF
6252 // Skip the session window updates unless we're using SPDY/3.1 and
6254 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6255 size_t num_reads
= arraysize(reads
) - read_offset
;
6257 // Force all writes to happen before any read, last write will not
6258 // actually queue a frame, due to window size being 0.
6259 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6260 writes
.get(), num_writes
);
6262 ScopedVector
<UploadElementReader
> element_readers
;
6263 std::string
upload_data_string(initial_window_size
, 'a');
6264 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6265 element_readers
.push_back(new UploadBytesElementReader(
6266 upload_data_string
.c_str(), upload_data_string
.size()));
6267 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6269 HttpRequestInfo request
;
6270 request
.method
= "POST";
6271 request
.url
= GURL(GetDefaultUrl());
6272 request
.upload_data_stream
= &upload_data_stream
;
6273 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6274 BoundNetLog(), GetParam(), NULL
);
6275 helper
.AddData(&data
);
6276 helper
.RunPreTestSetup();
6278 HttpNetworkTransaction
* trans
= helper
.trans();
6280 TestCompletionCallback callback
;
6281 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6284 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6286 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6287 ASSERT_TRUE(stream
!= NULL
);
6288 ASSERT_TRUE(stream
->stream() != NULL
);
6289 EXPECT_EQ(0, stream
->stream()->send_window_size());
6290 // All the body data should have been read.
6291 // TODO(satorux): This is because of the weirdness in reading the request
6292 // body in OnSendBodyComplete(). See crbug.com/113107.
6293 EXPECT_TRUE(upload_data_stream
.IsEOF());
6294 // But the body is not yet fully sent (kUploadData is not yet sent)
6295 // since we're send-stalled.
6296 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6298 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6299 rv
= callback
.WaitForResult();
6300 helper
.VerifyDataConsumed();
6303 // Test we correctly handle the case where the SETTINGS frame results in
6304 // unstalling the send window.
6305 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6306 const int32 initial_window_size
=
6307 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol
);
6309 // Number of frames we need to send to zero out the window size: data
6310 // frames plus SYN_STREAM plus the last data frame; also we need another
6311 // data frame that we will send once the SETTING is received, therefore +3.
6312 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6314 // Calculate last frame's size; 0 size data frame is legal.
6315 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6317 // Construct content for a data frame of maximum size.
6318 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6320 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6321 GetDefaultUrl(), 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
,
6325 scoped_ptr
<SpdyFrame
> body1(
6326 spdy_util_
.ConstructSpdyBodyFrame(
6327 1, content
.c_str(), content
.size(), false));
6329 // Last frame to zero out the window size.
6330 scoped_ptr
<SpdyFrame
> body2(
6331 spdy_util_
.ConstructSpdyBodyFrame(
6332 1, content
.c_str(), last_frame_size
, false));
6334 // Data frame to be sent once SETTINGS frame is received.
6335 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6337 // Fill in mock reads/writes.
6338 std::vector
<MockRead
> reads
;
6339 std::vector
<MockWrite
> writes
;
6341 writes
.push_back(CreateMockWrite(*req
, i
++));
6342 while (i
< num_writes
- 2)
6343 writes
.push_back(CreateMockWrite(*body1
, i
++));
6344 writes
.push_back(CreateMockWrite(*body2
, i
++));
6346 // Construct read frame for SETTINGS that gives enough space to upload the
6347 // rest of the data.
6348 SettingsMap settings
;
6349 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6350 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
* 2);
6351 scoped_ptr
<SpdyFrame
> settings_frame_large(
6352 spdy_util_
.ConstructSpdySettings(settings
));
6354 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6356 scoped_ptr
<SpdyFrame
> session_window_update(
6357 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6358 if (GetParam().protocol
>= kProtoSPDY31
)
6359 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6361 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6362 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6364 writes
.push_back(CreateMockWrite(*body3
, i
++));
6366 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6367 reads
.push_back(CreateMockRead(*reply
, i
++));
6368 reads
.push_back(CreateMockRead(*body2
, i
++));
6369 reads
.push_back(CreateMockRead(*body3
, i
++));
6370 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6372 // Force all writes to happen before any read, last write will not
6373 // actually queue a frame, due to window size being 0.
6374 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6375 vector_as_array(&writes
), writes
.size());
6377 ScopedVector
<UploadElementReader
> element_readers
;
6378 std::string
upload_data_string(initial_window_size
, 'a');
6379 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6380 element_readers
.push_back(new UploadBytesElementReader(
6381 upload_data_string
.c_str(), upload_data_string
.size()));
6382 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6384 HttpRequestInfo request
;
6385 request
.method
= "POST";
6386 request
.url
= GURL(GetDefaultUrl());
6387 request
.upload_data_stream
= &upload_data_stream
;
6388 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6389 BoundNetLog(), GetParam(), NULL
);
6390 helper
.SetDeterministic();
6391 helper
.RunPreTestSetup();
6392 helper
.AddDeterministicData(&data
);
6394 HttpNetworkTransaction
* trans
= helper
.trans();
6396 TestCompletionCallback callback
;
6397 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6398 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6400 data
.RunFor(num_writes
- 1); // Write as much as we can.
6402 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6403 ASSERT_TRUE(stream
!= NULL
);
6404 ASSERT_TRUE(stream
->stream() != NULL
);
6405 EXPECT_EQ(0, stream
->stream()->send_window_size());
6407 // All the body data should have been read.
6408 // TODO(satorux): This is because of the weirdness in reading the request
6409 // body in OnSendBodyComplete(). See crbug.com/113107.
6410 EXPECT_TRUE(upload_data_stream
.IsEOF());
6411 // But the body is not yet fully sent (kUploadData is not yet sent)
6412 // since we're send-stalled.
6413 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6415 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6416 rv
= callback
.WaitForResult();
6417 helper
.VerifyDataConsumed();
6418 // If stream is NULL, that means it was unstalled and closed.
6419 EXPECT_TRUE(stream
->stream() == NULL
);
6422 // Test we correctly handle the case where the SETTINGS frame results in a
6423 // negative send window size.
6424 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6425 const int32 initial_window_size
=
6426 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol
);
6427 // Number of frames we need to send to zero out the window size: data
6428 // frames plus SYN_STREAM plus the last data frame; also we need another
6429 // data frame that we will send once the SETTING is received, therefore +3.
6430 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6432 // Calculate last frame's size; 0 size data frame is legal.
6433 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6435 // Construct content for a data frame of maximum size.
6436 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6438 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6439 GetDefaultUrl(), 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
,
6443 scoped_ptr
<SpdyFrame
> body1(
6444 spdy_util_
.ConstructSpdyBodyFrame(
6445 1, content
.c_str(), content
.size(), false));
6447 // Last frame to zero out the window size.
6448 scoped_ptr
<SpdyFrame
> body2(
6449 spdy_util_
.ConstructSpdyBodyFrame(
6450 1, content
.c_str(), last_frame_size
, false));
6452 // Data frame to be sent once SETTINGS frame is received.
6453 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6455 // Fill in mock reads/writes.
6456 std::vector
<MockRead
> reads
;
6457 std::vector
<MockWrite
> writes
;
6459 writes
.push_back(CreateMockWrite(*req
, i
++));
6460 while (i
< num_writes
- 2)
6461 writes
.push_back(CreateMockWrite(*body1
, i
++));
6462 writes
.push_back(CreateMockWrite(*body2
, i
++));
6464 // Construct read frame for SETTINGS that makes the send_window_size
6466 SettingsMap new_settings
;
6467 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6468 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
/ 2);
6469 scoped_ptr
<SpdyFrame
> settings_frame_small(
6470 spdy_util_
.ConstructSpdySettings(new_settings
));
6471 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6473 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6474 spdy_util_
.ConstructSpdyWindowUpdate(0, initial_window_size
));
6475 scoped_ptr
<SpdyFrame
> window_update_init_size(
6476 spdy_util_
.ConstructSpdyWindowUpdate(1, initial_window_size
));
6478 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6479 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6480 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6482 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6483 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6485 writes
.push_back(CreateMockWrite(*body3
, i
++));
6487 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6488 reads
.push_back(CreateMockRead(*reply
, i
++));
6489 reads
.push_back(CreateMockRead(*body2
, i
++));
6490 reads
.push_back(CreateMockRead(*body3
, i
++));
6491 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6493 // Force all writes to happen before any read, last write will not
6494 // actually queue a frame, due to window size being 0.
6495 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6496 vector_as_array(&writes
), writes
.size());
6498 ScopedVector
<UploadElementReader
> element_readers
;
6499 std::string
upload_data_string(initial_window_size
, 'a');
6500 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6501 element_readers
.push_back(new UploadBytesElementReader(
6502 upload_data_string
.c_str(), upload_data_string
.size()));
6503 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6505 HttpRequestInfo request
;
6506 request
.method
= "POST";
6507 request
.url
= GURL(GetDefaultUrl());
6508 request
.upload_data_stream
= &upload_data_stream
;
6509 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6510 BoundNetLog(), GetParam(), NULL
);
6511 helper
.SetDeterministic();
6512 helper
.RunPreTestSetup();
6513 helper
.AddDeterministicData(&data
);
6515 HttpNetworkTransaction
* trans
= helper
.trans();
6517 TestCompletionCallback callback
;
6518 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6519 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6521 data
.RunFor(num_writes
- 1); // Write as much as we can.
6523 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6524 ASSERT_TRUE(stream
!= NULL
);
6525 ASSERT_TRUE(stream
->stream() != NULL
);
6526 EXPECT_EQ(0, stream
->stream()->send_window_size());
6528 // All the body data should have been read.
6529 // TODO(satorux): This is because of the weirdness in reading the request
6530 // body in OnSendBodyComplete(). See crbug.com/113107.
6531 EXPECT_TRUE(upload_data_stream
.IsEOF());
6532 // But the body is not yet fully sent (kUploadData is not yet sent)
6533 // since we're send-stalled.
6534 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6536 // Read in WINDOW_UPDATE or SETTINGS frame.
6537 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6538 rv
= callback
.WaitForResult();
6539 helper
.VerifyDataConsumed();
6542 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnOddPushStreamId
) {
6543 if (spdy_util_
.spdy_version() < SPDY3
)
6546 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
6547 spdy_util_
.AddUrlToHeaderBlock("http://www.example.org/a.dat",
6548 push_headers
.get());
6549 scoped_ptr
<SpdyFrame
> push(
6550 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 3, 1));
6551 MockRead reads
[] = {CreateMockRead(*push
, 1)};
6553 scoped_ptr
<SpdyFrame
> req(
6554 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6555 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6556 0, GOAWAY_PROTOCOL_ERROR
, "Odd push stream id."));
6557 MockWrite writes
[] = {
6558 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 2),
6561 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6562 NormalSpdyTransactionHelper
helper(
6563 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6564 helper
.RunToCompletion(&data
);
6565 TransactionHelperResult out
= helper
.output();
6566 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6569 TEST_P(SpdyNetworkTransactionTest
,
6570 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted
) {
6571 if (spdy_util_
.spdy_version() < SPDY3
)
6574 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
6575 NULL
, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
6576 scoped_ptr
<SpdyHeaderBlock
> push_b_headers(new SpdyHeaderBlock
);
6577 spdy_util_
.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
6578 push_b_headers
.get());
6579 scoped_ptr
<SpdyFrame
> push_b(
6580 spdy_util_
.ConstructInitialSpdyPushFrame(push_b_headers
.Pass(), 2, 1));
6581 MockRead reads
[] = {
6582 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
6585 scoped_ptr
<SpdyFrame
> req(
6586 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6587 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6589 GOAWAY_PROTOCOL_ERROR
,
6590 "New push stream id must be greater than the last accepted."));
6591 MockWrite writes
[] = {
6592 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
6595 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6596 NormalSpdyTransactionHelper
helper(
6597 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6598 helper
.RunToCompletion(&data
);
6599 TransactionHelperResult out
= helper
.output();
6600 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6603 class SpdyNetworkTransactionNoTLSUsageCheckTest
6604 : public SpdyNetworkTransactionTest
{
6606 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6607 // Construct the request.
6608 scoped_ptr
<SpdyFrame
> req(
6609 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6610 MockWrite writes
[] = {CreateMockWrite(*req
)};
6612 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6613 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6614 MockRead reads
[] = {
6615 CreateMockRead(*resp
), CreateMockRead(*body
),
6616 MockRead(ASYNC
, 0, 0) // EOF
6619 DelayedSocketData
data(
6620 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6621 HttpRequestInfo request
;
6622 request
.method
= "GET";
6623 request
.url
= GURL("https://www.example.org/");
6624 NormalSpdyTransactionHelper
helper(
6625 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6626 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6627 TransactionHelperResult out
= helper
.output();
6628 EXPECT_EQ(OK
, out
.rv
);
6629 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6630 EXPECT_EQ("hello!", out
.response_data
);
6634 //-----------------------------------------------------------------------------
6635 // All tests are run with three different connection types: SPDY after NPN
6636 // negotiation, SPDY without SSL, and SPDY with SSL.
6638 // TODO(akalin): Use ::testing::Combine() when we are able to use
6640 INSTANTIATE_TEST_CASE_P(
6642 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6643 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31
,
6644 HTTPS_SPDY_VIA_NPN
)));
6646 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6647 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6648 new SSLSocketDataProvider(ASYNC
, OK
));
6649 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6650 &ssl_provider
->connection_status
);
6652 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6655 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6656 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6657 new SSLSocketDataProvider(ASYNC
, OK
));
6658 // Set to TLS_RSA_WITH_NULL_MD5
6659 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6661 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6664 class SpdyNetworkTransactionTLSUsageCheckTest
6665 : public SpdyNetworkTransactionTest
{
6667 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6668 scoped_ptr
<SpdyFrame
> goaway(
6669 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6670 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6672 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6673 HttpRequestInfo request
;
6674 request
.method
= "GET";
6675 request
.url
= GURL("https://www.example.org/");
6676 NormalSpdyTransactionHelper
helper(
6677 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6678 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6679 TransactionHelperResult out
= helper
.output();
6680 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6684 INSTANTIATE_TEST_CASE_P(
6686 SpdyNetworkTransactionTLSUsageCheckTest
,
6688 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, HTTPS_SPDY_VIA_NPN
),
6689 SpdyNetworkTransactionTestParams(kProtoSPDY4
, HTTPS_SPDY_VIA_NPN
)));
6691 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6692 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6693 new SSLSocketDataProvider(ASYNC
, OK
));
6694 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6695 &ssl_provider
->connection_status
);
6697 RunTLSUsageCheckTest(ssl_provider
.Pass());
6700 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6701 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6702 new SSLSocketDataProvider(ASYNC
, OK
));
6703 // Set to TLS_RSA_WITH_NULL_MD5
6704 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6706 RunTLSUsageCheckTest(ssl_provider
.Pass());