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/net_log_unittest.h"
21 #include "net/base/request_priority.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/socket/client_socket_pool_base.h"
29 #include "net/socket/next_proto.h"
30 #include "net/spdy/buffered_spdy_framer.h"
31 #include "net/spdy/spdy_http_stream.h"
32 #include "net/spdy/spdy_http_utils.h"
33 #include "net/spdy/spdy_session.h"
34 #include "net/spdy/spdy_session_pool.h"
35 #include "net/spdy/spdy_test_util_common.h"
36 #include "net/spdy/spdy_test_utils.h"
37 #include "net/ssl/ssl_connection_status_flags.h"
38 #include "net/url_request/url_request_test_util.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/platform_test.h"
42 //-----------------------------------------------------------------------------
51 const char kRequestUrl
[] = "http://www.google.com/";
53 enum SpdyNetworkTransactionTestSSLType
{
59 struct SpdyNetworkTransactionTestParams
{
60 SpdyNetworkTransactionTestParams()
61 : protocol(kProtoSPDY31
),
64 SpdyNetworkTransactionTestParams(
66 SpdyNetworkTransactionTestSSLType ssl_type
)
71 SpdyNetworkTransactionTestSSLType ssl_type
;
74 void UpdateSpdySessionDependencies(
75 SpdyNetworkTransactionTestParams test_params
,
76 SpdySessionDependencies
* session_deps
) {
77 switch (test_params
.ssl_type
) {
79 session_deps
->http_server_properties
.SetAlternateProtocol(
80 HostPortPair("www.google.com", 80), 443,
81 AlternateProtocolFromNextProto(test_params
.protocol
), 1);
82 session_deps
->use_alternate_protocols
= true;
83 session_deps
->next_protos
= SpdyNextProtos();
86 session_deps
->force_spdy_over_ssl
= false;
87 session_deps
->force_spdy_always
= true;
90 session_deps
->force_spdy_over_ssl
= true;
91 session_deps
->force_spdy_always
= true;
98 SpdySessionDependencies
* CreateSpdySessionDependencies(
99 SpdyNetworkTransactionTestParams test_params
) {
100 SpdySessionDependencies
* session_deps
=
101 new SpdySessionDependencies(test_params
.protocol
);
102 UpdateSpdySessionDependencies(test_params
, session_deps
);
106 SpdySessionDependencies
* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params
,
108 ProxyService
* proxy_service
) {
109 SpdySessionDependencies
* session_deps
=
110 new SpdySessionDependencies(test_params
.protocol
, proxy_service
);
111 UpdateSpdySessionDependencies(test_params
, session_deps
);
117 class SpdyNetworkTransactionTest
118 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestParams
> {
120 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol
) {
123 virtual ~SpdyNetworkTransactionTest() {
124 // UploadDataStream may post a deletion tasks back to the message loop on
126 upload_data_stream_
.reset();
127 base::RunLoop().RunUntilIdle();
130 void SetUp() override
{
131 google_get_request_initialized_
= false;
132 google_post_request_initialized_
= false;
133 google_chunked_post_request_initialized_
= false;
134 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
137 struct TransactionHelperResult
{
139 std::string status_line
;
140 std::string response_data
;
141 HttpResponseInfo response_info
;
144 // A helper class that handles all the initial npn/ssl setup.
145 class NormalSpdyTransactionHelper
{
147 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
148 RequestPriority priority
,
149 const BoundNetLog
& log
,
150 SpdyNetworkTransactionTestParams test_params
,
151 SpdySessionDependencies
* session_deps
)
154 session_deps_(session_deps
== NULL
?
155 CreateSpdySessionDependencies(test_params
) :
157 session_(SpdySessionDependencies::SpdyCreateSession(
158 session_deps_
.get())),
160 test_params_(test_params
),
161 deterministic_(false),
162 spdy_enabled_(true) {
163 switch (test_params_
.ssl_type
) {
176 ~NormalSpdyTransactionHelper() {
177 // Any test which doesn't close the socket by sending it an EOF will
178 // have a valid session left open, which leaks the entire session pool.
179 // This is just fine - in fact, some of our tests intentionally do this
180 // so that we can check consistency of the SpdySessionPool as the test
181 // finishes. If we had put an EOF on the socket, the SpdySession would
182 // have closed and we wouldn't be able to check the consistency.
184 // Forcefully close existing sessions here.
185 session()->spdy_session_pool()->CloseAllSessions();
188 void SetDeterministic() {
189 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
190 session_deps_
.get());
191 deterministic_
= true;
194 void SetSpdyDisabled() {
195 spdy_enabled_
= false;
199 void RunPreTestSetup() {
200 if (!session_deps_
.get())
201 session_deps_
.reset(CreateSpdySessionDependencies(test_params_
));
202 if (!session_
.get()) {
203 session_
= SpdySessionDependencies::SpdyCreateSession(
204 session_deps_
.get());
207 // We're now ready to use SSL-npn SPDY.
208 trans_
.reset(new HttpNetworkTransaction(priority_
, session_
.get()));
211 // Start the transaction, read some data, finish.
212 void RunDefaultTest() {
213 if (!StartDefaultTest())
218 bool StartDefaultTest() {
219 output_
.rv
= trans_
->Start(&request_
, callback_
.callback(), log_
);
221 // We expect an IO Pending or some sort of error.
222 EXPECT_LT(output_
.rv
, 0);
223 return output_
.rv
== ERR_IO_PENDING
;
226 void FinishDefaultTest() {
227 output_
.rv
= callback_
.WaitForResult();
228 if (output_
.rv
!= OK
) {
229 session_
->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED
);
234 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
235 ASSERT_TRUE(response
!= NULL
);
236 ASSERT_TRUE(response
->headers
.get() != NULL
);
237 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
238 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
239 if (HttpStreamFactory::spdy_enabled()) {
241 HttpResponseInfo::ConnectionInfoFromNextProto(
242 test_params_
.protocol
),
243 response
->connection_info
);
245 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
,
246 response
->connection_info
);
248 if (test_params_
.ssl_type
== SPDYNPN
&& spdy_enabled_
) {
249 EXPECT_TRUE(response
->was_npn_negotiated
);
251 EXPECT_TRUE(!response
->was_npn_negotiated
);
253 // If SPDY is not enabled, a HTTP request should not be diverted
254 // over a SSL session.
255 if (!spdy_enabled_
) {
256 EXPECT_EQ(request_
.url
.SchemeIs("https"),
257 response
->was_npn_negotiated
);
259 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
260 EXPECT_EQ(port_
, response
->socket_address
.port());
261 output_
.status_line
= response
->headers
->GetStatusLine();
262 output_
.response_info
= *response
; // Make a copy so we can verify.
263 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
266 // Most tests will want to call this function. In particular, the MockReads
267 // should end with an empty read, and that read needs to be processed to
268 // ensure proper deletion of the spdy_session_pool.
269 void VerifyDataConsumed() {
270 for (DataVector::iterator it
= data_vector_
.begin();
271 it
!= data_vector_
.end(); ++it
) {
272 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
273 << (*it
)->read_count()
275 << (*it
)->read_index();
276 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
277 << (*it
)->write_count()
279 << (*it
)->write_index();
283 // Occasionally a test will expect to error out before certain reads are
284 // processed. In that case we want to explicitly ensure that the reads were
286 void VerifyDataNotConsumed() {
287 for (DataVector::iterator it
= data_vector_
.begin();
288 it
!= data_vector_
.end(); ++it
) {
289 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
290 << (*it
)->read_count()
292 << (*it
)->read_index();
293 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
294 << (*it
)->write_count()
296 << (*it
)->write_index();
300 void RunToCompletion(StaticSocketDataProvider
* data
) {
304 VerifyDataConsumed();
307 void RunToCompletionWithSSLData(
308 StaticSocketDataProvider
* data
,
309 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
311 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
313 VerifyDataConsumed();
316 void AddData(StaticSocketDataProvider
* data
) {
317 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
318 new SSLSocketDataProvider(ASYNC
, OK
));
319 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
322 void AddDataWithSSLSocketDataProvider(
323 StaticSocketDataProvider
* data
,
324 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
325 DCHECK(!deterministic_
);
326 data_vector_
.push_back(data
);
327 if (test_params_
.ssl_type
== SPDYNPN
)
328 ssl_provider
->SetNextProto(test_params_
.protocol
);
330 if (test_params_
.ssl_type
== SPDYNPN
||
331 test_params_
.ssl_type
== SPDYSSL
) {
332 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
== SPDYNPN
) {
339 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
340 StaticSocketDataProvider
* hanging_non_alternate_protocol_socket
=
341 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
342 hanging_non_alternate_protocol_socket
->set_connect_data(
343 never_finishing_connect
);
344 session_deps_
->socket_factory
->AddSocketDataProvider(
345 hanging_non_alternate_protocol_socket
);
346 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
350 void AddDeterministicData(DeterministicSocketData
* data
) {
351 DCHECK(deterministic_
);
352 data_vector_
.push_back(data
);
353 SSLSocketDataProvider
* ssl_provider
=
354 new SSLSocketDataProvider(ASYNC
, OK
);
355 if (test_params_
.ssl_type
== SPDYNPN
)
356 ssl_provider
->SetNextProto(test_params_
.protocol
);
358 ssl_vector_
.push_back(ssl_provider
);
359 if (test_params_
.ssl_type
== SPDYNPN
||
360 test_params_
.ssl_type
== SPDYSSL
) {
361 session_deps_
->deterministic_socket_factory
->
362 AddSSLSocketDataProvider(ssl_provider
);
364 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
365 if (test_params_
.ssl_type
== SPDYNPN
) {
366 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
367 DeterministicSocketData
* hanging_non_alternate_protocol_socket
=
368 new DeterministicSocketData(NULL
, 0, NULL
, 0);
369 hanging_non_alternate_protocol_socket
->set_connect_data(
370 never_finishing_connect
);
371 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
372 hanging_non_alternate_protocol_socket
);
373 alternate_deterministic_vector_
.push_back(
374 hanging_non_alternate_protocol_socket
);
378 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
381 HttpNetworkTransaction
* trans() { return trans_
.get(); }
382 void ResetTrans() { trans_
.reset(); }
383 TransactionHelperResult
& output() { return output_
; }
384 const HttpRequestInfo
& request() const { return request_
; }
385 const scoped_refptr
<HttpNetworkSession
>& session() const {
388 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
389 return session_deps_
;
391 int port() const { return port_
; }
392 SpdyNetworkTransactionTestParams
test_params() const {
397 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
398 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
399 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
400 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
401 HttpRequestInfo request_
;
402 RequestPriority priority_
;
403 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
404 scoped_refptr
<HttpNetworkSession
> session_
;
405 TransactionHelperResult output_
;
406 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
407 SSLVector ssl_vector_
;
408 TestCompletionCallback callback_
;
409 scoped_ptr
<HttpNetworkTransaction
> trans_
;
410 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
411 DataVector data_vector_
;
412 AlternateVector alternate_vector_
;
413 AlternateDeterministicVector alternate_deterministic_vector_
;
414 const BoundNetLog
& log_
;
415 SpdyNetworkTransactionTestParams test_params_
;
421 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
422 int expected_status
);
424 void ConnectStatusHelper(const MockRead
& status
);
426 const HttpRequestInfo
& CreateGetPushRequest() {
427 google_get_push_request_
.method
= "GET";
428 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
429 google_get_push_request_
.load_flags
= 0;
430 return google_get_push_request_
;
433 const HttpRequestInfo
& CreateGetRequest() {
434 if (!google_get_request_initialized_
) {
435 google_get_request_
.method
= "GET";
436 google_get_request_
.url
= GURL(kDefaultURL
);
437 google_get_request_
.load_flags
= 0;
438 google_get_request_initialized_
= true;
440 return google_get_request_
;
443 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
444 if (!google_get_request_initialized_
) {
445 google_get_request_
.method
= "GET";
446 google_get_request_
.url
= GURL(kDefaultURL
);
447 google_get_request_
.load_flags
= 0;
448 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
449 google_get_request_initialized_
= true;
451 return google_get_request_
;
454 const HttpRequestInfo
& CreatePostRequest() {
455 if (!google_post_request_initialized_
) {
456 ScopedVector
<UploadElementReader
> element_readers
;
457 element_readers
.push_back(
458 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
459 upload_data_stream_
.reset(
460 new ElementsUploadDataStream(element_readers
.Pass(), 0));
462 google_post_request_
.method
= "POST";
463 google_post_request_
.url
= GURL(kDefaultURL
);
464 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
465 google_post_request_initialized_
= true;
467 return google_post_request_
;
470 const HttpRequestInfo
& CreateFilePostRequest() {
471 if (!google_post_request_initialized_
) {
472 base::FilePath file_path
;
473 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
474 CHECK_EQ(static_cast<int>(kUploadDataSize
),
475 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
477 ScopedVector
<UploadElementReader
> element_readers
;
478 element_readers
.push_back(
479 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
484 upload_data_stream_
.reset(
485 new ElementsUploadDataStream(element_readers
.Pass(), 0));
487 google_post_request_
.method
= "POST";
488 google_post_request_
.url
= GURL(kDefaultURL
);
489 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
490 google_post_request_initialized_
= true;
492 return google_post_request_
;
495 const HttpRequestInfo
& CreateUnreadableFilePostRequest() {
496 if (google_post_request_initialized_
)
497 return google_post_request_
;
499 base::FilePath file_path
;
500 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
501 CHECK_EQ(static_cast<int>(kUploadDataSize
),
502 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
503 CHECK(base::MakeFileUnreadable(file_path
));
505 ScopedVector
<UploadElementReader
> element_readers
;
506 element_readers
.push_back(
507 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
512 upload_data_stream_
.reset(
513 new ElementsUploadDataStream(element_readers
.Pass(), 0));
515 google_post_request_
.method
= "POST";
516 google_post_request_
.url
= GURL(kDefaultURL
);
517 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
518 google_post_request_initialized_
= true;
519 return google_post_request_
;
522 const HttpRequestInfo
& CreateComplexPostRequest() {
523 if (!google_post_request_initialized_
) {
524 const int kFileRangeOffset
= 1;
525 const int kFileRangeLength
= 3;
526 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
528 base::FilePath file_path
;
529 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
530 CHECK_EQ(static_cast<int>(kUploadDataSize
),
531 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
533 ScopedVector
<UploadElementReader
> element_readers
;
534 element_readers
.push_back(
535 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
536 element_readers
.push_back(
537 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
542 element_readers
.push_back(new UploadBytesElementReader(
543 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
544 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
545 upload_data_stream_
.reset(
546 new ElementsUploadDataStream(element_readers
.Pass(), 0));
548 google_post_request_
.method
= "POST";
549 google_post_request_
.url
= GURL(kDefaultURL
);
550 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
551 google_post_request_initialized_
= true;
553 return google_post_request_
;
556 const HttpRequestInfo
& CreateChunkedPostRequest() {
557 if (!google_chunked_post_request_initialized_
) {
558 upload_chunked_data_stream_
.reset(new ChunkedUploadDataStream(0));
559 google_chunked_post_request_
.method
= "POST";
560 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
561 google_chunked_post_request_
.upload_data_stream
=
562 upload_chunked_data_stream_
.get();
563 google_chunked_post_request_initialized_
= true;
565 return google_chunked_post_request_
;
568 // Read the result of a particular transaction, knowing that we've got
569 // multiple transactions in the read pipeline; so as we read, we may have
570 // to skip over data destined for other transactions while we consume
571 // the data for |trans|.
572 int ReadResult(HttpNetworkTransaction
* trans
,
573 StaticSocketDataProvider
* data
,
574 std::string
* result
) {
575 const int kSize
= 3000;
578 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
579 TestCompletionCallback callback
;
581 int rv
= trans
->Read(buf
.get(), kSize
, callback
.callback());
582 if (rv
== ERR_IO_PENDING
) {
583 // Multiple transactions may be in the data set. Keep pulling off
584 // reads until we complete our callback.
585 while (!callback
.have_result()) {
586 data
->CompleteRead();
587 base::RunLoop().RunUntilIdle();
589 rv
= callback
.WaitForResult();
590 } else if (rv
<= 0) {
593 result
->append(buf
->data(), rv
);
599 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
600 // This lengthy block is reaching into the pool to dig out the active
601 // session. Once we have the session, we verify that the streams are
602 // all closed and not leaked at this point.
603 const GURL
& url
= helper
.request().url
;
604 int port
= helper
.test_params().ssl_type
== SPDYNPN
? 443 : 80;
605 HostPortPair
host_port_pair(url
.host(), port
);
606 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
607 PRIVACY_MODE_DISABLED
);
609 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
610 base::WeakPtr
<SpdySession
> spdy_session
=
611 session
->spdy_session_pool()->FindAvailableSession(key
, log
);
612 ASSERT_TRUE(spdy_session
!= NULL
);
613 EXPECT_EQ(0u, spdy_session
->num_active_streams());
614 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
617 void RunServerPushTest(OrderedSocketData
* data
,
618 HttpResponseInfo
* response
,
619 HttpResponseInfo
* push_response
,
620 const std::string
& expected
) {
621 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
622 BoundNetLog(), GetParam(), NULL
);
623 helper
.RunPreTestSetup();
624 helper
.AddData(data
);
626 HttpNetworkTransaction
* trans
= helper
.trans();
628 // Start the transaction with basic parameters.
629 TestCompletionCallback callback
;
630 int rv
= trans
->Start(
631 &CreateGetRequest(), callback
.callback(), BoundNetLog());
632 EXPECT_EQ(ERR_IO_PENDING
, rv
);
633 rv
= callback
.WaitForResult();
635 // Request the pushed path.
636 scoped_ptr
<HttpNetworkTransaction
> trans2(
637 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
639 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
641 base::RunLoop().RunUntilIdle();
643 // The data for the pushed path may be coming in more than 1 frame. Compile
644 // the results into a single string.
646 // Read the server push body.
648 ReadResult(trans2
.get(), data
, &result2
);
649 // Read the response body.
651 ReadResult(trans
, data
, &result
);
653 // Verify that we consumed all test data.
654 EXPECT_TRUE(data
->at_read_eof());
655 EXPECT_TRUE(data
->at_write_eof());
657 // Verify that the received push data is same as the expected push data.
658 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
660 << "||||| Expected data: "
663 // Verify the SYN_REPLY.
664 // Copy the response info, because trans goes away.
665 *response
= *trans
->GetResponseInfo();
666 *push_response
= *trans2
->GetResponseInfo();
668 VerifyStreamsClosed(helper
);
671 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
673 helper
->ResetTrans();
676 static void StartTransactionCallback(
677 const scoped_refptr
<HttpNetworkSession
>& session
,
679 scoped_ptr
<HttpNetworkTransaction
> trans(
680 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
681 TestCompletionCallback callback
;
682 HttpRequestInfo request
;
683 request
.method
= "GET";
684 request
.url
= GURL("http://www.google.com/");
685 request
.load_flags
= 0;
686 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
688 callback
.WaitForResult();
691 ChunkedUploadDataStream
* upload_chunked_data_stream() const {
692 return upload_chunked_data_stream_
.get();
695 SpdyTestUtil spdy_util_
;
698 scoped_ptr
<ChunkedUploadDataStream
> upload_chunked_data_stream_
;
699 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
700 bool google_get_request_initialized_
;
701 bool google_post_request_initialized_
;
702 bool google_chunked_post_request_initialized_
;
703 HttpRequestInfo google_get_request_
;
704 HttpRequestInfo google_post_request_
;
705 HttpRequestInfo google_chunked_post_request_
;
706 HttpRequestInfo google_get_push_request_
;
707 base::ScopedTempDir temp_dir_
;
710 //-----------------------------------------------------------------------------
711 // All tests are run with three different connection types: SPDY after NPN
712 // negotiation, SPDY without SSL, and SPDY with SSL.
714 // TODO(akalin): Use ::testing::Combine() when we are able to use
716 INSTANTIATE_TEST_CASE_P(
718 SpdyNetworkTransactionTest
,
720 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNOSSL
),
721 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYSSL
),
722 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
),
723 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNOSSL
),
724 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYSSL
),
725 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
726 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNOSSL
),
727 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYSSL
),
728 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNPN
)));
730 // Verify HttpNetworkTransaction constructor.
731 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
732 scoped_ptr
<SpdySessionDependencies
> session_deps(
733 CreateSpdySessionDependencies(GetParam()));
734 scoped_refptr
<HttpNetworkSession
> session(
735 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
736 scoped_ptr
<HttpTransaction
> trans(
737 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
740 TEST_P(SpdyNetworkTransactionTest
, Get
) {
741 // Construct the request.
742 scoped_ptr
<SpdyFrame
> req(
743 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
744 MockWrite writes
[] = { CreateMockWrite(*req
) };
746 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
747 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
749 CreateMockRead(*resp
),
750 CreateMockRead(*body
),
751 MockRead(ASYNC
, 0, 0) // EOF
754 DelayedSocketData
data(1, reads
, arraysize(reads
),
755 writes
, arraysize(writes
));
756 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
757 BoundNetLog(), GetParam(), NULL
);
758 helper
.RunToCompletion(&data
);
759 TransactionHelperResult out
= helper
.output();
760 EXPECT_EQ(OK
, out
.rv
);
761 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
762 EXPECT_EQ("hello!", out
.response_data
);
765 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
766 for (RequestPriority p
= MINIMUM_PRIORITY
; p
<= MAXIMUM_PRIORITY
;
767 p
= RequestPriority(p
+ 1)) {
768 // Construct the request.
769 scoped_ptr
<SpdyFrame
> req(
770 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
771 MockWrite writes
[] = { CreateMockWrite(*req
) };
773 SpdyPriority spdy_prio
= 0;
774 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
775 // this repeats the RequestPriority-->SpdyPriority mapping from
776 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
777 // sure it's being done right.
778 if (spdy_util_
.spdy_version() < SPDY3
) {
781 EXPECT_EQ(0, spdy_prio
);
784 EXPECT_EQ(1, spdy_prio
);
788 EXPECT_EQ(2, spdy_prio
);
791 EXPECT_EQ(3, spdy_prio
);
799 EXPECT_EQ(0, spdy_prio
);
802 EXPECT_EQ(1, spdy_prio
);
805 EXPECT_EQ(2, spdy_prio
);
808 EXPECT_EQ(3, spdy_prio
);
811 EXPECT_EQ(4, spdy_prio
);
818 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
819 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
821 CreateMockRead(*resp
),
822 CreateMockRead(*body
),
823 MockRead(ASYNC
, 0, 0) // EOF
826 DelayedSocketData
data(1, reads
, arraysize(reads
),
827 writes
, arraysize(writes
));
828 HttpRequestInfo http_req
= CreateGetRequest();
830 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
832 helper
.RunToCompletion(&data
);
833 TransactionHelperResult out
= helper
.output();
834 EXPECT_EQ(OK
, out
.rv
);
835 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
836 EXPECT_EQ("hello!", out
.response_data
);
840 // Start three gets simultaniously; making sure that multiplexed
841 // streams work properly.
843 // This can't use the TransactionHelper method, since it only
844 // handles a single transaction, and finishes them as soon
845 // as it launches them.
847 // TODO(gavinp): create a working generalized TransactionHelper that
848 // can allow multiple streams in flight.
850 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
851 scoped_ptr
<SpdyFrame
> req(
852 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
853 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
854 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
855 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
857 scoped_ptr
<SpdyFrame
> req2(
858 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
859 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
860 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
861 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
863 scoped_ptr
<SpdyFrame
> req3(
864 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
865 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
866 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
867 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
869 MockWrite writes
[] = {
870 CreateMockWrite(*req
),
871 CreateMockWrite(*req2
),
872 CreateMockWrite(*req3
),
875 CreateMockRead(*resp
, 1),
876 CreateMockRead(*body
),
877 CreateMockRead(*resp2
, 4),
878 CreateMockRead(*body2
),
879 CreateMockRead(*resp3
, 7),
880 CreateMockRead(*body3
),
882 CreateMockRead(*fbody
),
883 CreateMockRead(*fbody2
),
884 CreateMockRead(*fbody3
),
886 MockRead(ASYNC
, 0, 0), // EOF
888 OrderedSocketData
data(reads
, arraysize(reads
),
889 writes
, arraysize(writes
));
890 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
893 TransactionHelperResult out
;
894 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
895 BoundNetLog(), GetParam(), NULL
);
896 helper
.RunPreTestSetup();
897 helper
.AddData(&data
);
898 // We require placeholder data because three get requests are sent out, so
899 // there needs to be three sets of SSL connection data.
900 helper
.AddData(&data_placeholder
);
901 helper
.AddData(&data_placeholder
);
902 scoped_ptr
<HttpNetworkTransaction
> trans1(
903 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
904 scoped_ptr
<HttpNetworkTransaction
> trans2(
905 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
906 scoped_ptr
<HttpNetworkTransaction
> trans3(
907 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
909 TestCompletionCallback callback1
;
910 TestCompletionCallback callback2
;
911 TestCompletionCallback callback3
;
913 HttpRequestInfo httpreq1
= CreateGetRequest();
914 HttpRequestInfo httpreq2
= CreateGetRequest();
915 HttpRequestInfo httpreq3
= CreateGetRequest();
917 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
918 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
919 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
920 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
921 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
922 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
924 out
.rv
= callback1
.WaitForResult();
925 ASSERT_EQ(OK
, out
.rv
);
926 out
.rv
= callback3
.WaitForResult();
927 ASSERT_EQ(OK
, out
.rv
);
929 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
930 EXPECT_TRUE(response1
->headers
.get() != NULL
);
931 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
932 out
.status_line
= response1
->headers
->GetStatusLine();
933 out
.response_info
= *response1
;
935 trans2
->GetResponseInfo();
937 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
938 helper
.VerifyDataConsumed();
939 EXPECT_EQ(OK
, out
.rv
);
941 EXPECT_EQ(OK
, out
.rv
);
942 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
943 EXPECT_EQ("hello!hello!", out
.response_data
);
946 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
947 scoped_ptr
<SpdyFrame
> req(
948 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
949 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
950 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
951 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
953 scoped_ptr
<SpdyFrame
> req2(
954 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
955 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
956 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
957 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
959 MockWrite writes
[] = {
960 CreateMockWrite(*req
),
961 CreateMockWrite(*req2
),
964 CreateMockRead(*resp
, 1),
965 CreateMockRead(*body
),
966 CreateMockRead(*resp2
, 4),
967 CreateMockRead(*body2
),
968 CreateMockRead(*fbody
),
969 CreateMockRead(*fbody2
),
970 MockRead(ASYNC
, 0, 0), // EOF
972 OrderedSocketData
data(reads
, arraysize(reads
),
973 writes
, arraysize(writes
));
975 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
977 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
978 data_placeholder
.set_connect_data(never_finishing_connect
);
981 TransactionHelperResult out
;
982 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
983 BoundNetLog(), GetParam(), NULL
);
984 helper
.RunPreTestSetup();
985 helper
.AddData(&data
);
986 // We require placeholder data because two get requests are sent out, so
987 // there needs to be two sets of SSL connection data.
988 helper
.AddData(&data_placeholder
);
989 scoped_ptr
<HttpNetworkTransaction
> trans1(
990 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
991 scoped_ptr
<HttpNetworkTransaction
> trans2(
992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
994 TestCompletionCallback callback1
;
995 TestCompletionCallback callback2
;
997 HttpRequestInfo httpreq1
= CreateGetRequest();
998 HttpRequestInfo httpreq2
= CreateGetRequest();
1000 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1001 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1002 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1003 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1005 out
.rv
= callback1
.WaitForResult();
1006 ASSERT_EQ(OK
, out
.rv
);
1007 out
.rv
= callback2
.WaitForResult();
1008 ASSERT_EQ(OK
, out
.rv
);
1010 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1011 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1012 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1013 out
.status_line
= response1
->headers
->GetStatusLine();
1014 out
.response_info
= *response1
;
1015 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1016 EXPECT_EQ(OK
, out
.rv
);
1017 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1018 EXPECT_EQ("hello!hello!", out
.response_data
);
1020 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1021 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1022 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1023 out
.status_line
= response2
->headers
->GetStatusLine();
1024 out
.response_info
= *response2
;
1025 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1026 EXPECT_EQ(OK
, out
.rv
);
1027 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1028 EXPECT_EQ("hello!hello!", out
.response_data
);
1030 helper
.VerifyDataConsumed();
1033 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
1034 scoped_ptr
<SpdyFrame
> req(
1035 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1036 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1037 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1038 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1040 scoped_ptr
<SpdyFrame
> req2(
1041 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1042 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1043 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1044 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1046 MockWrite writes
[] = {
1047 CreateMockWrite(*req
),
1048 CreateMockWrite(*req2
),
1050 MockRead reads
[] = {
1051 CreateMockRead(*resp
, 1),
1052 CreateMockRead(*body
),
1053 CreateMockRead(*resp2
, 4),
1054 CreateMockRead(*body2
),
1055 CreateMockRead(*fbody
),
1056 CreateMockRead(*fbody2
),
1057 MockRead(ASYNC
, 0, 0), // EOF
1059 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
1060 writes
, arraysize(writes
));
1062 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1064 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1065 data_placeholder
.set_connect_data(never_finishing_connect
);
1068 TransactionHelperResult out
;
1069 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1070 BoundNetLog(), GetParam(), NULL
);
1071 helper
.RunPreTestSetup();
1072 helper
.AddData(&preconnect_data
);
1073 // We require placeholder data because 3 connections are attempted (first is
1074 // the preconnect, 2nd and 3rd are the never finished connections.
1075 helper
.AddData(&data_placeholder
);
1076 helper
.AddData(&data_placeholder
);
1078 scoped_ptr
<HttpNetworkTransaction
> trans1(
1079 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1080 scoped_ptr
<HttpNetworkTransaction
> trans2(
1081 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1083 TestCompletionCallback callback1
;
1084 TestCompletionCallback callback2
;
1086 HttpRequestInfo httpreq
= CreateGetRequest();
1088 // Preconnect the first.
1089 SSLConfig preconnect_ssl_config
;
1090 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1091 HttpStreamFactory
* http_stream_factory
=
1092 helper
.session()->http_stream_factory();
1093 helper
.session()->GetNextProtos(&preconnect_ssl_config
.next_protos
);
1095 http_stream_factory
->PreconnectStreams(
1096 1, httpreq
, DEFAULT_PRIORITY
,
1097 preconnect_ssl_config
, preconnect_ssl_config
);
1099 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1100 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1101 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1102 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1104 out
.rv
= callback1
.WaitForResult();
1105 ASSERT_EQ(OK
, out
.rv
);
1106 out
.rv
= callback2
.WaitForResult();
1107 ASSERT_EQ(OK
, out
.rv
);
1109 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1110 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1111 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1112 out
.status_line
= response1
->headers
->GetStatusLine();
1113 out
.response_info
= *response1
;
1114 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1115 EXPECT_EQ(OK
, out
.rv
);
1116 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1117 EXPECT_EQ("hello!hello!", out
.response_data
);
1119 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1120 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1121 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1122 out
.status_line
= response2
->headers
->GetStatusLine();
1123 out
.response_info
= *response2
;
1124 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1125 EXPECT_EQ(OK
, out
.rv
);
1126 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1127 EXPECT_EQ("hello!hello!", out
.response_data
);
1129 helper
.VerifyDataConsumed();
1132 // Similar to ThreeGets above, however this test adds a SETTINGS
1133 // frame. The SETTINGS frame is read during the IO loop waiting on
1134 // the first transaction completion, and sets a maximum concurrent
1135 // stream limit of 1. This means that our IO loop exists after the
1136 // second transaction completes, so we can assert on read_index().
1137 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1138 // Construct the request.
1139 scoped_ptr
<SpdyFrame
> req(
1140 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1141 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1142 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1143 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1145 scoped_ptr
<SpdyFrame
> req2(
1146 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1147 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1148 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1149 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1151 scoped_ptr
<SpdyFrame
> req3(
1152 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1153 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1154 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1155 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1157 SettingsMap settings
;
1158 const uint32 max_concurrent_streams
= 1;
1159 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1160 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1161 scoped_ptr
<SpdyFrame
> settings_frame(
1162 spdy_util_
.ConstructSpdySettings(settings
));
1163 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1165 MockWrite writes
[] = {
1166 CreateMockWrite(*req
),
1167 CreateMockWrite(*settings_ack
, 2),
1168 CreateMockWrite(*req2
),
1169 CreateMockWrite(*req3
),
1172 MockRead reads
[] = {
1173 CreateMockRead(*settings_frame
, 1),
1174 CreateMockRead(*resp
),
1175 CreateMockRead(*body
),
1176 CreateMockRead(*fbody
),
1177 CreateMockRead(*resp2
, 8),
1178 CreateMockRead(*body2
),
1179 CreateMockRead(*fbody2
),
1180 CreateMockRead(*resp3
, 13),
1181 CreateMockRead(*body3
),
1182 CreateMockRead(*fbody3
),
1184 MockRead(ASYNC
, 0, 0), // EOF
1187 OrderedSocketData
data(reads
, arraysize(reads
),
1188 writes
, arraysize(writes
));
1189 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1192 TransactionHelperResult out
;
1194 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1195 BoundNetLog(), GetParam(), NULL
);
1196 helper
.RunPreTestSetup();
1197 helper
.AddData(&data
);
1198 // We require placeholder data because three get requests are sent out, so
1199 // there needs to be three sets of SSL connection data.
1200 helper
.AddData(&data_placeholder
);
1201 helper
.AddData(&data_placeholder
);
1202 scoped_ptr
<HttpNetworkTransaction
> trans1(
1203 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1204 scoped_ptr
<HttpNetworkTransaction
> trans2(
1205 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1206 scoped_ptr
<HttpNetworkTransaction
> trans3(
1207 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1209 TestCompletionCallback callback1
;
1210 TestCompletionCallback callback2
;
1211 TestCompletionCallback callback3
;
1213 HttpRequestInfo httpreq1
= CreateGetRequest();
1214 HttpRequestInfo httpreq2
= CreateGetRequest();
1215 HttpRequestInfo httpreq3
= CreateGetRequest();
1217 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1218 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1219 // Run transaction 1 through quickly to force a read of our SETTINGS
1221 out
.rv
= callback1
.WaitForResult();
1222 ASSERT_EQ(OK
, out
.rv
);
1224 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1225 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1226 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1227 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1228 out
.rv
= callback2
.WaitForResult();
1229 ASSERT_EQ(OK
, out
.rv
);
1230 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1232 out
.rv
= callback3
.WaitForResult();
1233 ASSERT_EQ(OK
, out
.rv
);
1235 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1236 ASSERT_TRUE(response1
!= NULL
);
1237 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1238 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1239 out
.status_line
= response1
->headers
->GetStatusLine();
1240 out
.response_info
= *response1
;
1241 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1242 EXPECT_EQ(OK
, out
.rv
);
1243 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1244 EXPECT_EQ("hello!hello!", out
.response_data
);
1246 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1247 out
.status_line
= response2
->headers
->GetStatusLine();
1248 out
.response_info
= *response2
;
1249 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1250 EXPECT_EQ(OK
, out
.rv
);
1251 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1252 EXPECT_EQ("hello!hello!", out
.response_data
);
1254 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1255 out
.status_line
= response3
->headers
->GetStatusLine();
1256 out
.response_info
= *response3
;
1257 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1258 EXPECT_EQ(OK
, out
.rv
);
1259 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1260 EXPECT_EQ("hello!hello!", out
.response_data
);
1262 helper
.VerifyDataConsumed();
1264 EXPECT_EQ(OK
, out
.rv
);
1267 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1268 // a fourth transaction. The third and fourth transactions have
1269 // different data ("hello!" vs "hello!hello!") and because of the
1270 // user specified priority, we expect to see them inverted in
1271 // the response from the server.
1272 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1273 // Construct the request.
1274 scoped_ptr
<SpdyFrame
> req(
1275 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1276 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1277 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1278 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1280 scoped_ptr
<SpdyFrame
> req2(
1281 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1282 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1283 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1284 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1286 scoped_ptr
<SpdyFrame
> req4(
1287 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1288 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1289 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1291 scoped_ptr
<SpdyFrame
> req3(
1292 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1293 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1294 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1295 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1297 SettingsMap settings
;
1298 const uint32 max_concurrent_streams
= 1;
1299 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1300 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1301 scoped_ptr
<SpdyFrame
> settings_frame(
1302 spdy_util_
.ConstructSpdySettings(settings
));
1303 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1305 MockWrite writes
[] = { CreateMockWrite(*req
),
1306 CreateMockWrite(*settings_ack
, 2),
1307 CreateMockWrite(*req2
),
1308 CreateMockWrite(*req4
),
1309 CreateMockWrite(*req3
),
1311 MockRead reads
[] = {
1312 CreateMockRead(*settings_frame
, 1),
1313 CreateMockRead(*resp
),
1314 CreateMockRead(*body
),
1315 CreateMockRead(*fbody
),
1316 CreateMockRead(*resp2
, 8),
1317 CreateMockRead(*body2
),
1318 CreateMockRead(*fbody2
),
1319 CreateMockRead(*resp4
, 14),
1320 CreateMockRead(*fbody4
),
1321 CreateMockRead(*resp3
, 17),
1322 CreateMockRead(*body3
),
1323 CreateMockRead(*fbody3
),
1325 MockRead(ASYNC
, 0, 0), // EOF
1328 OrderedSocketData
data(reads
, arraysize(reads
),
1329 writes
, arraysize(writes
));
1330 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1333 TransactionHelperResult out
;
1334 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1335 BoundNetLog(), GetParam(), NULL
);
1336 helper
.RunPreTestSetup();
1337 helper
.AddData(&data
);
1338 // We require placeholder data because four get requests are sent out, so
1339 // there needs to be four sets of SSL connection data.
1340 helper
.AddData(&data_placeholder
);
1341 helper
.AddData(&data_placeholder
);
1342 helper
.AddData(&data_placeholder
);
1343 scoped_ptr
<HttpNetworkTransaction
> trans1(
1344 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1345 scoped_ptr
<HttpNetworkTransaction
> trans2(
1346 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1347 scoped_ptr
<HttpNetworkTransaction
> trans3(
1348 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1349 scoped_ptr
<HttpNetworkTransaction
> trans4(
1350 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1352 TestCompletionCallback callback1
;
1353 TestCompletionCallback callback2
;
1354 TestCompletionCallback callback3
;
1355 TestCompletionCallback callback4
;
1357 HttpRequestInfo httpreq1
= CreateGetRequest();
1358 HttpRequestInfo httpreq2
= CreateGetRequest();
1359 HttpRequestInfo httpreq3
= CreateGetRequest();
1360 HttpRequestInfo httpreq4
= CreateGetRequest();
1362 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1363 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1364 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1365 out
.rv
= callback1
.WaitForResult();
1366 ASSERT_EQ(OK
, out
.rv
);
1368 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1369 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1370 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1371 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1372 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1373 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1375 out
.rv
= callback2
.WaitForResult();
1376 ASSERT_EQ(OK
, out
.rv
);
1377 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1379 out
.rv
= callback3
.WaitForResult();
1380 ASSERT_EQ(OK
, out
.rv
);
1382 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1383 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1384 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1385 out
.status_line
= response1
->headers
->GetStatusLine();
1386 out
.response_info
= *response1
;
1387 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1388 EXPECT_EQ(OK
, out
.rv
);
1389 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1390 EXPECT_EQ("hello!hello!", out
.response_data
);
1392 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1393 out
.status_line
= response2
->headers
->GetStatusLine();
1394 out
.response_info
= *response2
;
1395 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1396 EXPECT_EQ(OK
, out
.rv
);
1397 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1398 EXPECT_EQ("hello!hello!", out
.response_data
);
1400 // notice: response3 gets two hellos, response4 gets one
1401 // hello, so we know dequeuing priority was respected.
1402 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1403 out
.status_line
= response3
->headers
->GetStatusLine();
1404 out
.response_info
= *response3
;
1405 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1406 EXPECT_EQ(OK
, out
.rv
);
1407 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1408 EXPECT_EQ("hello!hello!", out
.response_data
);
1410 out
.rv
= callback4
.WaitForResult();
1411 EXPECT_EQ(OK
, out
.rv
);
1412 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1413 out
.status_line
= response4
->headers
->GetStatusLine();
1414 out
.response_info
= *response4
;
1415 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1416 EXPECT_EQ(OK
, out
.rv
);
1417 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1418 EXPECT_EQ("hello!", out
.response_data
);
1419 helper
.VerifyDataConsumed();
1420 EXPECT_EQ(OK
, out
.rv
);
1423 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1424 // deletes a session in the middle of the transaction to insure
1425 // that we properly remove pendingcreatestream objects from
1427 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1428 // Construct the request.
1429 scoped_ptr
<SpdyFrame
> req(
1430 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1431 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1432 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1433 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1435 scoped_ptr
<SpdyFrame
> req2(
1436 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1437 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1438 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1439 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1441 SettingsMap settings
;
1442 const uint32 max_concurrent_streams
= 1;
1443 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1444 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1445 scoped_ptr
<SpdyFrame
> settings_frame(
1446 spdy_util_
.ConstructSpdySettings(settings
));
1447 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1449 MockWrite writes
[] = {
1450 CreateMockWrite(*req
),
1451 CreateMockWrite(*settings_ack
, 2),
1452 CreateMockWrite(*req2
),
1454 MockRead reads
[] = {
1455 CreateMockRead(*settings_frame
, 1),
1456 CreateMockRead(*resp
),
1457 CreateMockRead(*body
),
1458 CreateMockRead(*fbody
),
1459 CreateMockRead(*resp2
, 8),
1460 CreateMockRead(*body2
),
1461 CreateMockRead(*fbody2
),
1462 MockRead(ASYNC
, 0, 0), // EOF
1465 OrderedSocketData
data(reads
, arraysize(reads
),
1466 writes
, arraysize(writes
));
1467 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1470 TransactionHelperResult out
;
1471 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1472 BoundNetLog(), GetParam(), NULL
);
1473 helper
.RunPreTestSetup();
1474 helper
.AddData(&data
);
1475 // We require placeholder data because three get requests are sent out, so
1476 // there needs to be three sets of SSL connection data.
1477 helper
.AddData(&data_placeholder
);
1478 helper
.AddData(&data_placeholder
);
1479 scoped_ptr
<HttpNetworkTransaction
> trans1(
1480 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1481 scoped_ptr
<HttpNetworkTransaction
> trans2(
1482 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1483 scoped_ptr
<HttpNetworkTransaction
> trans3(
1484 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1486 TestCompletionCallback callback1
;
1487 TestCompletionCallback callback2
;
1488 TestCompletionCallback callback3
;
1490 HttpRequestInfo httpreq1
= CreateGetRequest();
1491 HttpRequestInfo httpreq2
= CreateGetRequest();
1492 HttpRequestInfo httpreq3
= CreateGetRequest();
1494 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1495 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1496 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1497 out
.rv
= callback1
.WaitForResult();
1498 ASSERT_EQ(OK
, out
.rv
);
1500 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1501 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1502 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1503 delete trans3
.release();
1504 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1505 out
.rv
= callback2
.WaitForResult();
1506 ASSERT_EQ(OK
, out
.rv
);
1508 EXPECT_EQ(8U, data
.read_index());
1510 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1511 ASSERT_TRUE(response1
!= NULL
);
1512 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1513 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1514 out
.status_line
= response1
->headers
->GetStatusLine();
1515 out
.response_info
= *response1
;
1516 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1517 EXPECT_EQ(OK
, out
.rv
);
1518 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1519 EXPECT_EQ("hello!hello!", out
.response_data
);
1521 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1522 ASSERT_TRUE(response2
!= NULL
);
1523 out
.status_line
= response2
->headers
->GetStatusLine();
1524 out
.response_info
= *response2
;
1525 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1526 EXPECT_EQ(OK
, out
.rv
);
1527 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1528 EXPECT_EQ("hello!hello!", out
.response_data
);
1529 helper
.VerifyDataConsumed();
1530 EXPECT_EQ(OK
, out
.rv
);
1535 // The KillerCallback will delete the transaction on error as part of the
1537 class KillerCallback
: public TestCompletionCallbackBase
{
1539 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1540 : transaction_(transaction
),
1541 callback_(base::Bind(&KillerCallback::OnComplete
,
1542 base::Unretained(this))) {
1545 ~KillerCallback() override
{}
1547 const CompletionCallback
& callback() const { return callback_
; }
1550 void OnComplete(int result
) {
1552 delete transaction_
;
1557 HttpNetworkTransaction
* transaction_
;
1558 CompletionCallback callback_
;
1563 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1564 // closes the socket while we have a pending transaction waiting for
1565 // a pending stream creation. http://crbug.com/52901
1566 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1567 // Construct the request.
1568 scoped_ptr
<SpdyFrame
> req(
1569 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1570 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1571 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1572 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1574 scoped_ptr
<SpdyFrame
> req2(
1575 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1576 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1578 SettingsMap settings
;
1579 const uint32 max_concurrent_streams
= 1;
1580 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1581 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1582 scoped_ptr
<SpdyFrame
> settings_frame(
1583 spdy_util_
.ConstructSpdySettings(settings
));
1584 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1586 MockWrite writes
[] = {
1587 CreateMockWrite(*req
),
1588 CreateMockWrite(*settings_ack
, 2),
1589 CreateMockWrite(*req2
),
1591 MockRead reads
[] = {
1592 CreateMockRead(*settings_frame
, 1),
1593 CreateMockRead(*resp
),
1594 CreateMockRead(*body
),
1595 CreateMockRead(*fin_body
),
1596 CreateMockRead(*resp2
, 8),
1597 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1600 OrderedSocketData
data(reads
, arraysize(reads
),
1601 writes
, arraysize(writes
));
1602 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1605 TransactionHelperResult out
;
1606 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1607 BoundNetLog(), GetParam(), NULL
);
1608 helper
.RunPreTestSetup();
1609 helper
.AddData(&data
);
1610 // We require placeholder data because three get requests are sent out, so
1611 // there needs to be three sets of SSL connection data.
1612 helper
.AddData(&data_placeholder
);
1613 helper
.AddData(&data_placeholder
);
1614 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1615 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1616 HttpNetworkTransaction
* trans3(
1617 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1619 TestCompletionCallback callback1
;
1620 TestCompletionCallback callback2
;
1621 KillerCallback
callback3(trans3
);
1623 HttpRequestInfo httpreq1
= CreateGetRequest();
1624 HttpRequestInfo httpreq2
= CreateGetRequest();
1625 HttpRequestInfo httpreq3
= CreateGetRequest();
1627 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1628 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1629 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1630 out
.rv
= callback1
.WaitForResult();
1631 ASSERT_EQ(OK
, out
.rv
);
1633 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1634 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1635 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1636 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1637 out
.rv
= callback3
.WaitForResult();
1638 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1640 EXPECT_EQ(6U, data
.read_index());
1642 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1643 ASSERT_TRUE(response1
!= NULL
);
1644 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1645 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1646 out
.status_line
= response1
->headers
->GetStatusLine();
1647 out
.response_info
= *response1
;
1648 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1649 EXPECT_EQ(OK
, out
.rv
);
1651 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1652 ASSERT_TRUE(response2
!= NULL
);
1653 out
.status_line
= response2
->headers
->GetStatusLine();
1654 out
.response_info
= *response2
;
1655 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1656 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1658 helper
.VerifyDataConsumed();
1661 // Test that a simple PUT request works.
1662 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1663 // Setup the request
1664 HttpRequestInfo request
;
1665 request
.method
= "PUT";
1666 request
.url
= GURL("http://www.google.com/");
1668 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1669 spdy_util_
.ConstructPutHeaderBlock("http://www.google.com", 0));
1670 scoped_ptr
<SpdyFrame
> req(
1671 spdy_util_
.ConstructSpdySyn(1, *put_headers
, LOWEST
, false, true));
1672 MockWrite writes
[] = {
1673 CreateMockWrite(*req
),
1676 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1677 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1678 MockRead reads
[] = {
1679 CreateMockRead(*resp
),
1680 CreateMockRead(*body
),
1681 MockRead(ASYNC
, 0, 0) // EOF
1684 DelayedSocketData
data(1, reads
, arraysize(reads
),
1685 writes
, arraysize(writes
));
1686 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1687 BoundNetLog(), GetParam(), NULL
);
1688 helper
.RunToCompletion(&data
);
1689 TransactionHelperResult out
= helper
.output();
1691 EXPECT_EQ(OK
, out
.rv
);
1692 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1695 // Test that a simple HEAD request works.
1696 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1697 // Setup the request
1698 HttpRequestInfo request
;
1699 request
.method
= "HEAD";
1700 request
.url
= GURL("http://www.google.com/");
1702 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1703 spdy_util_
.ConstructHeadHeaderBlock("http://www.google.com", 0));
1704 scoped_ptr
<SpdyFrame
> req(
1705 spdy_util_
.ConstructSpdySyn(1, *head_headers
, LOWEST
, false, true));
1706 MockWrite writes
[] = {
1707 CreateMockWrite(*req
),
1710 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1711 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1712 MockRead reads
[] = {
1713 CreateMockRead(*resp
),
1714 CreateMockRead(*body
),
1715 MockRead(ASYNC
, 0, 0) // EOF
1718 DelayedSocketData
data(1, reads
, arraysize(reads
),
1719 writes
, arraysize(writes
));
1720 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1721 BoundNetLog(), GetParam(), NULL
);
1722 helper
.RunToCompletion(&data
);
1723 TransactionHelperResult out
= helper
.output();
1725 EXPECT_EQ(OK
, out
.rv
);
1726 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1729 // Test that a simple POST works.
1730 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1731 scoped_ptr
<SpdyFrame
> req(
1732 spdy_util_
.ConstructSpdyPost(
1733 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1734 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1735 MockWrite writes
[] = {
1736 CreateMockWrite(*req
),
1737 CreateMockWrite(*body
), // POST upload frame
1740 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1741 MockRead reads
[] = {
1742 CreateMockRead(*resp
),
1743 CreateMockRead(*body
),
1744 MockRead(ASYNC
, 0, 0) // EOF
1747 DelayedSocketData
data(2, reads
, arraysize(reads
),
1748 writes
, arraysize(writes
));
1749 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
1750 BoundNetLog(), GetParam(), NULL
);
1751 helper
.RunToCompletion(&data
);
1752 TransactionHelperResult out
= helper
.output();
1753 EXPECT_EQ(OK
, out
.rv
);
1754 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1755 EXPECT_EQ("hello!", out
.response_data
);
1758 // Test that a POST with a file works.
1759 TEST_P(SpdyNetworkTransactionTest
, FilePost
) {
1760 scoped_ptr
<SpdyFrame
> req(
1761 spdy_util_
.ConstructSpdyPost(
1762 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1763 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1764 MockWrite writes
[] = {
1765 CreateMockWrite(*req
),
1766 CreateMockWrite(*body
), // POST upload frame
1769 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1770 MockRead reads
[] = {
1771 CreateMockRead(*resp
),
1772 CreateMockRead(*body
),
1773 MockRead(ASYNC
, 0, 0) // EOF
1776 DelayedSocketData
data(2, reads
, arraysize(reads
),
1777 writes
, arraysize(writes
));
1778 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(), DEFAULT_PRIORITY
,
1779 BoundNetLog(), GetParam(), NULL
);
1780 helper
.RunToCompletion(&data
);
1781 TransactionHelperResult out
= helper
.output();
1782 EXPECT_EQ(OK
, out
.rv
);
1783 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1784 EXPECT_EQ("hello!", out
.response_data
);
1787 // Test that a POST with a unreadable file fails.
1788 TEST_P(SpdyNetworkTransactionTest
, UnreadableFilePost
) {
1789 MockWrite writes
[] = {
1790 MockWrite(ASYNC
, 0, 0) // EOF
1792 MockRead reads
[] = {
1793 MockRead(ASYNC
, 0, 0) // EOF
1796 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1797 NormalSpdyTransactionHelper
helper(CreateUnreadableFilePostRequest(),
1799 BoundNetLog(), GetParam(), NULL
);
1800 helper
.RunPreTestSetup();
1801 helper
.AddData(&data
);
1802 helper
.RunDefaultTest();
1804 base::RunLoop().RunUntilIdle();
1805 helper
.VerifyDataNotConsumed();
1806 EXPECT_EQ(ERR_ACCESS_DENIED
, helper
.output().rv
);
1809 // Test that a complex POST works.
1810 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1811 scoped_ptr
<SpdyFrame
> req(
1812 spdy_util_
.ConstructSpdyPost(
1813 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1814 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1815 MockWrite writes
[] = {
1816 CreateMockWrite(*req
),
1817 CreateMockWrite(*body
), // POST upload frame
1820 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1821 MockRead reads
[] = {
1822 CreateMockRead(*resp
),
1823 CreateMockRead(*body
),
1824 MockRead(ASYNC
, 0, 0) // EOF
1827 DelayedSocketData
data(2, reads
, arraysize(reads
),
1828 writes
, arraysize(writes
));
1829 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1831 BoundNetLog(), GetParam(), NULL
);
1832 helper
.RunToCompletion(&data
);
1833 TransactionHelperResult out
= helper
.output();
1834 EXPECT_EQ(OK
, out
.rv
);
1835 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1836 EXPECT_EQ("hello!", out
.response_data
);
1839 // Test that a chunked POST works.
1840 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1841 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1842 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1843 MockWrite writes
[] = {
1844 CreateMockWrite(*req
),
1845 CreateMockWrite(*body
),
1848 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1849 MockRead reads
[] = {
1850 CreateMockRead(*resp
),
1851 CreateMockRead(*body
),
1852 MockRead(ASYNC
, 0, 0) // EOF
1855 DelayedSocketData
data(2, reads
, arraysize(reads
),
1856 writes
, arraysize(writes
));
1857 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1859 BoundNetLog(), GetParam(), NULL
);
1861 // These chunks get merged into a single frame when being sent.
1862 const int kFirstChunkSize
= kUploadDataSize
/2;
1863 upload_chunked_data_stream()->AppendData(kUploadData
, kFirstChunkSize
, false);
1864 upload_chunked_data_stream()->AppendData(
1865 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1867 helper
.RunToCompletion(&data
);
1868 TransactionHelperResult out
= helper
.output();
1869 EXPECT_EQ(OK
, out
.rv
);
1870 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1871 EXPECT_EQ(kUploadData
, out
.response_data
);
1874 // Test that a chunked POST works with chunks appended after transaction starts.
1875 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1876 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1877 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1878 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1879 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1880 MockWrite writes
[] = {
1881 CreateMockWrite(*req
),
1882 CreateMockWrite(*chunk1
),
1883 CreateMockWrite(*chunk2
),
1884 CreateMockWrite(*chunk3
),
1887 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1888 MockRead reads
[] = {
1889 CreateMockRead(*resp
),
1890 CreateMockRead(*chunk1
),
1891 CreateMockRead(*chunk2
),
1892 CreateMockRead(*chunk3
),
1893 MockRead(ASYNC
, 0, 0) // EOF
1896 DelayedSocketData
data(4, reads
, arraysize(reads
),
1897 writes
, arraysize(writes
));
1898 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1900 BoundNetLog(), GetParam(), NULL
);
1902 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1904 helper
.RunPreTestSetup();
1905 helper
.AddData(&data
);
1906 ASSERT_TRUE(helper
.StartDefaultTest());
1908 base::RunLoop().RunUntilIdle();
1909 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1910 base::RunLoop().RunUntilIdle();
1911 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
1913 helper
.FinishDefaultTest();
1914 helper
.VerifyDataConsumed();
1916 std::string expected_response
;
1917 expected_response
+= kUploadData
;
1918 expected_response
+= kUploadData
;
1919 expected_response
+= kUploadData
;
1921 TransactionHelperResult out
= helper
.output();
1922 EXPECT_EQ(OK
, out
.rv
);
1923 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1924 EXPECT_EQ(expected_response
, out
.response_data
);
1927 // Test that a POST without any post data works.
1928 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1929 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1930 // Setup the request
1931 HttpRequestInfo request
;
1932 request
.method
= "POST";
1933 request
.url
= GURL(kRequestUrl
);
1934 // Create an empty UploadData.
1935 request
.upload_data_stream
= NULL
;
1937 // When request.upload_data_stream is NULL for post, content-length is
1938 // expected to be 0.
1939 scoped_ptr
<SpdyHeaderBlock
> req_block(
1940 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, 0));
1941 scoped_ptr
<SpdyFrame
> req(
1942 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1944 MockWrite writes
[] = {
1945 CreateMockWrite(*req
),
1948 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1949 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1950 MockRead reads
[] = {
1951 CreateMockRead(*resp
),
1952 CreateMockRead(*body
),
1953 MockRead(ASYNC
, 0, 0) // EOF
1956 DelayedSocketData
data(1, reads
, arraysize(reads
),
1957 writes
, arraysize(writes
));
1959 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1960 BoundNetLog(), GetParam(), NULL
);
1961 helper
.RunToCompletion(&data
);
1962 TransactionHelperResult out
= helper
.output();
1963 EXPECT_EQ(OK
, out
.rv
);
1964 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1965 EXPECT_EQ("hello!", out
.response_data
);
1968 // Test that a simple POST works.
1969 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1970 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1971 // Create an empty UploadDataStream.
1972 ScopedVector
<UploadElementReader
> element_readers
;
1973 ElementsUploadDataStream
stream(element_readers
.Pass(), 0);
1975 // Setup the request
1976 HttpRequestInfo request
;
1977 request
.method
= "POST";
1978 request
.url
= GURL(kRequestUrl
);
1979 request
.upload_data_stream
= &stream
;
1981 const uint64 kContentLength
= 0;
1983 scoped_ptr
<SpdyHeaderBlock
> req_block(
1984 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, kContentLength
));
1985 scoped_ptr
<SpdyFrame
> req(
1986 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1988 MockWrite writes
[] = {
1989 CreateMockWrite(*req
),
1992 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1993 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1994 MockRead reads
[] = {
1995 CreateMockRead(*resp
),
1996 CreateMockRead(*body
),
1997 MockRead(ASYNC
, 0, 0) // EOF
2000 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
2002 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
2003 BoundNetLog(), GetParam(), NULL
);
2004 helper
.RunToCompletion(&data
);
2005 TransactionHelperResult out
= helper
.output();
2006 EXPECT_EQ(OK
, out
.rv
);
2007 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2008 EXPECT_EQ("hello!", out
.response_data
);
2011 // While we're doing a post, the server sends the reply before upload completes.
2012 TEST_P(SpdyNetworkTransactionTest
, ResponseBeforePostCompletes
) {
2013 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
2014 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2015 MockWrite writes
[] = {
2016 CreateMockWrite(*req
, 0),
2017 CreateMockWrite(*body
, 3),
2019 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2020 MockRead reads
[] = {
2021 CreateMockRead(*resp
, 1),
2022 CreateMockRead(*body
, 2),
2023 MockRead(ASYNC
, 0, 4) // EOF
2026 // Write the request headers, and read the complete response
2027 // while still waiting for chunked request data.
2028 DeterministicSocketData
data(reads
, arraysize(reads
),
2029 writes
, arraysize(writes
));
2030 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
2032 BoundNetLog(), GetParam(), NULL
);
2033 helper
.SetDeterministic();
2034 helper
.RunPreTestSetup();
2035 helper
.AddDeterministicData(&data
);
2037 ASSERT_TRUE(helper
.StartDefaultTest());
2039 // Process the request headers, SYN_REPLY, and response body.
2040 // The request body is still in flight.
2043 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
2044 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2046 // Finish sending the request body.
2047 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
2050 std::string response_body
;
2051 EXPECT_EQ(OK
, ReadTransaction(helper
.trans(), &response_body
));
2052 EXPECT_EQ(kUploadData
, response_body
);
2053 helper
.VerifyDataConsumed();
2056 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2057 // socket causes the TCP write to return zero. This test checks that the client
2058 // tries to queue up the RST_STREAM frame again.
2059 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2060 scoped_ptr
<SpdyFrame
> req(
2061 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2062 scoped_ptr
<SpdyFrame
> rst(
2063 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2064 MockWrite writes
[] = {
2065 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2066 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2067 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2070 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2071 MockRead reads
[] = {
2072 CreateMockRead(*resp
.get(), 1, ASYNC
),
2073 MockRead(ASYNC
, 0, 0, 4) // EOF
2076 DeterministicSocketData
data(reads
, arraysize(reads
),
2077 writes
, arraysize(writes
));
2078 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2079 BoundNetLog(), GetParam(), NULL
);
2080 helper
.SetDeterministic();
2081 helper
.RunPreTestSetup();
2082 helper
.AddDeterministicData(&data
);
2083 HttpNetworkTransaction
* trans
= helper
.trans();
2085 TestCompletionCallback callback
;
2086 int rv
= trans
->Start(
2087 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2088 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2092 helper
.ResetTrans();
2096 helper
.VerifyDataConsumed();
2099 // Test that the transaction doesn't crash when we don't have a reply.
2100 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2101 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2102 MockRead reads
[] = {
2103 CreateMockRead(*body
),
2104 MockRead(ASYNC
, 0, 0) // EOF
2107 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2108 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2109 BoundNetLog(), GetParam(), NULL
);
2110 helper
.RunToCompletion(&data
);
2111 TransactionHelperResult out
= helper
.output();
2112 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2115 // Test that the transaction doesn't crash when we get two replies on the same
2116 // stream ID. See http://crbug.com/45639.
2117 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2118 scoped_ptr
<SpdyFrame
> req(
2119 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2120 scoped_ptr
<SpdyFrame
> rst(
2121 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2122 MockWrite writes
[] = {
2123 CreateMockWrite(*req
),
2124 CreateMockWrite(*rst
),
2127 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2128 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2129 MockRead reads
[] = {
2130 CreateMockRead(*resp
),
2131 CreateMockRead(*resp
),
2132 CreateMockRead(*body
),
2133 MockRead(ASYNC
, 0, 0) // EOF
2136 DelayedSocketData
data(1, reads
, arraysize(reads
),
2137 writes
, arraysize(writes
));
2139 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2140 BoundNetLog(), GetParam(), NULL
);
2141 helper
.RunPreTestSetup();
2142 helper
.AddData(&data
);
2144 HttpNetworkTransaction
* trans
= helper
.trans();
2146 TestCompletionCallback callback
;
2147 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2148 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2149 rv
= callback
.WaitForResult();
2152 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2153 ASSERT_TRUE(response
!= NULL
);
2154 EXPECT_TRUE(response
->headers
.get() != NULL
);
2155 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2156 std::string response_data
;
2157 rv
= ReadTransaction(trans
, &response_data
);
2158 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2160 helper
.VerifyDataConsumed();
2163 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2164 // Construct the request.
2165 scoped_ptr
<SpdyFrame
> req(
2166 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2167 scoped_ptr
<SpdyFrame
> rst(
2168 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2169 MockWrite writes
[] = {
2170 CreateMockWrite(*req
),
2171 CreateMockWrite(*rst
),
2174 const char* const headers
[] = {
2175 "transfer-encoding", "chunked"
2177 scoped_ptr
<SpdyFrame
> resp(
2178 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2179 scoped_ptr
<SpdyFrame
> body(
2180 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2181 MockRead reads
[] = {
2182 CreateMockRead(*resp
),
2183 CreateMockRead(*body
),
2184 MockRead(ASYNC
, 0, 0) // EOF
2187 DelayedSocketData
data(1, reads
, arraysize(reads
),
2188 writes
, arraysize(writes
));
2189 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2190 BoundNetLog(), GetParam(), NULL
);
2191 helper
.RunToCompletion(&data
);
2192 TransactionHelperResult out
= helper
.output();
2193 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2195 helper
.session()->spdy_session_pool()->CloseAllSessions();
2196 helper
.VerifyDataConsumed();
2199 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2200 // Construct the request.
2201 scoped_ptr
<SpdyFrame
> req(
2202 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2203 scoped_ptr
<SpdyFrame
> rst(
2204 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2205 MockWrite writes
[] = {
2206 CreateMockWrite(*req
),
2207 CreateMockWrite(*rst
),
2210 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2211 const char* const headers
[] = {
2212 "transfer-encoding", "chunked"
2214 scoped_ptr
<SpdyFrame
> push(
2215 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2216 2, 1, "http://www.google.com/1"));
2217 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2218 MockRead reads
[] = {
2219 CreateMockRead(*resp
),
2220 CreateMockRead(*push
),
2221 CreateMockRead(*body
),
2222 MockRead(ASYNC
, 0, 0) // EOF
2225 DelayedSocketData
data(1, reads
, arraysize(reads
),
2226 writes
, arraysize(writes
));
2227 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2228 BoundNetLog(), GetParam(), NULL
);
2229 helper
.RunToCompletion(&data
);
2230 TransactionHelperResult out
= helper
.output();
2231 EXPECT_EQ(OK
, out
.rv
);
2232 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2233 EXPECT_EQ("hello!", out
.response_data
);
2235 helper
.session()->spdy_session_pool()->CloseAllSessions();
2236 helper
.VerifyDataConsumed();
2239 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2240 // Construct the request.
2241 scoped_ptr
<SpdyFrame
> req(
2242 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2243 MockWrite writes
[] = {
2244 CreateMockWrite(*req
),
2247 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2248 MockRead reads
[] = {
2249 CreateMockRead(*resp
),
2250 // This following read isn't used by the test, except during the
2251 // RunUntilIdle() call at the end since the SpdySession survives the
2252 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2253 // MockRead will do here.
2254 MockRead(ASYNC
, 0, 0) // EOF
2257 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2258 writes
, arraysize(writes
));
2260 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2261 BoundNetLog(), GetParam(), NULL
);
2262 helper
.RunPreTestSetup();
2263 helper
.AddData(&data
);
2264 HttpNetworkTransaction
* trans
= helper
.trans();
2266 TestCompletionCallback callback
;
2267 int rv
= trans
->Start(
2268 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2270 helper
.ResetTrans(); // Cancel the transaction.
2272 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2273 // MockClientSocketFactory) are still alive.
2274 base::RunLoop().RunUntilIdle();
2275 helper
.VerifyDataNotConsumed();
2278 // Verify that the client sends a Rst Frame upon cancelling the stream.
2279 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2280 scoped_ptr
<SpdyFrame
> req(
2281 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2282 scoped_ptr
<SpdyFrame
> rst(
2283 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2284 MockWrite writes
[] = {
2285 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2286 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2289 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2290 MockRead reads
[] = {
2291 CreateMockRead(*resp
, 1, ASYNC
),
2292 MockRead(ASYNC
, 0, 0, 3) // EOF
2295 DeterministicSocketData
data(reads
, arraysize(reads
),
2296 writes
, arraysize(writes
));
2298 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2301 helper
.SetDeterministic();
2302 helper
.RunPreTestSetup();
2303 helper
.AddDeterministicData(&data
);
2304 HttpNetworkTransaction
* trans
= helper
.trans();
2306 TestCompletionCallback callback
;
2308 int rv
= trans
->Start(
2309 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2314 helper
.ResetTrans();
2318 helper
.VerifyDataConsumed();
2321 // Verify that the client can correctly deal with the user callback attempting
2322 // to start another transaction on a session that is closing down. See
2323 // http://crbug.com/47455
2324 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2325 scoped_ptr
<SpdyFrame
> req(
2326 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2327 MockWrite writes
[] = { CreateMockWrite(*req
) };
2328 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2330 // The indicated length of this frame is longer than its actual length. When
2331 // the session receives an empty frame after this one, it shuts down the
2332 // session, and calls the read callback with the incomplete data.
2333 const uint8 kGetBodyFrame2
[] = {
2334 0x00, 0x00, 0x00, 0x01,
2335 0x01, 0x00, 0x00, 0x07,
2336 'h', 'e', 'l', 'l', 'o', '!',
2339 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2340 MockRead reads
[] = {
2341 CreateMockRead(*resp
, 2),
2342 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2343 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2344 arraysize(kGetBodyFrame2
), 4),
2345 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2346 MockRead(ASYNC
, 0, 0, 6), // EOF
2348 MockRead reads2
[] = {
2349 CreateMockRead(*resp
, 2),
2350 MockRead(ASYNC
, 0, 0, 3), // EOF
2353 OrderedSocketData
data(reads
, arraysize(reads
),
2354 writes
, arraysize(writes
));
2355 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2356 writes2
, arraysize(writes2
));
2358 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2359 BoundNetLog(), GetParam(), NULL
);
2360 helper
.RunPreTestSetup();
2361 helper
.AddData(&data
);
2362 helper
.AddData(&data2
);
2363 HttpNetworkTransaction
* trans
= helper
.trans();
2365 // Start the transaction with basic parameters.
2366 TestCompletionCallback callback
;
2367 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2369 rv
= callback
.WaitForResult();
2371 const int kSize
= 3000;
2372 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2376 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2378 // This forces an err_IO_pending, which sets the callback.
2379 data
.CompleteRead();
2380 // This finishes the read.
2381 data
.CompleteRead();
2382 helper
.VerifyDataConsumed();
2385 // Verify that the client can correctly deal with the user callback deleting the
2386 // transaction. Failures will usually be valgrind errors. See
2387 // http://crbug.com/46925
2388 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2389 scoped_ptr
<SpdyFrame
> req(
2390 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2391 MockWrite writes
[] = { CreateMockWrite(*req
) };
2393 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2394 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2395 MockRead reads
[] = {
2396 CreateMockRead(*resp
.get(), 2),
2397 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2398 CreateMockRead(*body
.get(), 4),
2399 MockRead(ASYNC
, 0, 0, 5), // EOF
2402 OrderedSocketData
data(reads
, arraysize(reads
),
2403 writes
, arraysize(writes
));
2405 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2406 BoundNetLog(), GetParam(), NULL
);
2407 helper
.RunPreTestSetup();
2408 helper
.AddData(&data
);
2409 HttpNetworkTransaction
* trans
= helper
.trans();
2411 // Start the transaction with basic parameters.
2412 TestCompletionCallback callback
;
2413 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2414 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2415 rv
= callback
.WaitForResult();
2417 // Setup a user callback which will delete the session, and clear out the
2418 // memory holding the stream object. Note that the callback deletes trans.
2419 const int kSize
= 3000;
2420 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2424 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2425 base::Unretained(&helper
)));
2426 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2427 data
.CompleteRead();
2429 // Finish running rest of tasks.
2430 base::RunLoop().RunUntilIdle();
2431 helper
.VerifyDataConsumed();
2434 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2435 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2436 scoped_ptr
<SpdyHeaderBlock
> headers(
2437 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2438 (*headers
)["user-agent"] = "";
2439 (*headers
)["accept-encoding"] = "gzip, deflate";
2440 scoped_ptr
<SpdyHeaderBlock
> headers2(
2441 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2442 (*headers2
)["user-agent"] = "";
2443 (*headers2
)["accept-encoding"] = "gzip, deflate";
2445 // Setup writes/reads to www.google.com
2446 scoped_ptr
<SpdyFrame
> req(
2447 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2448 scoped_ptr
<SpdyFrame
> req2(
2449 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2450 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2451 MockWrite writes
[] = {
2452 CreateMockWrite(*req
, 1),
2454 MockRead reads
[] = {
2455 CreateMockRead(*resp
, 2),
2456 MockRead(ASYNC
, 0, 0, 3) // EOF
2459 // Setup writes/reads to www.foo.com
2460 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2461 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2462 MockWrite writes2
[] = {
2463 CreateMockWrite(*req2
, 1),
2465 MockRead reads2
[] = {
2466 CreateMockRead(*resp2
, 2),
2467 CreateMockRead(*body2
, 3),
2468 MockRead(ASYNC
, 0, 0, 4) // EOF
2470 OrderedSocketData
data(reads
, arraysize(reads
),
2471 writes
, arraysize(writes
));
2472 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2473 writes2
, arraysize(writes2
));
2475 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2478 SpdyURLRequestContext
spdy_url_request_context(
2479 GetParam().protocol
,
2480 false /* force_spdy_over_ssl*/,
2481 true /* force_spdy_always */);
2482 scoped_ptr
<URLRequest
> r(
2483 spdy_url_request_context
.CreateRequest(GURL("http://www.google.com/"),
2487 spdy_url_request_context
.socket_factory().
2488 AddSocketDataProvider(&data
);
2489 spdy_url_request_context
.socket_factory().
2490 AddSocketDataProvider(&data2
);
2492 d
.set_quit_on_redirect(true);
2494 base::RunLoop().Run();
2496 EXPECT_EQ(1, d
.received_redirect_count());
2498 r
->FollowDeferredRedirect();
2499 base::RunLoop().Run();
2500 EXPECT_EQ(1, d
.response_started_count());
2501 EXPECT_FALSE(d
.received_data_before_response());
2502 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
->status().status());
2503 std::string
contents("hello!");
2504 EXPECT_EQ(contents
, d
.data_received());
2506 EXPECT_TRUE(data
.at_read_eof());
2507 EXPECT_TRUE(data
.at_write_eof());
2508 EXPECT_TRUE(data2
.at_read_eof());
2509 EXPECT_TRUE(data2
.at_write_eof());
2512 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2514 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2515 scoped_ptr
<SpdyHeaderBlock
> headers(
2516 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2517 (*headers
)["user-agent"] = "";
2518 (*headers
)["accept-encoding"] = "gzip, deflate";
2520 // Setup writes/reads to www.google.com
2521 scoped_ptr
<SpdyFrame
> req(
2522 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2523 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2524 scoped_ptr
<SpdyFrame
> rep(
2525 spdy_util_
.ConstructSpdyPush(NULL
,
2529 "http://www.google.com/foo.dat",
2530 "301 Moved Permanently",
2531 "http://www.foo.com/index.php"));
2532 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2533 scoped_ptr
<SpdyFrame
> rst(
2534 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
2535 MockWrite writes
[] = {
2536 CreateMockWrite(*req
, 1),
2537 CreateMockWrite(*rst
, 6),
2539 MockRead reads
[] = {
2540 CreateMockRead(*resp
, 2),
2541 CreateMockRead(*rep
, 3),
2542 CreateMockRead(*body
, 4),
2543 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2544 MockRead(ASYNC
, 0, 0, 7) // EOF
2547 // Setup writes/reads to www.foo.com
2548 scoped_ptr
<SpdyHeaderBlock
> headers2(
2549 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2550 (*headers2
)["user-agent"] = "";
2551 (*headers2
)["accept-encoding"] = "gzip, deflate";
2552 scoped_ptr
<SpdyFrame
> req2(
2553 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2554 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2555 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2556 MockWrite writes2
[] = {
2557 CreateMockWrite(*req2
, 1),
2559 MockRead reads2
[] = {
2560 CreateMockRead(*resp2
, 2),
2561 CreateMockRead(*body2
, 3),
2562 MockRead(ASYNC
, 0, 0, 5) // EOF
2564 OrderedSocketData
data(reads
, arraysize(reads
),
2565 writes
, arraysize(writes
));
2566 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2567 writes2
, arraysize(writes2
));
2569 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2572 SpdyURLRequestContext
spdy_url_request_context(
2573 GetParam().protocol
,
2574 false /* force_spdy_over_ssl*/,
2575 true /* force_spdy_always */);
2577 scoped_ptr
<URLRequest
> r(
2578 spdy_url_request_context
.CreateRequest(GURL("http://www.google.com/"),
2582 spdy_url_request_context
.socket_factory().
2583 AddSocketDataProvider(&data
);
2586 base::RunLoop().Run();
2588 EXPECT_EQ(0, d
.received_redirect_count());
2589 std::string
contents("hello!");
2590 EXPECT_EQ(contents
, d
.data_received());
2592 scoped_ptr
<URLRequest
> r2(
2593 spdy_url_request_context
.CreateRequest(
2594 GURL("http://www.google.com/foo.dat"),
2598 spdy_url_request_context
.socket_factory().
2599 AddSocketDataProvider(&data2
);
2601 d2
.set_quit_on_redirect(true);
2603 base::RunLoop().Run();
2604 EXPECT_EQ(1, d2
.received_redirect_count());
2606 r2
->FollowDeferredRedirect();
2607 base::RunLoop().Run();
2608 EXPECT_EQ(1, d2
.response_started_count());
2609 EXPECT_FALSE(d2
.received_data_before_response());
2610 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
->status().status());
2611 std::string
contents2("hello!");
2612 EXPECT_EQ(contents2
, d2
.data_received());
2614 data
.CompleteRead();
2615 data2
.CompleteRead();
2616 EXPECT_TRUE(data
.at_read_eof());
2617 EXPECT_TRUE(data
.at_write_eof());
2618 EXPECT_TRUE(data2
.at_read_eof());
2619 EXPECT_TRUE(data2
.at_write_eof());
2622 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2623 scoped_ptr
<SpdyFrame
> stream1_syn(
2624 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2625 scoped_ptr
<SpdyFrame
> stream1_body(
2626 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2627 MockWrite writes
[] = {
2628 CreateMockWrite(*stream1_syn
, 1),
2631 scoped_ptr
<SpdyFrame
>
2632 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2633 scoped_ptr
<SpdyFrame
>
2634 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2638 "http://www.google.com/foo.dat"));
2639 const char kPushedData
[] = "pushed";
2640 scoped_ptr
<SpdyFrame
> stream2_body(
2641 spdy_util_
.ConstructSpdyBodyFrame(
2642 2, kPushedData
, strlen(kPushedData
), true));
2643 MockRead reads
[] = {
2644 CreateMockRead(*stream1_reply
, 2),
2645 CreateMockRead(*stream2_syn
, 3),
2646 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2647 CreateMockRead(*stream2_body
, 5),
2648 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2651 HttpResponseInfo response
;
2652 HttpResponseInfo response2
;
2653 std::string
expected_push_result("pushed");
2654 OrderedSocketData
data(reads
, arraysize(reads
),
2655 writes
, arraysize(writes
));
2656 RunServerPushTest(&data
,
2659 expected_push_result
);
2661 // Verify the SYN_REPLY.
2662 EXPECT_TRUE(response
.headers
.get() != NULL
);
2663 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2665 // Verify the pushed stream.
2666 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2667 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2670 TEST_P(SpdyNetworkTransactionTest
, ServerPushBeforeSynReply
) {
2671 scoped_ptr
<SpdyFrame
> stream1_syn(
2672 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2673 scoped_ptr
<SpdyFrame
> stream1_body(
2674 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2675 MockWrite writes
[] = {
2676 CreateMockWrite(*stream1_syn
, 1),
2679 scoped_ptr
<SpdyFrame
>
2680 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2681 scoped_ptr
<SpdyFrame
>
2682 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2686 "http://www.google.com/foo.dat"));
2687 const char kPushedData
[] = "pushed";
2688 scoped_ptr
<SpdyFrame
> stream2_body(
2689 spdy_util_
.ConstructSpdyBodyFrame(
2690 2, kPushedData
, strlen(kPushedData
), true));
2691 MockRead reads
[] = {
2692 CreateMockRead(*stream2_syn
, 2),
2693 CreateMockRead(*stream1_reply
, 3),
2694 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2695 CreateMockRead(*stream2_body
, 5),
2696 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2699 HttpResponseInfo response
;
2700 HttpResponseInfo response2
;
2701 std::string
expected_push_result("pushed");
2702 OrderedSocketData
data(reads
, arraysize(reads
),
2703 writes
, arraysize(writes
));
2704 RunServerPushTest(&data
,
2707 expected_push_result
);
2709 // Verify the SYN_REPLY.
2710 EXPECT_TRUE(response
.headers
.get() != NULL
);
2711 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2713 // Verify the pushed stream.
2714 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2715 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2718 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2719 scoped_ptr
<SpdyFrame
> stream1_syn(
2720 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2721 MockWrite writes
[] = { CreateMockWrite(*stream1_syn
, 1), };
2723 scoped_ptr
<SpdyFrame
>
2724 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2725 scoped_ptr
<SpdyFrame
>
2726 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2730 "http://www.google.com/foo.dat"));
2731 const char kPushedData
[] = "pushed";
2732 scoped_ptr
<SpdyFrame
> stream2_body(
2733 spdy_util_
.ConstructSpdyBodyFrame(
2734 2, kPushedData
, strlen(kPushedData
), true));
2735 scoped_ptr
<SpdyFrame
>
2736 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2737 MockRead reads
[] = {
2738 CreateMockRead(*stream1_reply
, 2),
2739 CreateMockRead(*stream2_syn
, 3),
2740 CreateMockRead(*stream2_body
, 4),
2741 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2742 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2745 HttpResponseInfo response
;
2746 HttpResponseInfo response2
;
2747 std::string
expected_push_result("pushed");
2748 OrderedSocketData
data(reads
, arraysize(reads
),
2749 writes
, arraysize(writes
));
2750 RunServerPushTest(&data
,
2753 expected_push_result
);
2755 // Verify the SYN_REPLY.
2756 EXPECT_TRUE(response
.headers
.get() != NULL
);
2757 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2759 // Verify the pushed stream.
2760 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2761 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2764 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2765 scoped_ptr
<SpdyFrame
> stream1_syn(
2766 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2767 scoped_ptr
<SpdyFrame
> stream1_body(
2768 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2769 MockWrite writes
[] = {
2770 CreateMockWrite(*stream1_syn
, 1),
2773 scoped_ptr
<SpdyFrame
>
2774 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2775 scoped_ptr
<SpdyFrame
>
2776 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2780 "http://www.google.com/foo.dat"));
2781 scoped_ptr
<SpdyFrame
> stream2_rst(
2782 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2783 MockRead reads
[] = {
2784 CreateMockRead(*stream1_reply
, 2),
2785 CreateMockRead(*stream2_syn
, 3),
2786 CreateMockRead(*stream2_rst
, 4),
2787 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2788 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2791 OrderedSocketData
data(reads
, arraysize(reads
),
2792 writes
, arraysize(writes
));
2793 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2794 BoundNetLog(), GetParam(), NULL
);
2796 helper
.RunPreTestSetup();
2797 helper
.AddData(&data
);
2799 HttpNetworkTransaction
* trans
= helper
.trans();
2801 // Start the transaction with basic parameters.
2802 TestCompletionCallback callback
;
2803 int rv
= trans
->Start(
2804 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2805 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2806 rv
= callback
.WaitForResult();
2809 // Verify that we consumed all test data.
2810 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2811 << data
.read_count()
2813 << data
.read_index();
2814 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2815 << data
.write_count()
2817 << data
.write_index();
2819 // Verify the SYN_REPLY.
2820 HttpResponseInfo response
= *trans
->GetResponseInfo();
2821 EXPECT_TRUE(response
.headers
.get() != NULL
);
2822 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2825 // Verify that we don't leak streams and that we properly send a reset
2826 // if the server pushes the same stream twice.
2827 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2828 scoped_ptr
<SpdyFrame
> stream1_syn(
2829 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2830 scoped_ptr
<SpdyFrame
> stream1_body(
2831 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2832 scoped_ptr
<SpdyFrame
> stream3_rst(
2833 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR
));
2834 MockWrite writes
[] = {
2835 CreateMockWrite(*stream1_syn
, 1),
2836 CreateMockWrite(*stream3_rst
, 5),
2839 scoped_ptr
<SpdyFrame
>
2840 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2841 scoped_ptr
<SpdyFrame
>
2842 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2846 "http://www.google.com/foo.dat"));
2847 const char kPushedData
[] = "pushed";
2848 scoped_ptr
<SpdyFrame
> stream2_body(
2849 spdy_util_
.ConstructSpdyBodyFrame(
2850 2, kPushedData
, strlen(kPushedData
), true));
2851 scoped_ptr
<SpdyFrame
>
2852 stream3_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2856 "http://www.google.com/foo.dat"));
2857 MockRead reads
[] = {
2858 CreateMockRead(*stream1_reply
, 2),
2859 CreateMockRead(*stream2_syn
, 3),
2860 CreateMockRead(*stream3_syn
, 4),
2861 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
2862 CreateMockRead(*stream2_body
, 7),
2863 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
2866 HttpResponseInfo response
;
2867 HttpResponseInfo response2
;
2868 std::string
expected_push_result("pushed");
2869 OrderedSocketData
data(reads
, arraysize(reads
),
2870 writes
, arraysize(writes
));
2871 RunServerPushTest(&data
,
2874 expected_push_result
);
2876 // Verify the SYN_REPLY.
2877 EXPECT_TRUE(response
.headers
.get() != NULL
);
2878 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2880 // Verify the pushed stream.
2881 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2882 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2885 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2886 scoped_ptr
<SpdyFrame
> stream1_syn(
2887 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2888 scoped_ptr
<SpdyFrame
> stream1_body(
2889 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2890 MockWrite writes
[] = {
2891 CreateMockWrite(*stream1_syn
, 1),
2894 scoped_ptr
<SpdyFrame
>
2895 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2896 scoped_ptr
<SpdyFrame
>
2897 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2901 "http://www.google.com/foo.dat"));
2902 static const char kPushedData
[] = "pushed my darling hello my baby";
2903 scoped_ptr
<SpdyFrame
> stream2_body_base(
2904 spdy_util_
.ConstructSpdyBodyFrame(
2905 2, kPushedData
, strlen(kPushedData
), true));
2906 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2907 scoped_ptr
<SpdyFrame
> stream2_body1(
2908 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2909 scoped_ptr
<SpdyFrame
> stream2_body2(
2910 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2911 scoped_ptr
<SpdyFrame
> stream2_body3(
2912 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2913 kChunkSize
, false));
2914 scoped_ptr
<SpdyFrame
> stream2_body4(
2915 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2916 stream2_body_base
->size() - 3 * kChunkSize
, false));
2917 MockRead reads
[] = {
2918 CreateMockRead(*stream1_reply
, 2),
2919 CreateMockRead(*stream2_syn
, 3),
2920 CreateMockRead(*stream2_body1
, 4),
2921 CreateMockRead(*stream2_body2
, 5),
2922 CreateMockRead(*stream2_body3
, 6),
2923 CreateMockRead(*stream2_body4
, 7),
2924 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
2925 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
2928 HttpResponseInfo response
;
2929 HttpResponseInfo response2
;
2930 std::string
expected_push_result("pushed my darling hello my baby");
2931 OrderedSocketData
data(reads
, arraysize(reads
),
2932 writes
, arraysize(writes
));
2933 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2935 // Verify the SYN_REPLY.
2936 EXPECT_TRUE(response
.headers
.get() != NULL
);
2937 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2939 // Verify the pushed stream.
2940 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2941 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2944 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2945 scoped_ptr
<SpdyFrame
> stream1_syn(
2946 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2947 scoped_ptr
<SpdyFrame
> stream1_body(
2948 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2949 MockWrite writes
[] = {
2950 CreateMockWrite(*stream1_syn
, 1),
2953 scoped_ptr
<SpdyFrame
>
2954 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2955 scoped_ptr
<SpdyFrame
>
2956 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2960 "http://www.google.com/foo.dat"));
2961 static const char kPushedData
[] = "pushed my darling hello my baby";
2962 scoped_ptr
<SpdyFrame
> stream2_body_base(
2963 spdy_util_
.ConstructSpdyBodyFrame(
2964 2, kPushedData
, strlen(kPushedData
), true));
2965 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2966 scoped_ptr
<SpdyFrame
> stream2_body1(
2967 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2968 scoped_ptr
<SpdyFrame
> stream2_body2(
2969 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2970 scoped_ptr
<SpdyFrame
> stream2_body3(
2971 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2972 kChunkSize
, false));
2973 scoped_ptr
<SpdyFrame
> stream2_body4(
2974 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2975 stream2_body_base
->size() - 3 * kChunkSize
, false));
2976 MockRead reads
[] = {
2977 CreateMockRead(*stream1_reply
, 2),
2978 CreateMockRead(*stream2_syn
, 3),
2979 CreateMockRead(*stream2_body1
, 4),
2980 CreateMockRead(*stream2_body2
, 5),
2981 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2982 CreateMockRead(*stream2_body3
, 7),
2983 CreateMockRead(*stream2_body4
, 8),
2984 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
2985 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
2988 HttpResponseInfo response
;
2989 HttpResponseInfo response2
;
2990 OrderedSocketData
data(reads
, arraysize(reads
),
2991 writes
, arraysize(writes
));
2992 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2994 // Verify the SYN_REPLY.
2995 EXPECT_TRUE(response
.headers
.get() != NULL
);
2996 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2998 // Verify the pushed stream.
2999 EXPECT_TRUE(response2
.headers
.get() != NULL
);
3000 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3003 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
3004 if (spdy_util_
.spdy_version() == SPDY4
) {
3005 // PUSH_PROMISE with stream id 0 is connection-level error.
3006 // TODO(baranovich): Test session going away.
3010 scoped_ptr
<SpdyFrame
> stream1_syn(
3011 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3012 scoped_ptr
<SpdyFrame
> stream1_body(
3013 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3014 scoped_ptr
<SpdyFrame
> stream2_rst(
3015 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
3016 MockWrite writes
[] = {
3017 CreateMockWrite(*stream1_syn
, 1),
3018 CreateMockWrite(*stream2_rst
, 4),
3021 scoped_ptr
<SpdyFrame
>
3022 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3023 scoped_ptr
<SpdyFrame
>
3024 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3028 "http://www.google.com/foo.dat"));
3029 MockRead reads
[] = {
3030 CreateMockRead(*stream1_reply
, 2),
3031 CreateMockRead(*stream2_syn
, 3),
3032 CreateMockRead(*stream1_body
, 4),
3033 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3036 OrderedSocketData
data(reads
, arraysize(reads
),
3037 writes
, arraysize(writes
));
3038 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3039 BoundNetLog(), GetParam(), NULL
);
3041 helper
.RunPreTestSetup();
3042 helper
.AddData(&data
);
3044 HttpNetworkTransaction
* trans
= helper
.trans();
3046 // Start the transaction with basic parameters.
3047 TestCompletionCallback callback
;
3048 int rv
= trans
->Start(
3049 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3050 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3051 rv
= callback
.WaitForResult();
3054 // Verify that we consumed all test data.
3055 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3056 << data
.read_count()
3058 << data
.read_index();
3059 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3060 << data
.write_count()
3062 << data
.write_index();
3064 // Verify the SYN_REPLY.
3065 HttpResponseInfo response
= *trans
->GetResponseInfo();
3066 EXPECT_TRUE(response
.headers
.get() != NULL
);
3067 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3070 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3071 scoped_ptr
<SpdyFrame
> stream1_syn(
3072 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3073 scoped_ptr
<SpdyFrame
> stream1_body(
3074 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3075 scoped_ptr
<SpdyFrame
> stream2_rst(
3076 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM
));
3077 MockWrite writes
[] = {
3078 CreateMockWrite(*stream1_syn
, 1),
3079 CreateMockWrite(*stream2_rst
, 4),
3082 scoped_ptr
<SpdyFrame
>
3083 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3084 scoped_ptr
<SpdyFrame
>
3085 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3089 "http://www.google.com/foo.dat"));
3090 MockRead reads
[] = {
3091 CreateMockRead(*stream1_reply
, 2),
3092 CreateMockRead(*stream2_syn
, 3),
3093 CreateMockRead(*stream1_body
, 4),
3094 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3097 OrderedSocketData
data(reads
, arraysize(reads
),
3098 writes
, arraysize(writes
));
3099 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3100 BoundNetLog(), GetParam(), NULL
);
3102 helper
.RunPreTestSetup();
3103 helper
.AddData(&data
);
3105 HttpNetworkTransaction
* trans
= helper
.trans();
3107 // Start the transaction with basic parameters.
3108 TestCompletionCallback callback
;
3109 int rv
= trans
->Start(
3110 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3111 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3112 rv
= callback
.WaitForResult();
3115 // Verify that we consumed all test data.
3116 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3117 << data
.read_count()
3119 << data
.read_index();
3120 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3121 << data
.write_count()
3123 << data
.write_index();
3125 // Verify the SYN_REPLY.
3126 HttpResponseInfo response
= *trans
->GetResponseInfo();
3127 EXPECT_TRUE(response
.headers
.get() != NULL
);
3128 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3131 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3132 scoped_ptr
<SpdyFrame
> stream1_syn(
3133 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3134 scoped_ptr
<SpdyFrame
> stream1_body(
3135 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3136 scoped_ptr
<SpdyFrame
> stream2_rst(
3137 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
3138 MockWrite writes
[] = {
3139 CreateMockWrite(*stream1_syn
, 1),
3140 CreateMockWrite(*stream2_rst
, 4),
3143 scoped_ptr
<SpdyFrame
>
3144 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3145 scoped_ptr
<SpdyHeaderBlock
> incomplete_headers(new SpdyHeaderBlock());
3146 (*incomplete_headers
)["hello"] = "bye";
3147 (*incomplete_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
3148 (*incomplete_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
3149 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructInitialSpdyPushFrame(
3150 incomplete_headers
.Pass(), 2, 1));
3151 MockRead reads
[] = {
3152 CreateMockRead(*stream1_reply
, 2),
3153 CreateMockRead(*stream2_syn
, 3),
3154 CreateMockRead(*stream1_body
, 4),
3155 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3158 OrderedSocketData
data(reads
, arraysize(reads
),
3159 writes
, arraysize(writes
));
3160 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3161 BoundNetLog(), GetParam(), NULL
);
3163 helper
.RunPreTestSetup();
3164 helper
.AddData(&data
);
3166 HttpNetworkTransaction
* trans
= helper
.trans();
3168 // Start the transaction with basic parameters.
3169 TestCompletionCallback callback
;
3170 int rv
= trans
->Start(
3171 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3172 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3173 rv
= callback
.WaitForResult();
3175 // Verify that we consumed all test data.
3176 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3177 << data
.read_count()
3179 << data
.read_index();
3180 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3181 << data
.write_count()
3183 << data
.write_index();
3185 // Verify the SYN_REPLY.
3186 HttpResponseInfo response
= *trans
->GetResponseInfo();
3187 EXPECT_TRUE(response
.headers
.get() != NULL
);
3188 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3191 // Verify that various SynReply headers parse correctly through the
3193 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3194 struct SynReplyHeadersTests
{
3196 const char* extra_headers
[5];
3197 SpdyHeaderBlock expected_headers
;
3199 // This uses a multi-valued cookie header.
3202 "cookie", "val2", // will get appended separated by NULL
3206 // This is the minimalist set of headers.
3210 // Headers with a comma separated list.
3212 { "cookie", "val1,val2",
3218 test_cases
[0].expected_headers
["cookie"] = "val1";
3219 test_cases
[0].expected_headers
["cookie"] += '\0';
3220 test_cases
[0].expected_headers
["cookie"] += "val2";
3221 test_cases
[0].expected_headers
["hello"] = "bye";
3222 test_cases
[0].expected_headers
["status"] = "200";
3224 test_cases
[1].expected_headers
["hello"] = "bye";
3225 test_cases
[1].expected_headers
["status"] = "200";
3227 test_cases
[2].expected_headers
["cookie"] = "val1,val2";
3228 test_cases
[2].expected_headers
["hello"] = "bye";
3229 test_cases
[2].expected_headers
["status"] = "200";
3231 if (spdy_util_
.spdy_version() < SPDY4
) {
3232 // SPDY4/HTTP2 eliminates use of the :version header.
3233 test_cases
[0].expected_headers
["version"] = "HTTP/1.1";
3234 test_cases
[1].expected_headers
["version"] = "HTTP/1.1";
3235 test_cases
[2].expected_headers
["version"] = "HTTP/1.1";
3238 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3239 scoped_ptr
<SpdyFrame
> req(
3240 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3241 MockWrite writes
[] = { CreateMockWrite(*req
) };
3243 scoped_ptr
<SpdyFrame
> resp(
3244 spdy_util_
.ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3245 test_cases
[i
].num_headers
,
3247 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3248 MockRead reads
[] = {
3249 CreateMockRead(*resp
),
3250 CreateMockRead(*body
),
3251 MockRead(ASYNC
, 0, 0) // EOF
3254 DelayedSocketData
data(1, reads
, arraysize(reads
),
3255 writes
, arraysize(writes
));
3256 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3257 BoundNetLog(), GetParam(), NULL
);
3258 helper
.RunToCompletion(&data
);
3259 TransactionHelperResult out
= helper
.output();
3261 EXPECT_EQ(OK
, out
.rv
);
3262 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3263 EXPECT_EQ("hello!", out
.response_data
);
3265 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3266 EXPECT_TRUE(headers
.get() != NULL
);
3268 std::string name
, value
;
3269 SpdyHeaderBlock header_block
;
3270 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3271 if (header_block
[name
].empty()) {
3272 header_block
[name
] = value
;
3274 header_block
[name
] += '\0';
3275 header_block
[name
] += value
;
3278 EXPECT_EQ(test_cases
[i
].expected_headers
, header_block
);
3282 // Verify that various SynReply headers parse vary fields correctly
3283 // through the HTTP layer, and the response matches the request.
3284 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3285 // Modify the following data to change/add test cases:
3286 struct SynReplyTests
{
3289 const char* extra_headers
[2][16];
3291 // Test the case of a multi-valued cookie. When the value is delimited
3292 // with NUL characters, it needs to be unfolded into multiple headers.
3296 { { "cookie", "val1,val2",
3300 spdy_util_
.GetStatusKey(), "200",
3301 spdy_util_
.GetPathKey(), "/index.php",
3302 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3306 }, { // Multiple vary fields.
3309 { { "friend", "barney",
3310 "enemy", "snaggletooth",
3315 spdy_util_
.GetStatusKey(), "200",
3316 spdy_util_
.GetPathKey(), "/index.php",
3317 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3321 }, { // Test a '*' vary field.
3324 { { "cookie", "val1,val2",
3328 spdy_util_
.GetStatusKey(), "200",
3329 spdy_util_
.GetPathKey(), "/index.php",
3330 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3334 }, { // Multiple comma-separated vary fields.
3337 { { "friend", "barney",
3338 "enemy", "snaggletooth",
3341 { "vary", "friend,enemy",
3342 spdy_util_
.GetStatusKey(), "200",
3343 spdy_util_
.GetPathKey(), "/index.php",
3344 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3351 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3352 // Construct the request.
3353 scoped_ptr
<SpdyFrame
> frame_req(
3354 spdy_util_
.ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3355 test_cases
[i
].num_headers
[0],
3356 false, 1, LOWEST
, true));
3358 MockWrite writes
[] = {
3359 CreateMockWrite(*frame_req
),
3362 // Construct the reply.
3363 SpdyHeaderBlock reply_headers
;
3364 AppendToHeaderBlock(test_cases
[i
].extra_headers
[1],
3365 test_cases
[i
].num_headers
[1],
3367 scoped_ptr
<SpdyFrame
> frame_reply(
3368 spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3370 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3371 MockRead reads
[] = {
3372 CreateMockRead(*frame_reply
),
3373 CreateMockRead(*body
),
3374 MockRead(ASYNC
, 0, 0) // EOF
3377 // Attach the headers to the request.
3378 int header_count
= test_cases
[i
].num_headers
[0];
3380 HttpRequestInfo request
= CreateGetRequest();
3381 for (int ct
= 0; ct
< header_count
; ct
++) {
3382 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3383 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3384 request
.extra_headers
.SetHeader(header_key
, header_value
);
3387 DelayedSocketData
data(1, reads
, arraysize(reads
),
3388 writes
, arraysize(writes
));
3389 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
3390 BoundNetLog(), GetParam(), NULL
);
3391 helper
.RunToCompletion(&data
);
3392 TransactionHelperResult out
= helper
.output();
3394 EXPECT_EQ(OK
, out
.rv
) << i
;
3395 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3396 EXPECT_EQ("hello!", out
.response_data
) << i
;
3398 // Test the response information.
3399 EXPECT_TRUE(out
.response_info
.response_time
>
3400 out
.response_info
.request_time
) << i
;
3401 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3402 out
.response_info
.request_time
;
3403 base::TimeDelta min_expected_delay
;
3404 min_expected_delay
.FromMilliseconds(10);
3405 EXPECT_GT(test_delay
.InMillisecondsF(),
3406 min_expected_delay
.InMillisecondsF()) << i
;
3407 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3408 test_cases
[i
].vary_matches
) << i
;
3410 // Check the headers.
3411 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3412 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3414 std::string name
, value
, lines
;
3415 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3418 lines
.append(value
);
3422 // Construct the expected header reply string.
3423 std::string expected_reply
=
3424 spdy_util_
.ConstructSpdyReplyString(reply_headers
);
3425 EXPECT_EQ(expected_reply
, lines
) << i
;
3429 // Verify that we don't crash on invalid SynReply responses.
3430 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3431 struct InvalidSynReplyTests
{
3433 const char* headers
[10];
3435 // SYN_REPLY missing status header
3439 spdy_util_
.GetPathKey(), "/index.php",
3440 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3444 // SYN_REPLY missing version header
3447 spdy_util_
.GetPathKey(), "/index.php",
3451 // SYN_REPLY with no headers
3455 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3456 scoped_ptr
<SpdyFrame
> req(
3457 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3458 scoped_ptr
<SpdyFrame
> rst(
3459 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3460 MockWrite writes
[] = {
3461 CreateMockWrite(*req
),
3462 CreateMockWrite(*rst
),
3465 // Construct the reply.
3466 SpdyHeaderBlock reply_headers
;
3467 AppendToHeaderBlock(
3468 test_cases
[i
].headers
, test_cases
[i
].num_headers
, &reply_headers
);
3469 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3470 MockRead reads
[] = {
3471 CreateMockRead(*resp
),
3472 MockRead(ASYNC
, 0, 0) // EOF
3475 DelayedSocketData
data(1, reads
, arraysize(reads
),
3476 writes
, arraysize(writes
));
3477 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3478 BoundNetLog(), GetParam(), NULL
);
3479 helper
.RunToCompletion(&data
);
3480 TransactionHelperResult out
= helper
.output();
3481 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3485 // Verify that we don't crash on some corrupt frames.
3486 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3487 // connection error. I'd like to backport this behavior to SPDY3 as well.
3488 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3489 if (spdy_util_
.spdy_version() >= SPDY4
) {
3492 // This is the length field that's too short.
3493 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3494 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3495 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3497 (spdy_util_
.spdy_version() < SPDY4
) ?
3498 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize() :
3499 syn_reply_wrong_length
->size();
3500 size_t wrong_size
= right_size
- 4;
3501 test::SetFrameLength(syn_reply_wrong_length
.get(),
3503 spdy_util_
.spdy_version());
3505 struct SynReplyTests
{
3506 const SpdyFrame
* syn_reply
;
3508 { syn_reply_wrong_length
.get(), },
3511 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3512 scoped_ptr
<SpdyFrame
> req(
3513 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3514 scoped_ptr
<SpdyFrame
> rst(
3515 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3516 MockWrite writes
[] = {
3517 CreateMockWrite(*req
),
3518 CreateMockWrite(*rst
),
3521 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3522 MockRead reads
[] = {
3523 MockRead(ASYNC
, test_cases
[i
].syn_reply
->data(), wrong_size
),
3524 CreateMockRead(*body
),
3525 MockRead(ASYNC
, 0, 0) // EOF
3528 DelayedSocketData
data(1, reads
, arraysize(reads
),
3529 writes
, arraysize(writes
));
3530 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3531 BoundNetLog(), GetParam(), NULL
);
3532 helper
.RunToCompletion(&data
);
3533 TransactionHelperResult out
= helper
.output();
3534 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3538 // SPDY4 treats a header decompression failure as a connection-level error.
3539 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionErrorSpdy4
) {
3540 if (spdy_util_
.spdy_version() < SPDY4
) {
3543 // This is the length field that's too short.
3544 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3545 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3546 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3548 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize();
3549 size_t wrong_size
= right_size
- 4;
3550 test::SetFrameLength(syn_reply_wrong_length
.get(),
3552 spdy_util_
.spdy_version());
3554 scoped_ptr
<SpdyFrame
> req(
3555 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3556 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3557 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3558 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3560 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3561 MockRead reads
[] = {
3562 MockRead(ASYNC
, syn_reply_wrong_length
->data(),
3563 syn_reply_wrong_length
->size() - 4),
3566 DelayedSocketData
data(1, reads
, arraysize(reads
),
3567 writes
, arraysize(writes
));
3568 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3569 BoundNetLog(), GetParam(), NULL
);
3570 helper
.RunToCompletion(&data
);
3571 TransactionHelperResult out
= helper
.output();
3572 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3575 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnDecompressionFailure
) {
3576 if (GetParam().protocol
< kProtoSPDY4MinimumVersion
) {
3577 // Decompression failures are a stream error in SPDY3 and above.
3580 scoped_ptr
<SpdyFrame
> req(
3581 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3582 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3583 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3584 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3586 // Read HEADERS with corrupted payload.
3587 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3588 memset(resp
->data() + 12, 0xff, resp
->size() - 12);
3589 MockRead reads
[] = {CreateMockRead(*resp
)};
3591 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3592 NormalSpdyTransactionHelper
helper(
3593 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3594 helper
.RunToCompletion(&data
);
3595 TransactionHelperResult out
= helper
.output();
3596 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3599 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnFrameSizeError
) {
3600 scoped_ptr
<SpdyFrame
> req(
3601 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3602 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3603 0, GOAWAY_PROTOCOL_ERROR
, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3604 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3606 // Read WINDOW_UPDATE with incorrectly-sized payload.
3607 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3608 // which is mapped to a protocol error, and not a frame size error.
3609 scoped_ptr
<SpdyFrame
> bad_window_update(
3610 spdy_util_
.ConstructSpdyWindowUpdate(1, 1));
3611 test::SetFrameLength(bad_window_update
.get(),
3612 bad_window_update
->size() - 1,
3613 spdy_util_
.spdy_version());
3614 MockRead reads
[] = {CreateMockRead(*bad_window_update
)};
3616 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3617 NormalSpdyTransactionHelper
helper(
3618 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3619 helper
.RunToCompletion(&data
);
3620 TransactionHelperResult out
= helper
.output();
3621 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3624 // Test that we shutdown correctly on write errors.
3625 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3626 scoped_ptr
<SpdyFrame
> req(
3627 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3628 MockWrite writes
[] = {
3629 // We'll write 10 bytes successfully
3630 MockWrite(ASYNC
, req
->data(), 10, 0),
3631 // Followed by ERROR!
3632 MockWrite(ASYNC
, ERR_FAILED
, 1),
3633 // Session drains and attempts to write a GOAWAY: Another ERROR!
3634 MockWrite(ASYNC
, ERR_FAILED
, 2),
3637 MockRead reads
[] = {
3638 MockRead(ASYNC
, 0, 3) // EOF
3641 DeterministicSocketData
data(reads
, arraysize(reads
),
3642 writes
, arraysize(writes
));
3644 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3645 BoundNetLog(), GetParam(), NULL
);
3646 helper
.SetDeterministic();
3647 helper
.RunPreTestSetup();
3648 helper
.AddDeterministicData(&data
);
3649 EXPECT_TRUE(helper
.StartDefaultTest());
3651 helper
.FinishDefaultTest();
3652 EXPECT_TRUE(data
.at_write_eof());
3653 EXPECT_TRUE(!data
.at_read_eof());
3654 TransactionHelperResult out
= helper
.output();
3655 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3658 // Test that partial writes work.
3659 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3660 // Chop the SYN_STREAM frame into 5 chunks.
3661 scoped_ptr
<SpdyFrame
> req(
3662 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3663 const int kChunks
= 5;
3664 scoped_ptr
<MockWrite
[]> writes(ChopWriteFrame(*req
.get(), kChunks
));
3666 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3667 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3668 MockRead reads
[] = {
3669 CreateMockRead(*resp
),
3670 CreateMockRead(*body
),
3671 MockRead(ASYNC
, 0, 0) // EOF
3674 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
3675 writes
.get(), kChunks
);
3676 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3677 BoundNetLog(), GetParam(), NULL
);
3678 helper
.RunToCompletion(&data
);
3679 TransactionHelperResult out
= helper
.output();
3680 EXPECT_EQ(OK
, out
.rv
);
3681 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3682 EXPECT_EQ("hello!", out
.response_data
);
3685 // In this test, we enable compression, but get a uncompressed SynReply from
3686 // the server. Verify that teardown is all clean.
3687 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3688 if (spdy_util_
.spdy_version() >= SPDY4
) {
3689 // HPACK doesn't use deflate compression.
3692 scoped_ptr
<SpdyFrame
> compressed(
3693 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
, true));
3694 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3695 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3696 MockWrite writes
[] = {CreateMockWrite(*compressed
), CreateMockWrite(*goaway
)};
3698 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3699 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3700 MockRead reads
[] = {
3701 CreateMockRead(*resp
),
3704 DelayedSocketData
data(1, reads
, arraysize(reads
),
3705 writes
, arraysize(writes
));
3706 SpdySessionDependencies
* session_deps
=
3707 CreateSpdySessionDependencies(GetParam());
3708 session_deps
->enable_compression
= true;
3709 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3710 BoundNetLog(), GetParam(), session_deps
);
3711 helper
.RunToCompletion(&data
);
3712 TransactionHelperResult out
= helper
.output();
3713 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3717 // Test that the NetLog contains good data for a simple GET request.
3718 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3719 static const char* const kExtraHeaders
[] = {
3720 "user-agent", "Chrome",
3722 scoped_ptr
<SpdyFrame
> req(
3723 spdy_util_
.ConstructSpdyGet(kExtraHeaders
, 1, false, 1, LOWEST
, true));
3724 MockWrite writes
[] = { CreateMockWrite(*req
) };
3726 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3727 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3728 MockRead reads
[] = {
3729 CreateMockRead(*resp
),
3730 CreateMockRead(*body
),
3731 MockRead(ASYNC
, 0, 0) // EOF
3734 CapturingBoundNetLog log
;
3736 DelayedSocketData
data(1, reads
, arraysize(reads
),
3737 writes
, arraysize(writes
));
3738 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3740 log
.bound(), GetParam(), NULL
);
3741 helper
.RunToCompletion(&data
);
3742 TransactionHelperResult out
= helper
.output();
3743 EXPECT_EQ(OK
, out
.rv
);
3744 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3745 EXPECT_EQ("hello!", out
.response_data
);
3747 // Check that the NetLog was filled reasonably.
3748 // This test is intentionally non-specific about the exact ordering of the
3749 // log; instead we just check to make sure that certain events exist, and that
3750 // they are in the right order.
3751 net::CapturingNetLog::CapturedEntryList entries
;
3752 log
.GetEntries(&entries
);
3754 EXPECT_LT(0u, entries
.size());
3756 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3757 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3758 net::NetLog::PHASE_BEGIN
);
3759 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3760 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3761 net::NetLog::PHASE_END
);
3762 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3763 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3764 net::NetLog::PHASE_BEGIN
);
3765 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3766 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3767 net::NetLog::PHASE_END
);
3768 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3770 net::NetLog::PHASE_BEGIN
);
3771 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3773 net::NetLog::PHASE_END
);
3775 // Check that we logged all the headers correctly
3776 pos
= net::ExpectLogContainsSomewhere(
3778 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3779 net::NetLog::PHASE_NONE
);
3781 base::ListValue
* header_list
;
3782 ASSERT_TRUE(entries
[pos
].params
.get());
3783 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3785 std::vector
<std::string
> expected
;
3786 expected
.push_back(std::string(spdy_util_
.GetHostKey()) + ": www.google.com");
3787 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3788 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": http");
3789 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3790 expected
.push_back("user-agent: Chrome");
3791 if (spdy_util_
.spdy_version() < SPDY4
) {
3792 // SPDY4/HTTP2 eliminates use of the :version header.
3793 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3795 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3796 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3797 it
!= expected
.end();
3799 base::StringValue
header(*it
);
3800 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3801 "Header not found: " << *it
;
3805 // Since we buffer the IO from the stream to the renderer, this test verifies
3806 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3807 // on the network, but issued a Read for only 5 of those bytes) that the data
3808 // flow still works correctly.
3809 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3810 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3812 scoped_ptr
<SpdyFrame
> req(
3813 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3814 MockWrite writes
[] = { CreateMockWrite(*req
) };
3816 // 2 data frames in a single read.
3817 scoped_ptr
<SpdyFrame
> data_frame_1(
3818 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3819 scoped_ptr
<SpdyFrame
> data_frame_2(
3820 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3821 const SpdyFrame
* data_frames
[2] = {
3825 char combined_data_frames
[100];
3826 int combined_data_frames_len
=
3827 CombineFrames(data_frames
, arraysize(data_frames
),
3828 combined_data_frames
, arraysize(combined_data_frames
));
3829 scoped_ptr
<SpdyFrame
> last_frame(
3830 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3832 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3833 MockRead reads
[] = {
3834 CreateMockRead(*resp
),
3835 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3836 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3837 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3838 CreateMockRead(*last_frame
),
3839 MockRead(ASYNC
, 0, 0) // EOF
3842 DelayedSocketData
data(1, reads
, arraysize(reads
),
3843 writes
, arraysize(writes
));
3845 TestCompletionCallback callback
;
3847 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3848 BoundNetLog(), GetParam(), NULL
);
3849 helper
.RunPreTestSetup();
3850 helper
.AddData(&data
);
3851 HttpNetworkTransaction
* trans
= helper
.trans();
3852 int rv
= trans
->Start(
3853 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3856 TransactionHelperResult out
= helper
.output();
3857 out
.rv
= callback
.WaitForResult();
3858 EXPECT_EQ(out
.rv
, OK
);
3860 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3861 EXPECT_TRUE(response
->headers
.get() != NULL
);
3862 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3863 out
.status_line
= response
->headers
->GetStatusLine();
3864 out
.response_info
= *response
; // Make a copy so we can verify.
3867 TestCompletionCallback read_callback
;
3869 std::string content
;
3871 // Read small chunks at a time.
3872 const int kSmallReadSize
= 3;
3873 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3874 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3875 if (rv
== net::ERR_IO_PENDING
) {
3876 data
.CompleteRead();
3877 rv
= read_callback
.WaitForResult();
3880 content
.append(buf
->data(), rv
);
3881 } else if (rv
< 0) {
3886 out
.response_data
.swap(content
);
3888 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3889 // MockClientSocketFactory) are still alive.
3890 base::RunLoop().RunUntilIdle();
3892 // Verify that we consumed all test data.
3893 helper
.VerifyDataConsumed();
3895 EXPECT_EQ(OK
, out
.rv
);
3896 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3897 EXPECT_EQ("goodbye world", out
.response_data
);
3900 // Verify that basic buffering works; when multiple data frames arrive
3901 // at the same time, ensure that we don't notify a read completion for
3902 // each data frame individually.
3903 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3904 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3906 scoped_ptr
<SpdyFrame
> req(
3907 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3908 MockWrite writes
[] = { CreateMockWrite(*req
) };
3910 // 4 data frames in a single read.
3911 scoped_ptr
<SpdyFrame
> data_frame(
3912 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3913 scoped_ptr
<SpdyFrame
> data_frame_fin(
3914 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3915 const SpdyFrame
* data_frames
[4] = {
3919 data_frame_fin
.get()
3921 char combined_data_frames
[100];
3922 int combined_data_frames_len
=
3923 CombineFrames(data_frames
, arraysize(data_frames
),
3924 combined_data_frames
, arraysize(combined_data_frames
));
3926 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3927 MockRead reads
[] = {
3928 CreateMockRead(*resp
),
3929 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3930 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3931 MockRead(ASYNC
, 0, 0) // EOF
3934 DelayedSocketData
data(1, reads
, arraysize(reads
),
3935 writes
, arraysize(writes
));
3937 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3938 BoundNetLog(), GetParam(), NULL
);
3939 helper
.RunPreTestSetup();
3940 helper
.AddData(&data
);
3941 HttpNetworkTransaction
* trans
= helper
.trans();
3943 TestCompletionCallback callback
;
3944 int rv
= trans
->Start(
3945 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3948 TransactionHelperResult out
= helper
.output();
3949 out
.rv
= callback
.WaitForResult();
3950 EXPECT_EQ(out
.rv
, OK
);
3952 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3953 EXPECT_TRUE(response
->headers
.get() != NULL
);
3954 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3955 out
.status_line
= response
->headers
->GetStatusLine();
3956 out
.response_info
= *response
; // Make a copy so we can verify.
3959 TestCompletionCallback read_callback
;
3961 std::string content
;
3962 int reads_completed
= 0;
3964 // Read small chunks at a time.
3965 const int kSmallReadSize
= 14;
3966 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3967 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3968 if (rv
== net::ERR_IO_PENDING
) {
3969 data
.CompleteRead();
3970 rv
= read_callback
.WaitForResult();
3973 EXPECT_EQ(kSmallReadSize
, rv
);
3974 content
.append(buf
->data(), rv
);
3975 } else if (rv
< 0) {
3976 FAIL() << "Unexpected read error: " << rv
;
3981 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3983 out
.response_data
.swap(content
);
3985 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3986 // MockClientSocketFactory) are still alive.
3987 base::RunLoop().RunUntilIdle();
3989 // Verify that we consumed all test data.
3990 helper
.VerifyDataConsumed();
3992 EXPECT_EQ(OK
, out
.rv
);
3993 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3994 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
3997 // Verify the case where we buffer data but read it after it has been buffered.
3998 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
3999 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4001 scoped_ptr
<SpdyFrame
> req(
4002 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4003 MockWrite writes
[] = { CreateMockWrite(*req
) };
4005 // 5 data frames in a single read.
4006 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4007 scoped_ptr
<SpdyFrame
> data_frame(
4008 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4009 scoped_ptr
<SpdyFrame
> data_frame_fin(
4010 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4011 const SpdyFrame
* frames
[5] = {reply
.get(), data_frame
.get(), data_frame
.get(),
4012 data_frame
.get(), data_frame_fin
.get()};
4013 char combined_frames
[200];
4014 int combined_frames_len
=
4015 CombineFrames(frames
, arraysize(frames
),
4016 combined_frames
, arraysize(combined_frames
));
4018 MockRead reads
[] = {
4019 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4020 MockRead(ASYNC
, 0, 0) // EOF
4023 DelayedSocketData
data(1, reads
, arraysize(reads
),
4024 writes
, arraysize(writes
));
4026 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4027 BoundNetLog(), GetParam(), NULL
);
4028 helper
.RunPreTestSetup();
4029 helper
.AddData(&data
);
4030 HttpNetworkTransaction
* trans
= helper
.trans();
4032 TestCompletionCallback callback
;
4033 int rv
= trans
->Start(
4034 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4037 TransactionHelperResult out
= helper
.output();
4038 out
.rv
= callback
.WaitForResult();
4039 EXPECT_EQ(out
.rv
, OK
);
4041 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4042 EXPECT_TRUE(response
->headers
.get() != NULL
);
4043 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4044 out
.status_line
= response
->headers
->GetStatusLine();
4045 out
.response_info
= *response
; // Make a copy so we can verify.
4048 TestCompletionCallback read_callback
;
4050 std::string content
;
4051 int reads_completed
= 0;
4053 // Read small chunks at a time.
4054 const int kSmallReadSize
= 14;
4055 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4056 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4058 EXPECT_EQ(kSmallReadSize
, rv
);
4059 content
.append(buf
->data(), rv
);
4060 } else if (rv
< 0) {
4061 FAIL() << "Unexpected read error: " << rv
;
4066 EXPECT_EQ(3, reads_completed
);
4068 out
.response_data
.swap(content
);
4070 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4071 // MockClientSocketFactory) are still alive.
4072 base::RunLoop().RunUntilIdle();
4074 // Verify that we consumed all test data.
4075 helper
.VerifyDataConsumed();
4077 EXPECT_EQ(OK
, out
.rv
);
4078 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4079 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4082 // Verify the case where we buffer data and close the connection.
4083 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4084 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4086 scoped_ptr
<SpdyFrame
> req(
4087 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4088 MockWrite writes
[] = { CreateMockWrite(*req
) };
4090 // All data frames in a single read.
4091 // NOTE: We don't FIN the stream.
4092 scoped_ptr
<SpdyFrame
> data_frame(
4093 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4094 const SpdyFrame
* data_frames
[4] = {
4100 char combined_data_frames
[100];
4101 int combined_data_frames_len
=
4102 CombineFrames(data_frames
, arraysize(data_frames
),
4103 combined_data_frames
, arraysize(combined_data_frames
));
4104 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4105 MockRead reads
[] = {
4106 CreateMockRead(*resp
),
4107 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4108 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4109 MockRead(ASYNC
, 0, 0) // EOF
4112 DelayedSocketData
data(1, reads
, arraysize(reads
),
4113 writes
, arraysize(writes
));
4115 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4116 BoundNetLog(), GetParam(), NULL
);
4117 helper
.RunPreTestSetup();
4118 helper
.AddData(&data
);
4119 HttpNetworkTransaction
* trans
= helper
.trans();
4121 TestCompletionCallback callback
;
4123 int rv
= trans
->Start(
4124 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4125 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4127 TransactionHelperResult out
= helper
.output();
4128 out
.rv
= callback
.WaitForResult();
4129 EXPECT_EQ(out
.rv
, OK
);
4131 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4132 EXPECT_TRUE(response
->headers
.get() != NULL
);
4133 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4134 out
.status_line
= response
->headers
->GetStatusLine();
4135 out
.response_info
= *response
; // Make a copy so we can verify.
4138 TestCompletionCallback read_callback
;
4140 std::string content
;
4141 int reads_completed
= 0;
4143 // Read small chunks at a time.
4144 const int kSmallReadSize
= 14;
4145 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4146 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4147 if (rv
== net::ERR_IO_PENDING
) {
4148 data
.CompleteRead();
4149 rv
= read_callback
.WaitForResult();
4152 content
.append(buf
->data(), rv
);
4153 } else if (rv
< 0) {
4154 // This test intentionally closes the connection, and will get an error.
4155 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4161 EXPECT_EQ(0, reads_completed
);
4163 out
.response_data
.swap(content
);
4165 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4166 // MockClientSocketFactory) are still alive.
4167 base::RunLoop().RunUntilIdle();
4169 // Verify that we consumed all test data.
4170 helper
.VerifyDataConsumed();
4173 // Verify the case where we buffer data and cancel the transaction.
4174 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4175 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4177 scoped_ptr
<SpdyFrame
> req(
4178 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4179 scoped_ptr
<SpdyFrame
> rst(
4180 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
4181 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*rst
)};
4183 // NOTE: We don't FIN the stream.
4184 scoped_ptr
<SpdyFrame
> data_frame(
4185 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4187 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4188 MockRead reads
[] = {
4189 CreateMockRead(*resp
),
4190 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4191 CreateMockRead(*data_frame
),
4192 MockRead(ASYNC
, 0, 0) // EOF
4195 DelayedSocketData
data(1, reads
, arraysize(reads
),
4196 writes
, arraysize(writes
));
4198 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4199 BoundNetLog(), GetParam(), NULL
);
4200 helper
.RunPreTestSetup();
4201 helper
.AddData(&data
);
4202 HttpNetworkTransaction
* trans
= helper
.trans();
4203 TestCompletionCallback callback
;
4205 int rv
= trans
->Start(
4206 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4209 TransactionHelperResult out
= helper
.output();
4210 out
.rv
= callback
.WaitForResult();
4211 EXPECT_EQ(out
.rv
, OK
);
4213 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4214 EXPECT_TRUE(response
->headers
.get() != NULL
);
4215 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4216 out
.status_line
= response
->headers
->GetStatusLine();
4217 out
.response_info
= *response
; // Make a copy so we can verify.
4220 TestCompletionCallback read_callback
;
4222 const int kReadSize
= 256;
4223 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4224 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4225 ASSERT_EQ(net::ERR_IO_PENDING
, rv
) << "Unexpected read: " << rv
;
4227 // Complete the read now, which causes buffering to start.
4228 data
.CompleteRead();
4229 // Destroy the transaction, causing the stream to get cancelled
4230 // and orphaning the buffered IO task.
4231 helper
.ResetTrans();
4233 // Flush the MessageLoop; this will cause the buffered IO task
4234 // to run for the final time.
4235 base::RunLoop().RunUntilIdle();
4237 // Verify that we consumed all test data.
4238 helper
.VerifyDataConsumed();
4241 // Test that if the server requests persistence of settings, that we save
4242 // the settings in the HttpServerProperties.
4243 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4244 if (spdy_util_
.spdy_version() >= SPDY4
) {
4245 // SPDY4 doesn't support settings persistence.
4248 static const SpdyHeaderInfo kSynReplyInfo
= {
4249 SYN_REPLY
, // Syn Reply
4251 0, // Associated Stream ID
4252 ConvertRequestPriorityToSpdyPriority(
4253 LOWEST
, spdy_util_
.spdy_version()),
4254 kSpdyCredentialSlotUnused
,
4255 CONTROL_FLAG_NONE
, // Control Flags
4256 false, // Compressed
4257 RST_STREAM_INVALID
, // Status
4260 DATA_FLAG_NONE
// Data Flags
4263 BoundNetLog net_log
;
4264 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4265 net_log
, GetParam(), NULL
);
4266 helper
.RunPreTestSetup();
4268 // Verify that no settings exist initially.
4269 HostPortPair
host_port_pair("www.google.com", helper
.port());
4270 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4271 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4272 host_port_pair
).empty());
4274 // Construct the request.
4275 scoped_ptr
<SpdyFrame
> req(
4276 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4277 MockWrite writes
[] = { CreateMockWrite(*req
) };
4279 // Construct the reply.
4280 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4281 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4282 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4283 scoped_ptr
<SpdyFrame
> reply(
4284 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4286 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4287 unsigned int kSampleValue1
= 0x0a0a0a0a;
4288 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4289 unsigned int kSampleValue2
= 0x0b0b0b0b;
4290 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4291 unsigned int kSampleValue3
= 0x0c0c0c0c;
4292 scoped_ptr
<SpdyFrame
> settings_frame
;
4294 // Construct the SETTINGS frame.
4295 SettingsMap settings
;
4296 // First add a persisted setting.
4297 settings
[kSampleId1
] =
4298 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4299 // Next add a non-persisted setting.
4300 settings
[kSampleId2
] =
4301 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4302 // Next add another persisted setting.
4303 settings
[kSampleId3
] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4305 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4308 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4309 MockRead reads
[] = {
4310 CreateMockRead(*reply
),
4311 CreateMockRead(*body
),
4312 CreateMockRead(*settings_frame
),
4313 MockRead(ASYNC
, 0, 0) // EOF
4316 DelayedSocketData
data(1, reads
, arraysize(reads
),
4317 writes
, arraysize(writes
));
4318 helper
.AddData(&data
);
4319 helper
.RunDefaultTest();
4320 helper
.VerifyDataConsumed();
4321 TransactionHelperResult out
= helper
.output();
4322 EXPECT_EQ(OK
, out
.rv
);
4323 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4324 EXPECT_EQ("hello!", out
.response_data
);
4327 // Verify we had two persisted settings.
4328 const SettingsMap
& settings_map
=
4329 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4331 ASSERT_EQ(2u, settings_map
.size());
4333 // Verify the first persisted setting.
4334 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4335 EXPECT_TRUE(it1
!= settings_map
.end());
4336 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4337 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4338 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4340 // Verify the second persisted setting.
4341 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4342 EXPECT_TRUE(it3
!= settings_map
.end());
4343 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4344 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4345 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4349 // Test that when there are settings saved that they are sent back to the
4350 // server upon session establishment.
4351 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4352 if (spdy_util_
.spdy_version() >= SPDY4
) {
4353 // SPDY4 doesn't support settings persistence.
4356 static const SpdyHeaderInfo kSynReplyInfo
= {
4357 SYN_REPLY
, // Syn Reply
4359 0, // Associated Stream ID
4360 ConvertRequestPriorityToSpdyPriority(
4361 LOWEST
, spdy_util_
.spdy_version()),
4362 kSpdyCredentialSlotUnused
,
4363 CONTROL_FLAG_NONE
, // Control Flags
4364 false, // Compressed
4365 RST_STREAM_INVALID
, // Status
4368 DATA_FLAG_NONE
// Data Flags
4371 BoundNetLog net_log
;
4372 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4373 net_log
, GetParam(), NULL
);
4374 helper
.RunPreTestSetup();
4376 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4378 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4379 pool_peer
.SetEnableSendingInitialData(true);
4381 // Verify that no settings exist initially.
4382 HostPortPair
host_port_pair("www.google.com", helper
.port());
4383 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4384 host_port_pair
).empty());
4386 const SpdySettingsIds kSampleId1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
4387 unsigned int kSampleValue1
= 0x0a0a0a0a;
4388 const SpdySettingsIds kSampleId2
= SETTINGS_INITIAL_WINDOW_SIZE
;
4389 unsigned int kSampleValue2
= 0x0c0c0c0c;
4391 // First add a persisted setting.
4392 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4395 SETTINGS_FLAG_PLEASE_PERSIST
,
4398 // Next add another persisted setting.
4399 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4402 SETTINGS_FLAG_PLEASE_PERSIST
,
4405 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4406 host_port_pair
).size());
4408 // Construct the initial SETTINGS frame.
4409 SettingsMap initial_settings
;
4410 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4411 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4412 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4413 spdy_util_
.ConstructSpdySettings(initial_settings
));
4415 // Construct the initial window update.
4416 scoped_ptr
<SpdyFrame
> initial_window_update(
4417 spdy_util_
.ConstructSpdyWindowUpdate(
4418 kSessionFlowControlStreamId
,
4419 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
4421 // Construct the persisted SETTINGS frame.
4422 const SettingsMap
& settings
=
4423 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4425 scoped_ptr
<SpdyFrame
> settings_frame(
4426 spdy_util_
.ConstructSpdySettings(settings
));
4428 // Construct the request.
4429 scoped_ptr
<SpdyFrame
> req(
4430 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4432 std::vector
<MockWrite
> writes
;
4433 if ((GetParam().protocol
>= kProtoSPDY4MinimumVersion
) &&
4434 (GetParam().protocol
<= kProtoSPDY4MaximumVersion
)) {
4437 kHttp2ConnectionHeaderPrefix
,
4438 kHttp2ConnectionHeaderPrefixSize
));
4440 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4441 if (GetParam().protocol
>= kProtoSPDY31
) {
4442 writes
.push_back(CreateMockWrite(*initial_window_update
));
4444 writes
.push_back(CreateMockWrite(*settings_frame
));
4445 writes
.push_back(CreateMockWrite(*req
));
4447 // Construct the reply.
4448 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4449 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4450 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4451 scoped_ptr
<SpdyFrame
> reply(
4452 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4454 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4455 MockRead reads
[] = {
4456 CreateMockRead(*reply
),
4457 CreateMockRead(*body
),
4458 MockRead(ASYNC
, 0, 0) // EOF
4461 DelayedSocketData
data(2, reads
, arraysize(reads
),
4462 vector_as_array(&writes
), writes
.size());
4463 helper
.AddData(&data
);
4464 helper
.RunDefaultTest();
4465 helper
.VerifyDataConsumed();
4466 TransactionHelperResult out
= helper
.output();
4467 EXPECT_EQ(OK
, out
.rv
);
4468 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4469 EXPECT_EQ("hello!", out
.response_data
);
4472 // Verify we had two persisted settings.
4473 const SettingsMap
& settings_map
=
4474 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4476 ASSERT_EQ(2u, settings_map
.size());
4478 // Verify the first persisted setting.
4479 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4480 EXPECT_TRUE(it1
!= settings_map
.end());
4481 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4482 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4483 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4485 // Verify the second persisted setting.
4486 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4487 EXPECT_TRUE(it2
!= settings_map
.end());
4488 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4489 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4490 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4494 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4495 scoped_ptr
<SpdyFrame
> req(
4496 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4497 MockWrite writes
[] = { CreateMockWrite(*req
) };
4499 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4500 MockRead reads
[] = {
4501 CreateMockRead(*go_away
),
4504 DelayedSocketData
data(1, reads
, arraysize(reads
),
4505 writes
, arraysize(writes
));
4506 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4507 BoundNetLog(), GetParam(), NULL
);
4508 helper
.AddData(&data
);
4509 helper
.RunToCompletion(&data
);
4510 TransactionHelperResult out
= helper
.output();
4511 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4514 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4515 scoped_ptr
<SpdyFrame
> req(
4516 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4517 MockWrite writes
[] = { CreateMockWrite(*req
) };
4519 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4520 MockRead reads
[] = {
4521 CreateMockRead(*resp
),
4522 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4525 DelayedSocketData
data(1, reads
, arraysize(reads
),
4526 writes
, arraysize(writes
));
4528 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4529 log
, GetParam(), NULL
);
4530 helper
.RunPreTestSetup();
4531 helper
.AddData(&data
);
4532 HttpNetworkTransaction
* trans
= helper
.trans();
4534 TestCompletionCallback callback
;
4535 TransactionHelperResult out
;
4536 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4538 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4539 out
.rv
= callback
.WaitForResult();
4540 EXPECT_EQ(out
.rv
, OK
);
4542 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4543 EXPECT_TRUE(response
->headers
.get() != NULL
);
4544 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4545 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4546 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4548 // Verify that we consumed all test data.
4549 helper
.VerifyDataConsumed();
4552 // Test to make sure we can correctly connect through a proxy.
4553 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4554 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4555 BoundNetLog(), GetParam(), NULL
);
4556 helper
.session_deps().reset(CreateSpdySessionDependencies(
4558 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4559 helper
.SetSession(make_scoped_refptr(
4560 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4561 helper
.RunPreTestSetup();
4562 HttpNetworkTransaction
* trans
= helper
.trans();
4564 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4565 "Host: www.google.com\r\n"
4566 "Proxy-Connection: keep-alive\r\n\r\n"};
4567 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4568 "Host: www.google.com\r\n"
4569 "Proxy-Connection: keep-alive\r\n\r\n"};
4570 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4571 scoped_ptr
<SpdyFrame
> req(
4572 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4573 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4574 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4576 MockWrite writes_SPDYNPN
[] = {
4577 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4578 CreateMockWrite(*req
, 2),
4580 MockRead reads_SPDYNPN
[] = {
4581 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4582 CreateMockRead(*resp
, 3),
4583 CreateMockRead(*body
.get(), 4),
4584 MockRead(ASYNC
, 0, 0, 5),
4587 MockWrite writes_SPDYSSL
[] = {
4588 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4589 CreateMockWrite(*req
, 2),
4591 MockRead reads_SPDYSSL
[] = {
4592 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4593 CreateMockRead(*resp
, 3),
4594 CreateMockRead(*body
.get(), 4),
4595 MockRead(ASYNC
, 0, 0, 5),
4598 MockWrite writes_SPDYNOSSL
[] = {
4599 CreateMockWrite(*req
, 0),
4602 MockRead reads_SPDYNOSSL
[] = {
4603 CreateMockRead(*resp
, 1),
4604 CreateMockRead(*body
.get(), 2),
4605 MockRead(ASYNC
, 0, 0, 3),
4608 scoped_ptr
<OrderedSocketData
> data
;
4609 switch (GetParam().ssl_type
) {
4611 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4612 arraysize(reads_SPDYNOSSL
),
4614 arraysize(writes_SPDYNOSSL
)));
4617 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4618 arraysize(reads_SPDYSSL
),
4620 arraysize(writes_SPDYSSL
)));
4623 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4624 arraysize(reads_SPDYNPN
),
4626 arraysize(writes_SPDYNPN
)));
4632 helper
.AddData(data
.get());
4633 TestCompletionCallback callback
;
4635 int rv
= trans
->Start(
4636 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4637 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4639 rv
= callback
.WaitForResult();
4642 // Verify the SYN_REPLY.
4643 HttpResponseInfo response
= *trans
->GetResponseInfo();
4644 EXPECT_TRUE(response
.headers
.get() != NULL
);
4645 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4647 std::string response_data
;
4648 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4649 EXPECT_EQ("hello!", response_data
);
4650 helper
.VerifyDataConsumed();
4653 // Test to make sure we can correctly connect through a proxy to www.google.com,
4654 // if there already exists a direct spdy connection to www.google.com. See
4655 // http://crbug.com/49874
4656 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4657 // When setting up the first transaction, we store the SpdySessionPool so that
4658 // we can use the same pool in the second transaction.
4659 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4660 BoundNetLog(), GetParam(), NULL
);
4662 // Use a proxy service which returns a proxy fallback list from DIRECT to
4663 // myproxy:70. For this test there will be no fallback, so it is equivalent
4664 // to simply DIRECT. The reason for appending the second proxy is to verify
4665 // that the session pool key used does is just "DIRECT".
4666 helper
.session_deps().reset(CreateSpdySessionDependencies(
4668 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4669 helper
.SetSession(make_scoped_refptr(
4670 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4672 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4673 helper
.RunPreTestSetup();
4675 // Construct and send a simple GET request.
4676 scoped_ptr
<SpdyFrame
> req(
4677 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4678 MockWrite writes
[] = {
4679 CreateMockWrite(*req
, 1),
4682 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4683 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4684 MockRead reads
[] = {
4685 CreateMockRead(*resp
, 2),
4686 CreateMockRead(*body
, 3),
4687 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4688 MockRead(ASYNC
, 0, 5) // EOF
4690 OrderedSocketData
data(reads
, arraysize(reads
),
4691 writes
, arraysize(writes
));
4692 helper
.AddData(&data
);
4693 HttpNetworkTransaction
* trans
= helper
.trans();
4695 TestCompletionCallback callback
;
4696 TransactionHelperResult out
;
4697 out
.rv
= trans
->Start(
4698 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4700 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4701 out
.rv
= callback
.WaitForResult();
4702 EXPECT_EQ(out
.rv
, OK
);
4704 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4705 EXPECT_TRUE(response
->headers
.get() != NULL
);
4706 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4707 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4708 EXPECT_EQ(OK
, out
.rv
);
4709 out
.status_line
= response
->headers
->GetStatusLine();
4710 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4711 EXPECT_EQ("hello!", out
.response_data
);
4713 // Check that the SpdySession is still in the SpdySessionPool.
4714 HostPortPair
host_port_pair("www.google.com", helper
.port());
4715 SpdySessionKey
session_pool_key_direct(
4716 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4717 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4718 SpdySessionKey
session_pool_key_proxy(
4720 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4721 PRIVACY_MODE_DISABLED
);
4722 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4724 // Set up data for the proxy connection.
4725 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4726 "Host: www.google.com\r\n"
4727 "Proxy-Connection: keep-alive\r\n\r\n"};
4728 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4729 "Host: www.google.com\r\n"
4730 "Proxy-Connection: keep-alive\r\n\r\n"};
4731 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4732 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4733 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4734 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4735 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4737 MockWrite writes_SPDYNPN
[] = {
4738 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4739 CreateMockWrite(*req2
, 2),
4741 MockRead reads_SPDYNPN
[] = {
4742 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4743 CreateMockRead(*resp2
, 3),
4744 CreateMockRead(*body2
, 4),
4745 MockRead(ASYNC
, 0, 5) // EOF
4748 MockWrite writes_SPDYNOSSL
[] = {
4749 CreateMockWrite(*req2
, 0),
4751 MockRead reads_SPDYNOSSL
[] = {
4752 CreateMockRead(*resp2
, 1),
4753 CreateMockRead(*body2
, 2),
4754 MockRead(ASYNC
, 0, 3) // EOF
4757 MockWrite writes_SPDYSSL
[] = {
4758 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4759 CreateMockWrite(*req2
, 2),
4761 MockRead reads_SPDYSSL
[] = {
4762 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4763 CreateMockRead(*resp2
, 3),
4764 CreateMockRead(*body2
, 4),
4765 MockRead(ASYNC
, 0, 0, 5),
4768 scoped_ptr
<OrderedSocketData
> data_proxy
;
4769 switch (GetParam().ssl_type
) {
4771 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
4772 arraysize(reads_SPDYNPN
),
4774 arraysize(writes_SPDYNPN
)));
4777 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4778 arraysize(reads_SPDYNOSSL
),
4780 arraysize(writes_SPDYNOSSL
)));
4783 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
4784 arraysize(reads_SPDYSSL
),
4786 arraysize(writes_SPDYSSL
)));
4792 // Create another request to www.google.com, but this time through a proxy.
4793 HttpRequestInfo request_proxy
;
4794 request_proxy
.method
= "GET";
4795 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
4796 request_proxy
.load_flags
= 0;
4797 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
4798 CreateSpdySessionDependencies(GetParam()));
4799 // Ensure that this transaction uses the same SpdySessionPool.
4800 scoped_refptr
<HttpNetworkSession
> session_proxy(
4801 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4802 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
4803 BoundNetLog(), GetParam(), NULL
);
4804 HttpNetworkSessionPeer
session_peer(session_proxy
);
4805 scoped_ptr
<net::ProxyService
> proxy_service(
4806 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4807 session_peer
.SetProxyService(proxy_service
.get());
4808 helper_proxy
.session_deps().swap(ssd_proxy
);
4809 helper_proxy
.SetSession(session_proxy
);
4810 helper_proxy
.RunPreTestSetup();
4811 helper_proxy
.AddData(data_proxy
.get());
4813 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4814 TestCompletionCallback callback_proxy
;
4815 int rv
= trans_proxy
->Start(
4816 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
4817 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4818 rv
= callback_proxy
.WaitForResult();
4821 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4822 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
4823 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4825 std::string response_data
;
4826 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4827 EXPECT_EQ("hello!", response_data
);
4829 data
.CompleteRead();
4830 helper_proxy
.VerifyDataConsumed();
4833 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4834 // on a new connection, if the connection was previously known to be good.
4835 // This can happen when a server reboots without saying goodbye, or when
4836 // we're behind a NAT that masked the RST.
4837 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4838 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4839 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4840 MockRead reads
[] = {
4841 CreateMockRead(*resp
),
4842 CreateMockRead(*body
),
4843 MockRead(ASYNC
, ERR_IO_PENDING
),
4844 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
4847 MockRead reads2
[] = {
4848 CreateMockRead(*resp
),
4849 CreateMockRead(*body
),
4850 MockRead(ASYNC
, 0, 0) // EOF
4853 // This test has a couple of variants.
4855 // Induce the RST while waiting for our transaction to send.
4856 VARIANT_RST_DURING_SEND_COMPLETION
,
4857 // Induce the RST while waiting for our transaction to read.
4858 // In this case, the send completed - everything copied into the SNDBUF.
4859 VARIANT_RST_DURING_READ_COMPLETION
4862 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4863 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4865 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
4867 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
4869 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4870 BoundNetLog(), GetParam(), NULL
);
4871 helper
.AddData(&data1
);
4872 helper
.AddData(&data2
);
4873 helper
.RunPreTestSetup();
4875 for (int i
= 0; i
< 2; ++i
) {
4876 scoped_ptr
<HttpNetworkTransaction
> trans(
4877 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
4879 TestCompletionCallback callback
;
4880 int rv
= trans
->Start(
4881 &helper
.request(), callback
.callback(), BoundNetLog());
4882 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4883 // On the second transaction, we trigger the RST.
4885 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4886 // Writes to the socket complete asynchronously on SPDY by running
4887 // through the message loop. Complete the write here.
4888 base::RunLoop().RunUntilIdle();
4891 // Now schedule the ERR_CONNECTION_RESET.
4892 EXPECT_EQ(3u, data1
.read_index());
4893 data1
.CompleteRead();
4894 EXPECT_EQ(4u, data1
.read_index());
4896 rv
= callback
.WaitForResult();
4899 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4900 ASSERT_TRUE(response
!= NULL
);
4901 EXPECT_TRUE(response
->headers
.get() != NULL
);
4902 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4903 std::string response_data
;
4904 rv
= ReadTransaction(trans
.get(), &response_data
);
4906 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4907 EXPECT_EQ("hello!", response_data
);
4910 helper
.VerifyDataConsumed();
4914 // Test that turning SPDY on and off works properly.
4915 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4916 HttpStreamFactory::set_spdy_enabled(true);
4917 scoped_ptr
<SpdyFrame
> req(
4918 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4919 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4921 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4922 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4923 MockRead spdy_reads
[] = {
4924 CreateMockRead(*resp
),
4925 CreateMockRead(*body
),
4926 MockRead(ASYNC
, 0, 0) // EOF
4929 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
4930 spdy_writes
, arraysize(spdy_writes
));
4931 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4932 BoundNetLog(), GetParam(), NULL
);
4933 helper
.RunToCompletion(&data
);
4934 TransactionHelperResult out
= helper
.output();
4935 EXPECT_EQ(OK
, out
.rv
);
4936 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4937 EXPECT_EQ("hello!", out
.response_data
);
4939 net::HttpStreamFactory::set_spdy_enabled(false);
4940 MockRead http_reads
[] = {
4941 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4942 MockRead("hello from http"),
4943 MockRead(SYNCHRONOUS
, OK
),
4945 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
4946 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
4947 BoundNetLog(), GetParam(), NULL
);
4948 helper2
.SetSpdyDisabled();
4949 helper2
.RunToCompletion(&data2
);
4950 TransactionHelperResult out2
= helper2
.output();
4951 EXPECT_EQ(OK
, out2
.rv
);
4952 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
4953 EXPECT_EQ("hello from http", out2
.response_data
);
4955 net::HttpStreamFactory::set_spdy_enabled(true);
4958 // Tests that Basic authentication works over SPDY
4959 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
4960 net::HttpStreamFactory::set_spdy_enabled(true);
4962 // The first request will be a bare GET, the second request will be a
4963 // GET with an Authorization header.
4964 scoped_ptr
<SpdyFrame
> req_get(
4965 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4966 const char* const kExtraAuthorizationHeaders
[] = {
4967 "authorization", "Basic Zm9vOmJhcg=="
4969 scoped_ptr
<SpdyFrame
> req_get_authorization(
4970 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
4971 arraysize(kExtraAuthorizationHeaders
) / 2,
4972 false, 3, LOWEST
, true));
4973 MockWrite spdy_writes
[] = {
4974 CreateMockWrite(*req_get
, 1),
4975 CreateMockWrite(*req_get_authorization
, 4),
4978 // The first response is a 401 authentication challenge, and the second
4979 // response will be a 200 response since the second request includes a valid
4980 // Authorization header.
4981 const char* const kExtraAuthenticationHeaders
[] = {
4983 "Basic realm=\"MyRealm\""
4985 scoped_ptr
<SpdyFrame
> resp_authentication(
4986 spdy_util_
.ConstructSpdySynReplyError(
4987 "401 Authentication Required",
4988 kExtraAuthenticationHeaders
,
4989 arraysize(kExtraAuthenticationHeaders
) / 2,
4991 scoped_ptr
<SpdyFrame
> body_authentication(
4992 spdy_util_
.ConstructSpdyBodyFrame(1, true));
4993 scoped_ptr
<SpdyFrame
> resp_data(
4994 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4995 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
4996 MockRead spdy_reads
[] = {
4997 CreateMockRead(*resp_authentication
, 2),
4998 CreateMockRead(*body_authentication
, 3),
4999 CreateMockRead(*resp_data
, 5),
5000 CreateMockRead(*body_data
, 6),
5001 MockRead(ASYNC
, 0, 7),
5004 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5005 spdy_writes
, arraysize(spdy_writes
));
5006 HttpRequestInfo
request(CreateGetRequest());
5007 BoundNetLog net_log
;
5008 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5009 net_log
, GetParam(), NULL
);
5011 helper
.RunPreTestSetup();
5012 helper
.AddData(&data
);
5013 HttpNetworkTransaction
* trans
= helper
.trans();
5014 TestCompletionCallback callback
;
5015 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5016 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5017 const int rv_start_complete
= callback
.WaitForResult();
5018 EXPECT_EQ(OK
, rv_start_complete
);
5020 // Make sure the response has an auth challenge.
5021 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5022 ASSERT_TRUE(response_start
!= NULL
);
5023 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5024 EXPECT_EQ(401, response_start
->headers
->response_code());
5025 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5026 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5027 ASSERT_TRUE(auth_challenge
!= NULL
);
5028 EXPECT_FALSE(auth_challenge
->is_proxy
);
5029 EXPECT_EQ("basic", auth_challenge
->scheme
);
5030 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5032 // Restart with a username/password.
5033 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5034 base::ASCIIToUTF16("bar"));
5035 TestCompletionCallback callback_restart
;
5036 const int rv_restart
= trans
->RestartWithAuth(
5037 credentials
, callback_restart
.callback());
5038 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5039 const int rv_restart_complete
= callback_restart
.WaitForResult();
5040 EXPECT_EQ(OK
, rv_restart_complete
);
5041 // TODO(cbentzel): This is actually the same response object as before, but
5042 // data has changed.
5043 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5044 ASSERT_TRUE(response_restart
!= NULL
);
5045 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5046 EXPECT_EQ(200, response_restart
->headers
->response_code());
5047 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5050 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5051 scoped_ptr
<SpdyFrame
> stream1_syn(
5052 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5053 scoped_ptr
<SpdyFrame
> stream1_body(
5054 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5055 MockWrite writes
[] = {
5056 CreateMockWrite(*stream1_syn
, 1),
5059 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5060 spdy_util_
.AddUrlToHeaderBlock(
5061 "http://www.google.com/foo.dat", initial_headers
.get());
5062 scoped_ptr
<SpdyFrame
> stream2_syn(
5063 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5065 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5066 (*late_headers
)["hello"] = "bye";
5067 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5068 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5069 scoped_ptr
<SpdyFrame
> stream2_headers(
5070 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5078 scoped_ptr
<SpdyFrame
>
5079 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5080 const char kPushedData
[] = "pushed";
5081 scoped_ptr
<SpdyFrame
> stream2_body(
5082 spdy_util_
.ConstructSpdyBodyFrame(
5083 2, kPushedData
, strlen(kPushedData
), true));
5084 MockRead reads
[] = {
5085 CreateMockRead(*stream1_reply
, 2),
5086 CreateMockRead(*stream2_syn
, 3),
5087 CreateMockRead(*stream2_headers
, 4),
5088 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5089 CreateMockRead(*stream2_body
, 5),
5090 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5093 HttpResponseInfo response
;
5094 HttpResponseInfo response2
;
5095 std::string
expected_push_result("pushed");
5096 OrderedSocketData
data(reads
, arraysize(reads
),
5097 writes
, arraysize(writes
));
5098 RunServerPushTest(&data
,
5101 expected_push_result
);
5103 // Verify the SYN_REPLY.
5104 EXPECT_TRUE(response
.headers
.get() != NULL
);
5105 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5107 // Verify the pushed stream.
5108 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5109 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5112 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5113 // We push a stream and attempt to claim it before the headers come down.
5114 scoped_ptr
<SpdyFrame
> stream1_syn(
5115 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5116 scoped_ptr
<SpdyFrame
> stream1_body(
5117 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5118 MockWrite writes
[] = {
5119 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5122 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5123 spdy_util_
.AddUrlToHeaderBlock(
5124 "http://www.google.com/foo.dat", initial_headers
.get());
5125 scoped_ptr
<SpdyFrame
> stream2_syn(
5126 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5128 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5129 (*late_headers
)["hello"] = "bye";
5130 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5131 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5132 scoped_ptr
<SpdyFrame
> stream2_headers(
5133 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5141 scoped_ptr
<SpdyFrame
>
5142 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5143 const char kPushedData
[] = "pushed";
5144 scoped_ptr
<SpdyFrame
> stream2_body(
5145 spdy_util_
.ConstructSpdyBodyFrame(
5146 2, kPushedData
, strlen(kPushedData
), true));
5147 MockRead reads
[] = {
5148 CreateMockRead(*stream1_reply
, 1),
5149 CreateMockRead(*stream2_syn
, 2),
5150 CreateMockRead(*stream1_body
, 3),
5151 CreateMockRead(*stream2_headers
, 4),
5152 CreateMockRead(*stream2_body
, 5),
5153 MockRead(ASYNC
, 0, 6), // EOF
5156 HttpResponseInfo response
;
5157 HttpResponseInfo response2
;
5158 std::string
expected_push_result("pushed");
5159 DeterministicSocketData
data(reads
, arraysize(reads
),
5160 writes
, arraysize(writes
));
5162 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5163 BoundNetLog(), GetParam(), NULL
);
5164 helper
.SetDeterministic();
5165 helper
.AddDeterministicData(&data
);
5166 helper
.RunPreTestSetup();
5168 HttpNetworkTransaction
* trans
= helper
.trans();
5170 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5171 // and the body of the primary stream, but before we've received the HEADERS
5172 // for the pushed stream.
5175 // Start the transaction.
5176 TestCompletionCallback callback
;
5177 int rv
= trans
->Start(
5178 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5181 rv
= callback
.WaitForResult();
5184 // Request the pushed path. At this point, we've received the push, but the
5185 // headers are not yet complete.
5186 scoped_ptr
<HttpNetworkTransaction
> trans2(
5187 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5189 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5190 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5192 base::RunLoop().RunUntilIdle();
5194 // Read the server push body.
5195 std::string result2
;
5196 ReadResult(trans2
.get(), &data
, &result2
);
5197 // Read the response body.
5199 ReadResult(trans
, &data
, &result
);
5201 // Verify that the received push data is same as the expected push data.
5202 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5203 << "Received data: "
5205 << "||||| Expected data: "
5206 << expected_push_result
;
5208 // Verify the SYN_REPLY.
5209 // Copy the response info, because trans goes away.
5210 response
= *trans
->GetResponseInfo();
5211 response2
= *trans2
->GetResponseInfo();
5213 VerifyStreamsClosed(helper
);
5215 // Verify the SYN_REPLY.
5216 EXPECT_TRUE(response
.headers
.get() != NULL
);
5217 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5219 // Verify the pushed stream.
5220 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5221 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5223 // Read the final EOF (which will close the session)
5226 // Verify that we consumed all test data.
5227 EXPECT_TRUE(data
.at_read_eof());
5228 EXPECT_TRUE(data
.at_write_eof());
5231 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5232 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5233 // We push a stream and attempt to claim it before the headers come down.
5234 scoped_ptr
<SpdyFrame
> stream1_syn(
5235 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5236 scoped_ptr
<SpdyFrame
> stream1_body(
5237 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5238 MockWrite writes
[] = {
5239 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5242 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5243 if (spdy_util_
.spdy_version() < SPDY4
) {
5244 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5245 (*initial_headers
)["alpha"] = "beta";
5247 spdy_util_
.AddUrlToHeaderBlock(
5248 "http://www.google.com/foo.dat", initial_headers
.get());
5249 scoped_ptr
<SpdyFrame
> stream2_syn(
5250 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5252 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5253 (*middle_headers
)["hello"] = "bye";
5254 scoped_ptr
<SpdyFrame
> stream2_headers1(
5255 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5263 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5264 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5265 if (spdy_util_
.spdy_version() < SPDY4
) {
5266 // SPDY4/HTTP2 eliminates use of the :version header.
5267 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5269 scoped_ptr
<SpdyFrame
> stream2_headers2(
5270 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5278 scoped_ptr
<SpdyFrame
>
5279 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5280 const char kPushedData
[] = "pushed";
5281 scoped_ptr
<SpdyFrame
> stream2_body(
5282 spdy_util_
.ConstructSpdyBodyFrame(
5283 2, kPushedData
, strlen(kPushedData
), true));
5284 MockRead reads
[] = {
5285 CreateMockRead(*stream1_reply
, 1),
5286 CreateMockRead(*stream2_syn
, 2),
5287 CreateMockRead(*stream1_body
, 3),
5288 CreateMockRead(*stream2_headers1
, 4),
5289 CreateMockRead(*stream2_headers2
, 5),
5290 CreateMockRead(*stream2_body
, 6),
5291 MockRead(ASYNC
, 0, 7), // EOF
5294 HttpResponseInfo response
;
5295 HttpResponseInfo response2
;
5296 std::string
expected_push_result("pushed");
5297 DeterministicSocketData
data(reads
, arraysize(reads
),
5298 writes
, arraysize(writes
));
5300 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5301 BoundNetLog(), GetParam(), NULL
);
5302 helper
.SetDeterministic();
5303 helper
.AddDeterministicData(&data
);
5304 helper
.RunPreTestSetup();
5306 HttpNetworkTransaction
* trans
= helper
.trans();
5308 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5309 // the first HEADERS frame, and the body of the primary stream, but before
5310 // we've received the final HEADERS for the pushed stream.
5313 // Start the transaction.
5314 TestCompletionCallback callback
;
5315 int rv
= trans
->Start(
5316 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5317 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5319 rv
= callback
.WaitForResult();
5322 // Request the pushed path. At this point, we've received the push, but the
5323 // headers are not yet complete.
5324 scoped_ptr
<HttpNetworkTransaction
> trans2(
5325 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5327 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5328 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5330 base::RunLoop().RunUntilIdle();
5332 // Read the server push body.
5333 std::string result2
;
5334 ReadResult(trans2
.get(), &data
, &result2
);
5335 // Read the response body.
5337 ReadResult(trans
, &data
, &result
);
5339 // Verify that the received push data is same as the expected push data.
5340 EXPECT_EQ(expected_push_result
, result2
);
5342 // Verify the SYN_REPLY.
5343 // Copy the response info, because trans goes away.
5344 response
= *trans
->GetResponseInfo();
5345 response2
= *trans2
->GetResponseInfo();
5347 VerifyStreamsClosed(helper
);
5349 // Verify the SYN_REPLY.
5350 EXPECT_TRUE(response
.headers
.get() != NULL
);
5351 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5353 // Verify the pushed stream.
5354 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5355 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5357 // Verify we got all the headers from all header blocks.
5358 if (spdy_util_
.spdy_version() < SPDY4
)
5359 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5360 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5361 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5363 // Read the final EOF (which will close the session)
5366 // Verify that we consumed all test data.
5367 EXPECT_TRUE(data
.at_read_eof());
5368 EXPECT_TRUE(data
.at_write_eof());
5371 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5372 // We push a stream and attempt to claim it before the headers come down.
5373 scoped_ptr
<SpdyFrame
> stream1_syn(
5374 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5375 scoped_ptr
<SpdyFrame
> stream1_body(
5376 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5377 MockWrite writes
[] = {
5378 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5381 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5382 spdy_util_
.AddUrlToHeaderBlock(
5383 "http://www.google.com/foo.dat", initial_headers
.get());
5384 scoped_ptr
<SpdyFrame
> stream2_syn(
5385 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5387 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5388 (*middle_headers
)["hello"] = "bye";
5389 scoped_ptr
<SpdyFrame
> stream2_headers1(
5390 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5398 scoped_ptr
<SpdyFrame
>
5399 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5400 const char kPushedData
[] = "pushed";
5401 scoped_ptr
<SpdyFrame
> stream2_body(
5402 spdy_util_
.ConstructSpdyBodyFrame(
5403 2, kPushedData
, strlen(kPushedData
), true));
5404 MockRead reads
[] = {
5405 CreateMockRead(*stream1_reply
, 1),
5406 CreateMockRead(*stream2_syn
, 2),
5407 CreateMockRead(*stream1_body
, 3),
5408 CreateMockRead(*stream2_headers1
, 4),
5409 CreateMockRead(*stream2_body
, 5),
5410 MockRead(ASYNC
, 0, 6), // EOF
5413 DeterministicSocketData
data(reads
, arraysize(reads
),
5414 writes
, arraysize(writes
));
5416 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5417 BoundNetLog(), GetParam(), NULL
);
5418 helper
.SetDeterministic();
5419 helper
.AddDeterministicData(&data
);
5420 helper
.RunPreTestSetup();
5422 HttpNetworkTransaction
* trans
= helper
.trans();
5424 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5425 // the first HEADERS frame, and the body of the primary stream, but before
5426 // we've received the final HEADERS for the pushed stream.
5429 // Start the transaction.
5430 TestCompletionCallback callback
;
5431 int rv
= trans
->Start(
5432 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5433 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5435 rv
= callback
.WaitForResult();
5438 // Request the pushed path. At this point, we've received the push, but the
5439 // headers are not yet complete.
5440 scoped_ptr
<HttpNetworkTransaction
> trans2(
5441 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5443 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5444 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5446 base::RunLoop().RunUntilIdle();
5448 // Read the server push body.
5449 std::string result2
;
5450 ReadResult(trans2
.get(), &data
, &result2
);
5451 // Read the response body.
5453 ReadResult(trans
, &data
, &result
);
5454 EXPECT_EQ("hello!", result
);
5456 // Verify that we haven't received any push data.
5457 EXPECT_EQ("", result2
);
5459 // Verify the SYN_REPLY.
5460 // Copy the response info, because trans goes away.
5461 HttpResponseInfo response
= *trans
->GetResponseInfo();
5462 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5464 VerifyStreamsClosed(helper
);
5466 // Verify the SYN_REPLY.
5467 EXPECT_TRUE(response
.headers
.get() != NULL
);
5468 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5470 // Read the final EOF (which will close the session).
5473 // Verify that we consumed all test data.
5474 EXPECT_TRUE(data
.at_read_eof());
5475 EXPECT_TRUE(data
.at_write_eof());
5478 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5479 scoped_ptr
<SpdyFrame
> req(
5480 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5481 scoped_ptr
<SpdyFrame
> rst(
5482 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5483 MockWrite writes
[] = {
5484 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5487 scoped_ptr
<SpdyFrame
> stream1_reply(
5488 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5490 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5491 (*late_headers
)["hello"] = "bye";
5492 scoped_ptr
<SpdyFrame
> stream1_headers(
5493 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5500 scoped_ptr
<SpdyFrame
> stream1_body(
5501 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5502 MockRead reads
[] = {
5503 CreateMockRead(*stream1_reply
),
5504 CreateMockRead(*stream1_headers
),
5505 CreateMockRead(*stream1_body
),
5506 MockRead(ASYNC
, 0, 0) // EOF
5509 DelayedSocketData
data(1, reads
, arraysize(reads
),
5510 writes
, arraysize(writes
));
5511 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5512 BoundNetLog(), GetParam(), NULL
);
5513 helper
.RunToCompletion(&data
);
5514 TransactionHelperResult out
= helper
.output();
5515 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5518 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5519 scoped_ptr
<SpdyFrame
> req(
5520 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5521 scoped_ptr
<SpdyFrame
> rst(
5522 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5523 MockWrite writes
[] = {
5524 CreateMockWrite(*req
),
5525 CreateMockWrite(*rst
),
5528 scoped_ptr
<SpdyFrame
> stream1_reply(
5529 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5531 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5532 (*late_headers
)["hello"] = "bye";
5533 scoped_ptr
<SpdyFrame
> stream1_headers(
5534 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5541 scoped_ptr
<SpdyFrame
> stream1_body(
5542 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5543 scoped_ptr
<SpdyFrame
> stream1_body2(
5544 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5545 MockRead reads
[] = {
5546 CreateMockRead(*stream1_reply
),
5547 CreateMockRead(*stream1_body
),
5548 CreateMockRead(*stream1_headers
),
5549 CreateMockRead(*stream1_body2
),
5550 MockRead(ASYNC
, 0, 0) // EOF
5553 DelayedSocketData
data(1, reads
, arraysize(reads
),
5554 writes
, arraysize(writes
));
5555 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5556 BoundNetLog(), GetParam(), NULL
);
5557 helper
.RunToCompletion(&data
);
5558 TransactionHelperResult out
= helper
.output();
5559 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5562 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5563 // In this test we want to verify that we can't accidentally push content
5564 // which can't be pushed by this content server.
5565 // This test assumes that:
5566 // - if we're requesting http://www.foo.com/barbaz
5567 // - the browser has made a connection to "www.foo.com".
5569 // A list of the URL to fetch, followed by the URL being pushed.
5570 static const char* const kTestCases
[] = {
5571 "http://www.google.com/foo.html",
5572 "http://www.google.com:81/foo.js", // Bad port
5574 "http://www.google.com/foo.html",
5575 "https://www.google.com/foo.js", // Bad protocol
5577 "http://www.google.com/foo.html",
5578 "ftp://www.google.com/foo.js", // Invalid Protocol
5580 "http://www.google.com/foo.html",
5581 "http://blat.www.google.com/foo.js", // Cross subdomain
5583 "http://www.google.com/foo.html",
5584 "http://www.foo.com/foo.js", // Cross domain
5587 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5588 const char* url_to_fetch
= kTestCases
[index
];
5589 const char* url_to_push
= kTestCases
[index
+ 1];
5591 scoped_ptr
<SpdyFrame
> stream1_syn(
5592 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5593 scoped_ptr
<SpdyFrame
> stream1_body(
5594 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5595 scoped_ptr
<SpdyFrame
> push_rst(
5596 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5597 MockWrite writes
[] = {
5598 CreateMockWrite(*stream1_syn
, 1),
5599 CreateMockWrite(*push_rst
, 4),
5602 scoped_ptr
<SpdyFrame
>
5603 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5604 scoped_ptr
<SpdyFrame
>
5605 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5610 const char kPushedData
[] = "pushed";
5611 scoped_ptr
<SpdyFrame
> stream2_body(
5612 spdy_util_
.ConstructSpdyBodyFrame(
5613 2, kPushedData
, strlen(kPushedData
), true));
5614 scoped_ptr
<SpdyFrame
> rst(
5615 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5617 MockRead reads
[] = {
5618 CreateMockRead(*stream1_reply
, 2),
5619 CreateMockRead(*stream2_syn
, 3),
5620 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5621 CreateMockRead(*stream2_body
, 6),
5622 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5625 HttpResponseInfo response
;
5626 OrderedSocketData
data(reads
, arraysize(reads
),
5627 writes
, arraysize(writes
));
5629 HttpRequestInfo request
;
5630 request
.method
= "GET";
5631 request
.url
= GURL(url_to_fetch
);
5632 request
.load_flags
= 0;
5634 // Enable cross-origin push. Since we are not using a proxy, this should
5635 // not actually enable cross-origin SPDY push.
5636 scoped_ptr
<SpdySessionDependencies
> session_deps(
5637 CreateSpdySessionDependencies(GetParam()));
5638 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5639 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5640 BoundNetLog(), GetParam(),
5641 session_deps
.release());
5642 helper
.RunPreTestSetup();
5643 helper
.AddData(&data
);
5645 HttpNetworkTransaction
* trans
= helper
.trans();
5647 // Start the transaction with basic parameters.
5648 TestCompletionCallback callback
;
5650 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5651 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5652 rv
= callback
.WaitForResult();
5654 // Read the response body.
5656 ReadResult(trans
, &data
, &result
);
5658 // Verify that we consumed all test data.
5659 EXPECT_TRUE(data
.at_read_eof());
5660 EXPECT_TRUE(data
.at_write_eof());
5662 // Verify the SYN_REPLY.
5663 // Copy the response info, because trans goes away.
5664 response
= *trans
->GetResponseInfo();
5666 VerifyStreamsClosed(helper
);
5668 // Verify the SYN_REPLY.
5669 EXPECT_TRUE(response
.headers
.get() != NULL
);
5670 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5674 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5675 // Construct the request.
5676 scoped_ptr
<SpdyFrame
> req(
5677 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5678 scoped_ptr
<SpdyFrame
> req2(
5679 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5680 MockWrite writes
[] = {
5681 CreateMockWrite(*req
, 1),
5682 CreateMockWrite(*req2
, 3),
5685 scoped_ptr
<SpdyFrame
> refused(
5686 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5687 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5688 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5689 MockRead reads
[] = {
5690 CreateMockRead(*refused
, 2),
5691 CreateMockRead(*resp
, 4),
5692 CreateMockRead(*body
, 5),
5693 MockRead(ASYNC
, 0, 6) // EOF
5696 OrderedSocketData
data(reads
, arraysize(reads
),
5697 writes
, arraysize(writes
));
5698 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5699 BoundNetLog(), GetParam(), NULL
);
5701 helper
.RunPreTestSetup();
5702 helper
.AddData(&data
);
5704 HttpNetworkTransaction
* trans
= helper
.trans();
5706 // Start the transaction with basic parameters.
5707 TestCompletionCallback callback
;
5708 int rv
= trans
->Start(
5709 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5710 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5711 rv
= callback
.WaitForResult();
5714 // Verify that we consumed all test data.
5715 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5716 << data
.read_count()
5718 << data
.read_index();
5719 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5720 << data
.write_count()
5722 << data
.write_index();
5724 // Verify the SYN_REPLY.
5725 HttpResponseInfo response
= *trans
->GetResponseInfo();
5726 EXPECT_TRUE(response
.headers
.get() != NULL
);
5727 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5730 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5731 // This first request will start to establish the SpdySession.
5732 // Then we will start the second (MEDIUM priority) and then third
5733 // (HIGHEST priority) request in such a way that the third will actually
5734 // start before the second, causing the second to be numbered differently
5735 // than the order they were created.
5736 scoped_ptr
<SpdyFrame
> req1(
5737 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5738 scoped_ptr
<SpdyFrame
> req2(
5739 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5740 scoped_ptr
<SpdyFrame
> req3(
5741 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5742 MockWrite writes
[] = {
5743 CreateMockWrite(*req1
, 0),
5744 CreateMockWrite(*req2
, 3),
5745 CreateMockWrite(*req3
, 4),
5748 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5749 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5750 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5751 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5752 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5753 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5754 MockRead reads
[] = {
5755 CreateMockRead(*resp1
, 1),
5756 CreateMockRead(*body1
, 2),
5757 CreateMockRead(*resp2
, 5),
5758 CreateMockRead(*body2
, 6),
5759 CreateMockRead(*resp3
, 7),
5760 CreateMockRead(*body3
, 8),
5761 MockRead(ASYNC
, 0, 9) // EOF
5764 DeterministicSocketData
data(reads
, arraysize(reads
),
5765 writes
, arraysize(writes
));
5766 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5767 BoundNetLog(), GetParam(), NULL
);
5768 helper
.SetDeterministic();
5769 helper
.RunPreTestSetup();
5770 helper
.AddDeterministicData(&data
);
5772 // Start the first transaction to set up the SpdySession
5773 HttpNetworkTransaction
* trans
= helper
.trans();
5774 TestCompletionCallback callback
;
5775 HttpRequestInfo info1
= CreateGetRequest();
5776 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
5777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5779 // Run the message loop, but do not allow the write to complete.
5780 // This leaves the SpdySession with a write pending, which prevents
5781 // SpdySession from attempting subsequent writes until this write completes.
5782 base::RunLoop().RunUntilIdle();
5784 // Now, start both new transactions
5785 HttpRequestInfo info2
= CreateGetRequest();
5786 TestCompletionCallback callback2
;
5787 scoped_ptr
<HttpNetworkTransaction
> trans2(
5788 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
5789 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
5790 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5791 base::RunLoop().RunUntilIdle();
5793 HttpRequestInfo info3
= CreateGetRequest();
5794 TestCompletionCallback callback3
;
5795 scoped_ptr
<HttpNetworkTransaction
> trans3(
5796 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
5797 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
5798 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5799 base::RunLoop().RunUntilIdle();
5801 // We now have two SYN_STREAM frames queued up which will be
5802 // dequeued only once the first write completes, which we
5803 // now allow to happen.
5805 EXPECT_EQ(OK
, callback
.WaitForResult());
5807 // And now we can allow everything else to run to completion.
5810 EXPECT_EQ(OK
, callback2
.WaitForResult());
5811 EXPECT_EQ(OK
, callback3
.WaitForResult());
5813 helper
.VerifyDataConsumed();
5816 // The tests below are only for SPDY/3 and above.
5818 // Test that sent data frames and received WINDOW_UPDATE frames change
5819 // the send_window_size_ correctly.
5821 // WINDOW_UPDATE is different than most other frames in that it can arrive
5822 // while the client is still sending the request body. In order to enforce
5823 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5824 // socket data provider, so that initial read that is done as soon as the
5825 // stream is created, succeeds and schedules another read. This way reads
5826 // and writes are interleaved; after doing a full frame write, SpdyStream
5827 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5828 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5829 // since request has not been completely written, therefore we feed
5830 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5831 // write, leading to a complete write of request body; after that we send
5832 // a reply with a body, to cause a graceful shutdown.
5834 // TODO(agayev): develop a socket data provider where both, reads and
5835 // writes are ordered so that writing tests like these are easy and rewrite
5836 // all these tests using it. Right now we are working around the
5837 // limitations as described above and it's not deterministic, tests may
5838 // fail under specific circumstances.
5839 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
5840 static int kFrameCount
= 2;
5841 scoped_ptr
<std::string
> content(
5842 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
5843 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
5844 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
5845 scoped_ptr
<SpdyFrame
> body(
5846 spdy_util_
.ConstructSpdyBodyFrame(
5847 1, content
->c_str(), content
->size(), false));
5848 scoped_ptr
<SpdyFrame
> body_end(
5849 spdy_util_
.ConstructSpdyBodyFrame(
5850 1, content
->c_str(), content
->size(), true));
5852 MockWrite writes
[] = {
5853 CreateMockWrite(*req
, 0),
5854 CreateMockWrite(*body
, 1),
5855 CreateMockWrite(*body_end
, 2),
5858 static const int32 kDeltaWindowSize
= 0xff;
5859 static const int kDeltaCount
= 4;
5860 scoped_ptr
<SpdyFrame
> window_update(
5861 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
5862 scoped_ptr
<SpdyFrame
> window_update_dummy(
5863 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
5864 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
5865 MockRead reads
[] = {
5866 CreateMockRead(*window_update_dummy
, 3),
5867 CreateMockRead(*window_update_dummy
, 4),
5868 CreateMockRead(*window_update_dummy
, 5),
5869 CreateMockRead(*window_update
, 6), // Four updates, therefore window
5870 CreateMockRead(*window_update
, 7), // size should increase by
5871 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
5872 CreateMockRead(*window_update
, 9),
5873 CreateMockRead(*resp
, 10),
5874 CreateMockRead(*body_end
, 11),
5875 MockRead(ASYNC
, 0, 0, 12) // EOF
5878 DeterministicSocketData
data(reads
, arraysize(reads
),
5879 writes
, arraysize(writes
));
5881 ScopedVector
<UploadElementReader
> element_readers
;
5882 for (int i
= 0; i
< kFrameCount
; ++i
) {
5883 element_readers
.push_back(
5884 new UploadBytesElementReader(content
->c_str(), content
->size()));
5886 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5888 // Setup the request
5889 HttpRequestInfo request
;
5890 request
.method
= "POST";
5891 request
.url
= GURL(kDefaultURL
);
5892 request
.upload_data_stream
= &upload_data_stream
;
5894 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5895 BoundNetLog(), GetParam(), NULL
);
5896 helper
.SetDeterministic();
5897 helper
.AddDeterministicData(&data
);
5898 helper
.RunPreTestSetup();
5900 HttpNetworkTransaction
* trans
= helper
.trans();
5902 TestCompletionCallback callback
;
5903 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5905 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5909 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5910 ASSERT_TRUE(stream
!= NULL
);
5911 ASSERT_TRUE(stream
->stream() != NULL
);
5912 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
) +
5913 kDeltaWindowSize
* kDeltaCount
-
5914 kMaxSpdyFrameChunkSize
* kFrameCount
,
5915 stream
->stream()->send_window_size());
5919 rv
= callback
.WaitForResult();
5922 helper
.VerifyDataConsumed();
5925 // Test that received data frames and sent WINDOW_UPDATE frames change
5926 // the recv_window_size_ correctly.
5927 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
5928 // Amount of body required to trigger a sent window update.
5929 const size_t kTargetSize
= kSpdyStreamInitialWindowSize
/ 2 + 1;
5931 scoped_ptr
<SpdyFrame
> req(
5932 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5933 scoped_ptr
<SpdyFrame
> session_window_update(
5934 spdy_util_
.ConstructSpdyWindowUpdate(0, kTargetSize
));
5935 scoped_ptr
<SpdyFrame
> window_update(
5936 spdy_util_
.ConstructSpdyWindowUpdate(1, kTargetSize
));
5938 std::vector
<MockWrite
> writes
;
5939 writes
.push_back(CreateMockWrite(*req
));
5940 if (GetParam().protocol
>= kProtoSPDY31
)
5941 writes
.push_back(CreateMockWrite(*session_window_update
));
5942 writes
.push_back(CreateMockWrite(*window_update
));
5944 std::vector
<MockRead
> reads
;
5945 scoped_ptr
<SpdyFrame
> resp(
5946 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5947 reads
.push_back(CreateMockRead(*resp
));
5949 ScopedVector
<SpdyFrame
> body_frames
;
5950 const std::string
body_data(4096, 'x');
5951 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
5952 size_t frame_size
= std::min(remaining
, body_data
.size());
5953 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
5954 1, body_data
.data(), frame_size
, false));
5955 reads
.push_back(CreateMockRead(*body_frames
.back()));
5956 remaining
-= frame_size
;
5958 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
5960 DelayedSocketData
data(1, vector_as_array(&reads
), reads
.size(),
5961 vector_as_array(&writes
), writes
.size());
5963 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5964 BoundNetLog(), GetParam(), NULL
);
5965 helper
.AddData(&data
);
5966 helper
.RunPreTestSetup();
5967 HttpNetworkTransaction
* trans
= helper
.trans();
5969 TestCompletionCallback callback
;
5970 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5972 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5973 rv
= callback
.WaitForResult();
5976 SpdyHttpStream
* stream
=
5977 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5978 ASSERT_TRUE(stream
!= NULL
);
5979 ASSERT_TRUE(stream
->stream() != NULL
);
5981 // All data has been read, but not consumed. The window reflects this.
5982 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
- kTargetSize
),
5983 stream
->stream()->recv_window_size());
5985 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5986 ASSERT_TRUE(response
!= NULL
);
5987 ASSERT_TRUE(response
->headers
.get() != NULL
);
5988 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5989 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5991 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5992 // size increased to default.
5993 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kTargetSize
));
5994 EXPECT_EQ(static_cast<int>(kTargetSize
),
5995 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
5996 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
),
5997 stream
->stream()->recv_window_size());
5998 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6000 // Allow scheduled WINDOW_UPDATE frames to write.
6001 base::RunLoop().RunUntilIdle();
6002 helper
.VerifyDataConsumed();
6005 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6006 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6007 // Number of full frames we hope to write (but will not, used to
6008 // set content-length header correctly)
6009 static int kFrameCount
= 3;
6011 scoped_ptr
<std::string
> content(
6012 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6013 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6014 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6015 scoped_ptr
<SpdyFrame
> body(
6016 spdy_util_
.ConstructSpdyBodyFrame(
6017 1, content
->c_str(), content
->size(), false));
6018 scoped_ptr
<SpdyFrame
> rst(
6019 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6021 // We're not going to write a data frame with FIN, we'll receive a bad
6022 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6023 MockWrite writes
[] = {
6024 CreateMockWrite(*req
, 0),
6025 CreateMockWrite(*body
, 2),
6026 CreateMockWrite(*rst
, 3),
6029 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6030 scoped_ptr
<SpdyFrame
> window_update(
6031 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6032 MockRead reads
[] = {
6033 CreateMockRead(*window_update
, 1),
6034 MockRead(ASYNC
, 0, 4) // EOF
6037 DeterministicSocketData
data(reads
, arraysize(reads
),
6038 writes
, arraysize(writes
));
6040 ScopedVector
<UploadElementReader
> element_readers
;
6041 for (int i
= 0; i
< kFrameCount
; ++i
) {
6042 element_readers
.push_back(
6043 new UploadBytesElementReader(content
->c_str(), content
->size()));
6045 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6047 // Setup the request
6048 HttpRequestInfo request
;
6049 request
.method
= "POST";
6050 request
.url
= GURL("http://www.google.com/");
6051 request
.upload_data_stream
= &upload_data_stream
;
6053 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6054 BoundNetLog(), GetParam(), NULL
);
6055 helper
.SetDeterministic();
6056 helper
.RunPreTestSetup();
6057 helper
.AddDeterministicData(&data
);
6058 HttpNetworkTransaction
* trans
= helper
.trans();
6060 TestCompletionCallback callback
;
6061 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6062 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6065 ASSERT_TRUE(callback
.have_result());
6066 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6067 helper
.VerifyDataConsumed();
6070 // Test that after hitting a send window size of 0, the write process
6071 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6073 // This test constructs a POST request followed by enough data frames
6074 // containing 'a' that would make the window size 0, followed by another
6075 // data frame containing default content (which is "hello!") and this frame
6076 // also contains a FIN flag. DelayedSocketData is used to enforce all
6077 // writes go through before a read could happen. However, the last frame
6078 // ("hello!") is not supposed to go through since by the time its turn
6079 // arrives, window size is 0. At this point MessageLoop::Run() called via
6080 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6081 // which returns after performing all possible writes. We use DCHECKS to
6082 // ensure that last data frame is still there and stream has stalled.
6083 // After that, next read is artifically enforced, which causes a
6084 // WINDOW_UPDATE to be read and I/O process resumes.
6085 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6086 // Number of frames we need to send to zero out the window size: data
6087 // frames plus SYN_STREAM plus the last data frame; also we need another
6088 // data frame that we will send once the WINDOW_UPDATE is received,
6090 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6092 // Calculate last frame's size; 0 size data frame is legal.
6093 size_t last_frame_size
=
6094 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6096 // Construct content for a data frame of maximum size.
6097 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6099 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6100 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6104 scoped_ptr
<SpdyFrame
> body1(
6105 spdy_util_
.ConstructSpdyBodyFrame(
6106 1, content
.c_str(), content
.size(), false));
6108 // Last frame to zero out the window size.
6109 scoped_ptr
<SpdyFrame
> body2(
6110 spdy_util_
.ConstructSpdyBodyFrame(
6111 1, content
.c_str(), last_frame_size
, false));
6113 // Data frame to be sent once WINDOW_UPDATE frame is received.
6114 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6116 // Fill in mock writes.
6117 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6119 writes
[i
] = CreateMockWrite(*req
);
6120 for (i
= 1; i
< num_writes
- 2; i
++)
6121 writes
[i
] = CreateMockWrite(*body1
);
6122 writes
[i
++] = CreateMockWrite(*body2
);
6123 writes
[i
] = CreateMockWrite(*body3
);
6125 // Construct read frame, give enough space to upload the rest of the
6127 scoped_ptr
<SpdyFrame
> session_window_update(
6128 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6129 scoped_ptr
<SpdyFrame
> window_update(
6130 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6131 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6132 MockRead reads
[] = {
6133 CreateMockRead(*session_window_update
),
6134 CreateMockRead(*session_window_update
),
6135 CreateMockRead(*window_update
),
6136 CreateMockRead(*window_update
),
6137 CreateMockRead(*reply
),
6138 CreateMockRead(*body2
),
6139 CreateMockRead(*body3
),
6140 MockRead(ASYNC
, 0, 0) // EOF
6143 // Skip the session window updates unless we're using SPDY/3.1 and
6145 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6146 size_t num_reads
= arraysize(reads
) - read_offset
;
6148 // Force all writes to happen before any read, last write will not
6149 // actually queue a frame, due to window size being 0.
6150 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6151 writes
.get(), num_writes
);
6153 ScopedVector
<UploadElementReader
> element_readers
;
6154 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6155 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6156 element_readers
.push_back(new UploadBytesElementReader(
6157 upload_data_string
.c_str(), upload_data_string
.size()));
6158 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6160 HttpRequestInfo request
;
6161 request
.method
= "POST";
6162 request
.url
= GURL("http://www.google.com/");
6163 request
.upload_data_stream
= &upload_data_stream
;
6164 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6165 BoundNetLog(), GetParam(), NULL
);
6166 helper
.AddData(&data
);
6167 helper
.RunPreTestSetup();
6169 HttpNetworkTransaction
* trans
= helper
.trans();
6171 TestCompletionCallback callback
;
6172 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6173 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6175 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6177 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6178 ASSERT_TRUE(stream
!= NULL
);
6179 ASSERT_TRUE(stream
->stream() != NULL
);
6180 EXPECT_EQ(0, stream
->stream()->send_window_size());
6181 // All the body data should have been read.
6182 // TODO(satorux): This is because of the weirdness in reading the request
6183 // body in OnSendBodyComplete(). See crbug.com/113107.
6184 EXPECT_TRUE(upload_data_stream
.IsEOF());
6185 // But the body is not yet fully sent (kUploadData is not yet sent)
6186 // since we're send-stalled.
6187 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6189 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6190 rv
= callback
.WaitForResult();
6191 helper
.VerifyDataConsumed();
6194 // Test we correctly handle the case where the SETTINGS frame results in
6195 // unstalling the send window.
6196 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6197 // Number of frames we need to send to zero out the window size: data
6198 // frames plus SYN_STREAM plus the last data frame; also we need another
6199 // data frame that we will send once the SETTING is received, therefore +3.
6200 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6202 // Calculate last frame's size; 0 size data frame is legal.
6203 size_t last_frame_size
=
6204 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6206 // Construct content for a data frame of maximum size.
6207 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6209 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6210 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6214 scoped_ptr
<SpdyFrame
> body1(
6215 spdy_util_
.ConstructSpdyBodyFrame(
6216 1, content
.c_str(), content
.size(), false));
6218 // Last frame to zero out the window size.
6219 scoped_ptr
<SpdyFrame
> body2(
6220 spdy_util_
.ConstructSpdyBodyFrame(
6221 1, content
.c_str(), last_frame_size
, false));
6223 // Data frame to be sent once SETTINGS frame is received.
6224 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6226 // Fill in mock reads/writes.
6227 std::vector
<MockRead
> reads
;
6228 std::vector
<MockWrite
> writes
;
6230 writes
.push_back(CreateMockWrite(*req
, i
++));
6231 while (i
< num_writes
- 2)
6232 writes
.push_back(CreateMockWrite(*body1
, i
++));
6233 writes
.push_back(CreateMockWrite(*body2
, i
++));
6235 // Construct read frame for SETTINGS that gives enough space to upload the
6236 // rest of the data.
6237 SettingsMap settings
;
6238 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6239 SettingsFlagsAndValue(
6240 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
* 2);
6241 scoped_ptr
<SpdyFrame
> settings_frame_large(
6242 spdy_util_
.ConstructSpdySettings(settings
));
6244 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6246 scoped_ptr
<SpdyFrame
> session_window_update(
6247 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6248 if (GetParam().protocol
>= kProtoSPDY31
)
6249 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6251 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6252 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6254 writes
.push_back(CreateMockWrite(*body3
, i
++));
6256 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6257 reads
.push_back(CreateMockRead(*reply
, i
++));
6258 reads
.push_back(CreateMockRead(*body2
, i
++));
6259 reads
.push_back(CreateMockRead(*body3
, i
++));
6260 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6262 // Force all writes to happen before any read, last write will not
6263 // actually queue a frame, due to window size being 0.
6264 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6265 vector_as_array(&writes
), writes
.size());
6267 ScopedVector
<UploadElementReader
> element_readers
;
6268 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6269 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6270 element_readers
.push_back(new UploadBytesElementReader(
6271 upload_data_string
.c_str(), upload_data_string
.size()));
6272 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6274 HttpRequestInfo request
;
6275 request
.method
= "POST";
6276 request
.url
= GURL("http://www.google.com/");
6277 request
.upload_data_stream
= &upload_data_stream
;
6278 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6279 BoundNetLog(), GetParam(), NULL
);
6280 helper
.SetDeterministic();
6281 helper
.RunPreTestSetup();
6282 helper
.AddDeterministicData(&data
);
6284 HttpNetworkTransaction
* trans
= helper
.trans();
6286 TestCompletionCallback callback
;
6287 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6288 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6290 data
.RunFor(num_writes
- 1); // Write as much as we can.
6292 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6293 ASSERT_TRUE(stream
!= NULL
);
6294 ASSERT_TRUE(stream
->stream() != NULL
);
6295 EXPECT_EQ(0, stream
->stream()->send_window_size());
6297 // All the body data should have been read.
6298 // TODO(satorux): This is because of the weirdness in reading the request
6299 // body in OnSendBodyComplete(). See crbug.com/113107.
6300 EXPECT_TRUE(upload_data_stream
.IsEOF());
6301 // But the body is not yet fully sent (kUploadData is not yet sent)
6302 // since we're send-stalled.
6303 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6305 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6306 rv
= callback
.WaitForResult();
6307 helper
.VerifyDataConsumed();
6308 // If stream is NULL, that means it was unstalled and closed.
6309 EXPECT_TRUE(stream
->stream() == NULL
);
6312 // Test we correctly handle the case where the SETTINGS frame results in a
6313 // negative send window size.
6314 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6315 // Number of frames we need to send to zero out the window size: data
6316 // frames plus SYN_STREAM plus the last data frame; also we need another
6317 // data frame that we will send once the SETTING is received, therefore +3.
6318 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6320 // Calculate last frame's size; 0 size data frame is legal.
6321 size_t last_frame_size
=
6322 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6324 // Construct content for a data frame of maximum size.
6325 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6327 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6328 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6332 scoped_ptr
<SpdyFrame
> body1(
6333 spdy_util_
.ConstructSpdyBodyFrame(
6334 1, content
.c_str(), content
.size(), false));
6336 // Last frame to zero out the window size.
6337 scoped_ptr
<SpdyFrame
> body2(
6338 spdy_util_
.ConstructSpdyBodyFrame(
6339 1, content
.c_str(), last_frame_size
, false));
6341 // Data frame to be sent once SETTINGS frame is received.
6342 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6344 // Fill in mock reads/writes.
6345 std::vector
<MockRead
> reads
;
6346 std::vector
<MockWrite
> writes
;
6348 writes
.push_back(CreateMockWrite(*req
, i
++));
6349 while (i
< num_writes
- 2)
6350 writes
.push_back(CreateMockWrite(*body1
, i
++));
6351 writes
.push_back(CreateMockWrite(*body2
, i
++));
6353 // Construct read frame for SETTINGS that makes the send_window_size
6355 SettingsMap new_settings
;
6356 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6357 SettingsFlagsAndValue(
6358 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
/ 2);
6359 scoped_ptr
<SpdyFrame
> settings_frame_small(
6360 spdy_util_
.ConstructSpdySettings(new_settings
));
6361 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6363 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6364 spdy_util_
.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize
));
6365 scoped_ptr
<SpdyFrame
> window_update_init_size(
6366 spdy_util_
.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize
));
6368 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6369 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6370 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6372 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6373 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6375 writes
.push_back(CreateMockWrite(*body3
, i
++));
6377 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6378 reads
.push_back(CreateMockRead(*reply
, i
++));
6379 reads
.push_back(CreateMockRead(*body2
, i
++));
6380 reads
.push_back(CreateMockRead(*body3
, i
++));
6381 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6383 // Force all writes to happen before any read, last write will not
6384 // actually queue a frame, due to window size being 0.
6385 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6386 vector_as_array(&writes
), writes
.size());
6388 ScopedVector
<UploadElementReader
> element_readers
;
6389 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6390 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6391 element_readers
.push_back(new UploadBytesElementReader(
6392 upload_data_string
.c_str(), upload_data_string
.size()));
6393 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6395 HttpRequestInfo request
;
6396 request
.method
= "POST";
6397 request
.url
= GURL("http://www.google.com/");
6398 request
.upload_data_stream
= &upload_data_stream
;
6399 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6400 BoundNetLog(), GetParam(), NULL
);
6401 helper
.SetDeterministic();
6402 helper
.RunPreTestSetup();
6403 helper
.AddDeterministicData(&data
);
6405 HttpNetworkTransaction
* trans
= helper
.trans();
6407 TestCompletionCallback callback
;
6408 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6409 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6411 data
.RunFor(num_writes
- 1); // Write as much as we can.
6413 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6414 ASSERT_TRUE(stream
!= NULL
);
6415 ASSERT_TRUE(stream
->stream() != NULL
);
6416 EXPECT_EQ(0, stream
->stream()->send_window_size());
6418 // All the body data should have been read.
6419 // TODO(satorux): This is because of the weirdness in reading the request
6420 // body in OnSendBodyComplete(). See crbug.com/113107.
6421 EXPECT_TRUE(upload_data_stream
.IsEOF());
6422 // But the body is not yet fully sent (kUploadData is not yet sent)
6423 // since we're send-stalled.
6424 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6426 // Read in WINDOW_UPDATE or SETTINGS frame.
6427 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6428 rv
= callback
.WaitForResult();
6429 helper
.VerifyDataConsumed();
6432 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnOddPushStreamId
) {
6433 if (spdy_util_
.spdy_version() < SPDY3
)
6436 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
6437 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6438 push_headers
.get());
6439 scoped_ptr
<SpdyFrame
> push(
6440 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 3, 1));
6441 MockRead reads
[] = {CreateMockRead(*push
, 1)};
6443 scoped_ptr
<SpdyFrame
> req(
6444 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6445 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6446 0, GOAWAY_PROTOCOL_ERROR
, "Odd push stream id."));
6447 MockWrite writes
[] = {
6448 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 2),
6451 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6452 NormalSpdyTransactionHelper
helper(
6453 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6454 helper
.RunToCompletion(&data
);
6455 TransactionHelperResult out
= helper
.output();
6456 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6459 TEST_P(SpdyNetworkTransactionTest
,
6460 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted
) {
6461 if (spdy_util_
.spdy_version() < SPDY3
)
6464 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
6465 NULL
, 0, 4, 1, "http://www.google.com/a.dat"));
6466 scoped_ptr
<SpdyHeaderBlock
> push_b_headers(new SpdyHeaderBlock
);
6467 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6468 push_b_headers
.get());
6469 scoped_ptr
<SpdyFrame
> push_b(
6470 spdy_util_
.ConstructInitialSpdyPushFrame(push_b_headers
.Pass(), 2, 1));
6471 MockRead reads
[] = {
6472 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
6475 scoped_ptr
<SpdyFrame
> req(
6476 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6477 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6479 GOAWAY_PROTOCOL_ERROR
,
6480 "New push stream id must be greater than the last accepted."));
6481 MockWrite writes
[] = {
6482 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
6485 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6486 NormalSpdyTransactionHelper
helper(
6487 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6488 helper
.RunToCompletion(&data
);
6489 TransactionHelperResult out
= helper
.output();
6490 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6493 class SpdyNetworkTransactionNoTLSUsageCheckTest
6494 : public SpdyNetworkTransactionTest
{
6496 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6497 // Construct the request.
6498 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyGet(
6499 "https://www.google.com/", false, 1, LOWEST
));
6500 MockWrite writes
[] = {CreateMockWrite(*req
)};
6502 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6503 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6504 MockRead reads
[] = {
6505 CreateMockRead(*resp
), CreateMockRead(*body
),
6506 MockRead(ASYNC
, 0, 0) // EOF
6509 DelayedSocketData
data(
6510 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6511 HttpRequestInfo request
;
6512 request
.method
= "GET";
6513 request
.url
= GURL("https://www.google.com/");
6514 NormalSpdyTransactionHelper
helper(
6515 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6516 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6517 TransactionHelperResult out
= helper
.output();
6518 EXPECT_EQ(OK
, out
.rv
);
6519 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6520 EXPECT_EQ("hello!", out
.response_data
);
6524 //-----------------------------------------------------------------------------
6525 // All tests are run with three different connection types: SPDY after NPN
6526 // negotiation, SPDY without SSL, and SPDY with SSL.
6528 // TODO(akalin): Use ::testing::Combine() when we are able to use
6530 INSTANTIATE_TEST_CASE_P(
6532 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6533 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
)));
6535 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6536 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6537 new SSLSocketDataProvider(ASYNC
, OK
));
6538 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6539 &ssl_provider
->connection_status
);
6541 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6544 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6545 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6546 new SSLSocketDataProvider(ASYNC
, OK
));
6547 // Set to TLS_RSA_WITH_NULL_MD5
6548 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6550 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6553 class SpdyNetworkTransactionTLSUsageCheckTest
6554 : public SpdyNetworkTransactionTest
{
6556 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6557 scoped_ptr
<SpdyFrame
> goaway(
6558 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6559 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6561 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6562 HttpRequestInfo request
;
6563 request
.method
= "GET";
6564 request
.url
= GURL("https://www.google.com/");
6565 NormalSpdyTransactionHelper
helper(
6566 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6567 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6568 TransactionHelperResult out
= helper
.output();
6569 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6573 INSTANTIATE_TEST_CASE_P(
6575 SpdyNetworkTransactionTLSUsageCheckTest
,
6577 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
6578 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNPN
)));
6580 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6581 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6582 new SSLSocketDataProvider(ASYNC
, OK
));
6583 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6584 &ssl_provider
->connection_status
);
6586 RunTLSUsageCheckTest(ssl_provider
.Pass());
6589 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6590 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6591 new SSLSocketDataProvider(ASYNC
, OK
));
6592 // Set to TLS_RSA_WITH_NULL_MD5
6593 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6595 RunTLSUsageCheckTest(ssl_provider
.Pass());