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(kProtoSPDY3
),
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 virtual void SetUp() {
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(kProtoDeprecatedSPDY2
, SPDYNOSSL
),
721 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
, SPDYSSL
),
722 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
, SPDYNPN
),
723 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNOSSL
),
724 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYSSL
),
725 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNPN
),
726 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNOSSL
),
727 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYSSL
),
728 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
),
729 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNOSSL
),
730 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYSSL
),
731 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNPN
)));
733 // Verify HttpNetworkTransaction constructor.
734 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
735 scoped_ptr
<SpdySessionDependencies
> session_deps(
736 CreateSpdySessionDependencies(GetParam()));
737 scoped_refptr
<HttpNetworkSession
> session(
738 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
739 scoped_ptr
<HttpTransaction
> trans(
740 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
743 TEST_P(SpdyNetworkTransactionTest
, Get
) {
744 // Construct the request.
745 scoped_ptr
<SpdyFrame
> req(
746 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
747 MockWrite writes
[] = { CreateMockWrite(*req
) };
749 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
750 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
752 CreateMockRead(*resp
),
753 CreateMockRead(*body
),
754 MockRead(ASYNC
, 0, 0) // EOF
757 DelayedSocketData
data(1, reads
, arraysize(reads
),
758 writes
, arraysize(writes
));
759 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
760 BoundNetLog(), GetParam(), NULL
);
761 helper
.RunToCompletion(&data
);
762 TransactionHelperResult out
= helper
.output();
763 EXPECT_EQ(OK
, out
.rv
);
764 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
765 EXPECT_EQ("hello!", out
.response_data
);
768 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
769 for (RequestPriority p
= MINIMUM_PRIORITY
; p
<= MAXIMUM_PRIORITY
;
770 p
= RequestPriority(p
+ 1)) {
771 // Construct the request.
772 scoped_ptr
<SpdyFrame
> req(
773 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
774 MockWrite writes
[] = { CreateMockWrite(*req
) };
776 SpdyPriority spdy_prio
= 0;
777 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
778 // this repeats the RequestPriority-->SpdyPriority mapping from
779 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
780 // sure it's being done right.
781 if (spdy_util_
.spdy_version() < SPDY3
) {
784 EXPECT_EQ(0, spdy_prio
);
787 EXPECT_EQ(1, spdy_prio
);
791 EXPECT_EQ(2, spdy_prio
);
794 EXPECT_EQ(3, spdy_prio
);
802 EXPECT_EQ(0, spdy_prio
);
805 EXPECT_EQ(1, spdy_prio
);
808 EXPECT_EQ(2, spdy_prio
);
811 EXPECT_EQ(3, spdy_prio
);
814 EXPECT_EQ(4, spdy_prio
);
821 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
822 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
824 CreateMockRead(*resp
),
825 CreateMockRead(*body
),
826 MockRead(ASYNC
, 0, 0) // EOF
829 DelayedSocketData
data(1, reads
, arraysize(reads
),
830 writes
, arraysize(writes
));
831 HttpRequestInfo http_req
= CreateGetRequest();
833 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
835 helper
.RunToCompletion(&data
);
836 TransactionHelperResult out
= helper
.output();
837 EXPECT_EQ(OK
, out
.rv
);
838 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
839 EXPECT_EQ("hello!", out
.response_data
);
843 // Start three gets simultaniously; making sure that multiplexed
844 // streams work properly.
846 // This can't use the TransactionHelper method, since it only
847 // handles a single transaction, and finishes them as soon
848 // as it launches them.
850 // TODO(gavinp): create a working generalized TransactionHelper that
851 // can allow multiple streams in flight.
853 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
854 scoped_ptr
<SpdyFrame
> req(
855 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
856 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
857 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
858 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
860 scoped_ptr
<SpdyFrame
> req2(
861 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
862 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
863 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
864 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
866 scoped_ptr
<SpdyFrame
> req3(
867 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
868 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
869 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
870 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
872 MockWrite writes
[] = {
873 CreateMockWrite(*req
),
874 CreateMockWrite(*req2
),
875 CreateMockWrite(*req3
),
878 CreateMockRead(*resp
, 1),
879 CreateMockRead(*body
),
880 CreateMockRead(*resp2
, 4),
881 CreateMockRead(*body2
),
882 CreateMockRead(*resp3
, 7),
883 CreateMockRead(*body3
),
885 CreateMockRead(*fbody
),
886 CreateMockRead(*fbody2
),
887 CreateMockRead(*fbody3
),
889 MockRead(ASYNC
, 0, 0), // EOF
891 OrderedSocketData
data(reads
, arraysize(reads
),
892 writes
, arraysize(writes
));
893 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
896 TransactionHelperResult out
;
897 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
898 BoundNetLog(), GetParam(), NULL
);
899 helper
.RunPreTestSetup();
900 helper
.AddData(&data
);
901 // We require placeholder data because three get requests are sent out, so
902 // there needs to be three sets of SSL connection data.
903 helper
.AddData(&data_placeholder
);
904 helper
.AddData(&data_placeholder
);
905 scoped_ptr
<HttpNetworkTransaction
> trans1(
906 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
907 scoped_ptr
<HttpNetworkTransaction
> trans2(
908 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
909 scoped_ptr
<HttpNetworkTransaction
> trans3(
910 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
912 TestCompletionCallback callback1
;
913 TestCompletionCallback callback2
;
914 TestCompletionCallback callback3
;
916 HttpRequestInfo httpreq1
= CreateGetRequest();
917 HttpRequestInfo httpreq2
= CreateGetRequest();
918 HttpRequestInfo httpreq3
= CreateGetRequest();
920 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
921 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
922 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
923 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
924 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
925 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
927 out
.rv
= callback1
.WaitForResult();
928 ASSERT_EQ(OK
, out
.rv
);
929 out
.rv
= callback3
.WaitForResult();
930 ASSERT_EQ(OK
, out
.rv
);
932 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
933 EXPECT_TRUE(response1
->headers
.get() != NULL
);
934 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
935 out
.status_line
= response1
->headers
->GetStatusLine();
936 out
.response_info
= *response1
;
938 trans2
->GetResponseInfo();
940 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
941 helper
.VerifyDataConsumed();
942 EXPECT_EQ(OK
, out
.rv
);
944 EXPECT_EQ(OK
, out
.rv
);
945 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
946 EXPECT_EQ("hello!hello!", out
.response_data
);
949 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
950 scoped_ptr
<SpdyFrame
> req(
951 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
952 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
953 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
954 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
956 scoped_ptr
<SpdyFrame
> req2(
957 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
958 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
959 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
960 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
962 MockWrite writes
[] = {
963 CreateMockWrite(*req
),
964 CreateMockWrite(*req2
),
967 CreateMockRead(*resp
, 1),
968 CreateMockRead(*body
),
969 CreateMockRead(*resp2
, 4),
970 CreateMockRead(*body2
),
971 CreateMockRead(*fbody
),
972 CreateMockRead(*fbody2
),
973 MockRead(ASYNC
, 0, 0), // EOF
975 OrderedSocketData
data(reads
, arraysize(reads
),
976 writes
, arraysize(writes
));
978 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
980 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
981 data_placeholder
.set_connect_data(never_finishing_connect
);
984 TransactionHelperResult out
;
985 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
986 BoundNetLog(), GetParam(), NULL
);
987 helper
.RunPreTestSetup();
988 helper
.AddData(&data
);
989 // We require placeholder data because two get requests are sent out, so
990 // there needs to be two sets of SSL connection data.
991 helper
.AddData(&data_placeholder
);
992 scoped_ptr
<HttpNetworkTransaction
> trans1(
993 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
994 scoped_ptr
<HttpNetworkTransaction
> trans2(
995 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
997 TestCompletionCallback callback1
;
998 TestCompletionCallback callback2
;
1000 HttpRequestInfo httpreq1
= CreateGetRequest();
1001 HttpRequestInfo httpreq2
= CreateGetRequest();
1003 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1004 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1005 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1006 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1008 out
.rv
= callback1
.WaitForResult();
1009 ASSERT_EQ(OK
, out
.rv
);
1010 out
.rv
= callback2
.WaitForResult();
1011 ASSERT_EQ(OK
, out
.rv
);
1013 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1014 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1015 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1016 out
.status_line
= response1
->headers
->GetStatusLine();
1017 out
.response_info
= *response1
;
1018 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1019 EXPECT_EQ(OK
, out
.rv
);
1020 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1021 EXPECT_EQ("hello!hello!", out
.response_data
);
1023 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1024 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1025 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1026 out
.status_line
= response2
->headers
->GetStatusLine();
1027 out
.response_info
= *response2
;
1028 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1029 EXPECT_EQ(OK
, out
.rv
);
1030 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1031 EXPECT_EQ("hello!hello!", out
.response_data
);
1033 helper
.VerifyDataConsumed();
1036 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
1037 scoped_ptr
<SpdyFrame
> req(
1038 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1039 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1040 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1041 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1043 scoped_ptr
<SpdyFrame
> req2(
1044 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1045 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1046 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1047 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1049 MockWrite writes
[] = {
1050 CreateMockWrite(*req
),
1051 CreateMockWrite(*req2
),
1053 MockRead reads
[] = {
1054 CreateMockRead(*resp
, 1),
1055 CreateMockRead(*body
),
1056 CreateMockRead(*resp2
, 4),
1057 CreateMockRead(*body2
),
1058 CreateMockRead(*fbody
),
1059 CreateMockRead(*fbody2
),
1060 MockRead(ASYNC
, 0, 0), // EOF
1062 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
1063 writes
, arraysize(writes
));
1065 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1067 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1068 data_placeholder
.set_connect_data(never_finishing_connect
);
1071 TransactionHelperResult out
;
1072 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1073 BoundNetLog(), GetParam(), NULL
);
1074 helper
.RunPreTestSetup();
1075 helper
.AddData(&preconnect_data
);
1076 // We require placeholder data because 3 connections are attempted (first is
1077 // the preconnect, 2nd and 3rd are the never finished connections.
1078 helper
.AddData(&data_placeholder
);
1079 helper
.AddData(&data_placeholder
);
1081 scoped_ptr
<HttpNetworkTransaction
> trans1(
1082 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1083 scoped_ptr
<HttpNetworkTransaction
> trans2(
1084 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1086 TestCompletionCallback callback1
;
1087 TestCompletionCallback callback2
;
1089 HttpRequestInfo httpreq
= CreateGetRequest();
1091 // Preconnect the first.
1092 SSLConfig preconnect_ssl_config
;
1093 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1094 HttpStreamFactory
* http_stream_factory
=
1095 helper
.session()->http_stream_factory();
1096 helper
.session()->GetNextProtos(&preconnect_ssl_config
.next_protos
);
1098 http_stream_factory
->PreconnectStreams(
1099 1, httpreq
, DEFAULT_PRIORITY
,
1100 preconnect_ssl_config
, preconnect_ssl_config
);
1102 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1103 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1104 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1105 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1107 out
.rv
= callback1
.WaitForResult();
1108 ASSERT_EQ(OK
, out
.rv
);
1109 out
.rv
= callback2
.WaitForResult();
1110 ASSERT_EQ(OK
, out
.rv
);
1112 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1113 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1114 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1115 out
.status_line
= response1
->headers
->GetStatusLine();
1116 out
.response_info
= *response1
;
1117 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1118 EXPECT_EQ(OK
, out
.rv
);
1119 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1120 EXPECT_EQ("hello!hello!", out
.response_data
);
1122 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1123 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1124 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1125 out
.status_line
= response2
->headers
->GetStatusLine();
1126 out
.response_info
= *response2
;
1127 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1128 EXPECT_EQ(OK
, out
.rv
);
1129 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1130 EXPECT_EQ("hello!hello!", out
.response_data
);
1132 helper
.VerifyDataConsumed();
1135 // Similar to ThreeGets above, however this test adds a SETTINGS
1136 // frame. The SETTINGS frame is read during the IO loop waiting on
1137 // the first transaction completion, and sets a maximum concurrent
1138 // stream limit of 1. This means that our IO loop exists after the
1139 // second transaction completes, so we can assert on read_index().
1140 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1141 // Construct the request.
1142 scoped_ptr
<SpdyFrame
> req(
1143 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1144 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1145 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1146 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1148 scoped_ptr
<SpdyFrame
> req2(
1149 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1150 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1151 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1152 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1154 scoped_ptr
<SpdyFrame
> req3(
1155 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1156 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1157 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1158 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1160 SettingsMap settings
;
1161 const uint32 max_concurrent_streams
= 1;
1162 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1163 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1164 scoped_ptr
<SpdyFrame
> settings_frame(
1165 spdy_util_
.ConstructSpdySettings(settings
));
1166 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1168 MockWrite writes
[] = {
1169 CreateMockWrite(*req
),
1170 CreateMockWrite(*settings_ack
, 2),
1171 CreateMockWrite(*req2
),
1172 CreateMockWrite(*req3
),
1175 MockRead reads
[] = {
1176 CreateMockRead(*settings_frame
, 1),
1177 CreateMockRead(*resp
),
1178 CreateMockRead(*body
),
1179 CreateMockRead(*fbody
),
1180 CreateMockRead(*resp2
, 8),
1181 CreateMockRead(*body2
),
1182 CreateMockRead(*fbody2
),
1183 CreateMockRead(*resp3
, 13),
1184 CreateMockRead(*body3
),
1185 CreateMockRead(*fbody3
),
1187 MockRead(ASYNC
, 0, 0), // EOF
1190 OrderedSocketData
data(reads
, arraysize(reads
),
1191 writes
, arraysize(writes
));
1192 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1195 TransactionHelperResult out
;
1197 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1198 BoundNetLog(), GetParam(), NULL
);
1199 helper
.RunPreTestSetup();
1200 helper
.AddData(&data
);
1201 // We require placeholder data because three get requests are sent out, so
1202 // there needs to be three sets of SSL connection data.
1203 helper
.AddData(&data_placeholder
);
1204 helper
.AddData(&data_placeholder
);
1205 scoped_ptr
<HttpNetworkTransaction
> trans1(
1206 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1207 scoped_ptr
<HttpNetworkTransaction
> trans2(
1208 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1209 scoped_ptr
<HttpNetworkTransaction
> trans3(
1210 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1212 TestCompletionCallback callback1
;
1213 TestCompletionCallback callback2
;
1214 TestCompletionCallback callback3
;
1216 HttpRequestInfo httpreq1
= CreateGetRequest();
1217 HttpRequestInfo httpreq2
= CreateGetRequest();
1218 HttpRequestInfo httpreq3
= CreateGetRequest();
1220 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1221 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1222 // Run transaction 1 through quickly to force a read of our SETTINGS
1224 out
.rv
= callback1
.WaitForResult();
1225 ASSERT_EQ(OK
, out
.rv
);
1227 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1228 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1229 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1230 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1231 out
.rv
= callback2
.WaitForResult();
1232 ASSERT_EQ(OK
, out
.rv
);
1233 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1235 out
.rv
= callback3
.WaitForResult();
1236 ASSERT_EQ(OK
, out
.rv
);
1238 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1239 ASSERT_TRUE(response1
!= NULL
);
1240 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1241 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1242 out
.status_line
= response1
->headers
->GetStatusLine();
1243 out
.response_info
= *response1
;
1244 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1245 EXPECT_EQ(OK
, out
.rv
);
1246 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1247 EXPECT_EQ("hello!hello!", out
.response_data
);
1249 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1250 out
.status_line
= response2
->headers
->GetStatusLine();
1251 out
.response_info
= *response2
;
1252 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1253 EXPECT_EQ(OK
, out
.rv
);
1254 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1255 EXPECT_EQ("hello!hello!", out
.response_data
);
1257 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1258 out
.status_line
= response3
->headers
->GetStatusLine();
1259 out
.response_info
= *response3
;
1260 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1261 EXPECT_EQ(OK
, out
.rv
);
1262 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1263 EXPECT_EQ("hello!hello!", out
.response_data
);
1265 helper
.VerifyDataConsumed();
1267 EXPECT_EQ(OK
, out
.rv
);
1270 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1271 // a fourth transaction. The third and fourth transactions have
1272 // different data ("hello!" vs "hello!hello!") and because of the
1273 // user specified priority, we expect to see them inverted in
1274 // the response from the server.
1275 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1276 // Construct the request.
1277 scoped_ptr
<SpdyFrame
> req(
1278 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1279 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1280 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1281 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1283 scoped_ptr
<SpdyFrame
> req2(
1284 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1285 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1286 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1287 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1289 scoped_ptr
<SpdyFrame
> req4(
1290 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1291 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1292 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1294 scoped_ptr
<SpdyFrame
> req3(
1295 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1296 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1297 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1298 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1300 SettingsMap settings
;
1301 const uint32 max_concurrent_streams
= 1;
1302 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1303 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1304 scoped_ptr
<SpdyFrame
> settings_frame(
1305 spdy_util_
.ConstructSpdySettings(settings
));
1306 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1308 MockWrite writes
[] = { CreateMockWrite(*req
),
1309 CreateMockWrite(*settings_ack
, 2),
1310 CreateMockWrite(*req2
),
1311 CreateMockWrite(*req4
),
1312 CreateMockWrite(*req3
),
1314 MockRead reads
[] = {
1315 CreateMockRead(*settings_frame
, 1),
1316 CreateMockRead(*resp
),
1317 CreateMockRead(*body
),
1318 CreateMockRead(*fbody
),
1319 CreateMockRead(*resp2
, 8),
1320 CreateMockRead(*body2
),
1321 CreateMockRead(*fbody2
),
1322 CreateMockRead(*resp4
, 14),
1323 CreateMockRead(*fbody4
),
1324 CreateMockRead(*resp3
, 17),
1325 CreateMockRead(*body3
),
1326 CreateMockRead(*fbody3
),
1328 MockRead(ASYNC
, 0, 0), // EOF
1331 OrderedSocketData
data(reads
, arraysize(reads
),
1332 writes
, arraysize(writes
));
1333 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1336 TransactionHelperResult out
;
1337 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1338 BoundNetLog(), GetParam(), NULL
);
1339 helper
.RunPreTestSetup();
1340 helper
.AddData(&data
);
1341 // We require placeholder data because four get requests are sent out, so
1342 // there needs to be four sets of SSL connection data.
1343 helper
.AddData(&data_placeholder
);
1344 helper
.AddData(&data_placeholder
);
1345 helper
.AddData(&data_placeholder
);
1346 scoped_ptr
<HttpNetworkTransaction
> trans1(
1347 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1348 scoped_ptr
<HttpNetworkTransaction
> trans2(
1349 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1350 scoped_ptr
<HttpNetworkTransaction
> trans3(
1351 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1352 scoped_ptr
<HttpNetworkTransaction
> trans4(
1353 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1355 TestCompletionCallback callback1
;
1356 TestCompletionCallback callback2
;
1357 TestCompletionCallback callback3
;
1358 TestCompletionCallback callback4
;
1360 HttpRequestInfo httpreq1
= CreateGetRequest();
1361 HttpRequestInfo httpreq2
= CreateGetRequest();
1362 HttpRequestInfo httpreq3
= CreateGetRequest();
1363 HttpRequestInfo httpreq4
= CreateGetRequest();
1365 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1366 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1367 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1368 out
.rv
= callback1
.WaitForResult();
1369 ASSERT_EQ(OK
, out
.rv
);
1371 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1372 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1373 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1374 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1375 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1376 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1378 out
.rv
= callback2
.WaitForResult();
1379 ASSERT_EQ(OK
, out
.rv
);
1380 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1382 out
.rv
= callback3
.WaitForResult();
1383 ASSERT_EQ(OK
, out
.rv
);
1385 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1386 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1387 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1388 out
.status_line
= response1
->headers
->GetStatusLine();
1389 out
.response_info
= *response1
;
1390 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1391 EXPECT_EQ(OK
, out
.rv
);
1392 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1393 EXPECT_EQ("hello!hello!", out
.response_data
);
1395 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1396 out
.status_line
= response2
->headers
->GetStatusLine();
1397 out
.response_info
= *response2
;
1398 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1399 EXPECT_EQ(OK
, out
.rv
);
1400 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1401 EXPECT_EQ("hello!hello!", out
.response_data
);
1403 // notice: response3 gets two hellos, response4 gets one
1404 // hello, so we know dequeuing priority was respected.
1405 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1406 out
.status_line
= response3
->headers
->GetStatusLine();
1407 out
.response_info
= *response3
;
1408 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1409 EXPECT_EQ(OK
, out
.rv
);
1410 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1411 EXPECT_EQ("hello!hello!", out
.response_data
);
1413 out
.rv
= callback4
.WaitForResult();
1414 EXPECT_EQ(OK
, out
.rv
);
1415 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1416 out
.status_line
= response4
->headers
->GetStatusLine();
1417 out
.response_info
= *response4
;
1418 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1419 EXPECT_EQ(OK
, out
.rv
);
1420 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1421 EXPECT_EQ("hello!", out
.response_data
);
1422 helper
.VerifyDataConsumed();
1423 EXPECT_EQ(OK
, out
.rv
);
1426 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1427 // deletes a session in the middle of the transaction to insure
1428 // that we properly remove pendingcreatestream objects from
1430 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1431 // Construct the request.
1432 scoped_ptr
<SpdyFrame
> req(
1433 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1434 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1435 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1436 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1438 scoped_ptr
<SpdyFrame
> req2(
1439 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1440 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1441 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1442 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1444 SettingsMap settings
;
1445 const uint32 max_concurrent_streams
= 1;
1446 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1447 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1448 scoped_ptr
<SpdyFrame
> settings_frame(
1449 spdy_util_
.ConstructSpdySettings(settings
));
1450 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1452 MockWrite writes
[] = {
1453 CreateMockWrite(*req
),
1454 CreateMockWrite(*settings_ack
, 2),
1455 CreateMockWrite(*req2
),
1457 MockRead reads
[] = {
1458 CreateMockRead(*settings_frame
, 1),
1459 CreateMockRead(*resp
),
1460 CreateMockRead(*body
),
1461 CreateMockRead(*fbody
),
1462 CreateMockRead(*resp2
, 8),
1463 CreateMockRead(*body2
),
1464 CreateMockRead(*fbody2
),
1465 MockRead(ASYNC
, 0, 0), // EOF
1468 OrderedSocketData
data(reads
, arraysize(reads
),
1469 writes
, arraysize(writes
));
1470 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1473 TransactionHelperResult out
;
1474 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1475 BoundNetLog(), GetParam(), NULL
);
1476 helper
.RunPreTestSetup();
1477 helper
.AddData(&data
);
1478 // We require placeholder data because three get requests are sent out, so
1479 // there needs to be three sets of SSL connection data.
1480 helper
.AddData(&data_placeholder
);
1481 helper
.AddData(&data_placeholder
);
1482 scoped_ptr
<HttpNetworkTransaction
> trans1(
1483 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1484 scoped_ptr
<HttpNetworkTransaction
> trans2(
1485 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1486 scoped_ptr
<HttpNetworkTransaction
> trans3(
1487 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1489 TestCompletionCallback callback1
;
1490 TestCompletionCallback callback2
;
1491 TestCompletionCallback callback3
;
1493 HttpRequestInfo httpreq1
= CreateGetRequest();
1494 HttpRequestInfo httpreq2
= CreateGetRequest();
1495 HttpRequestInfo httpreq3
= CreateGetRequest();
1497 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1498 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1499 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1500 out
.rv
= callback1
.WaitForResult();
1501 ASSERT_EQ(OK
, out
.rv
);
1503 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1504 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1505 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1506 delete trans3
.release();
1507 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1508 out
.rv
= callback2
.WaitForResult();
1509 ASSERT_EQ(OK
, out
.rv
);
1511 EXPECT_EQ(8U, data
.read_index());
1513 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1514 ASSERT_TRUE(response1
!= NULL
);
1515 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1516 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1517 out
.status_line
= response1
->headers
->GetStatusLine();
1518 out
.response_info
= *response1
;
1519 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1520 EXPECT_EQ(OK
, out
.rv
);
1521 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1522 EXPECT_EQ("hello!hello!", out
.response_data
);
1524 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1525 ASSERT_TRUE(response2
!= NULL
);
1526 out
.status_line
= response2
->headers
->GetStatusLine();
1527 out
.response_info
= *response2
;
1528 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1529 EXPECT_EQ(OK
, out
.rv
);
1530 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1531 EXPECT_EQ("hello!hello!", out
.response_data
);
1532 helper
.VerifyDataConsumed();
1533 EXPECT_EQ(OK
, out
.rv
);
1538 // The KillerCallback will delete the transaction on error as part of the
1540 class KillerCallback
: public TestCompletionCallbackBase
{
1542 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1543 : transaction_(transaction
),
1544 callback_(base::Bind(&KillerCallback::OnComplete
,
1545 base::Unretained(this))) {
1548 ~KillerCallback() override
{}
1550 const CompletionCallback
& callback() const { return callback_
; }
1553 void OnComplete(int result
) {
1555 delete transaction_
;
1560 HttpNetworkTransaction
* transaction_
;
1561 CompletionCallback callback_
;
1566 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1567 // closes the socket while we have a pending transaction waiting for
1568 // a pending stream creation. http://crbug.com/52901
1569 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1570 // Construct the request.
1571 scoped_ptr
<SpdyFrame
> req(
1572 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1573 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1574 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1575 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1577 scoped_ptr
<SpdyFrame
> req2(
1578 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1579 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1581 SettingsMap settings
;
1582 const uint32 max_concurrent_streams
= 1;
1583 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1584 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1585 scoped_ptr
<SpdyFrame
> settings_frame(
1586 spdy_util_
.ConstructSpdySettings(settings
));
1587 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1589 MockWrite writes
[] = {
1590 CreateMockWrite(*req
),
1591 CreateMockWrite(*settings_ack
, 2),
1592 CreateMockWrite(*req2
),
1594 MockRead reads
[] = {
1595 CreateMockRead(*settings_frame
, 1),
1596 CreateMockRead(*resp
),
1597 CreateMockRead(*body
),
1598 CreateMockRead(*fin_body
),
1599 CreateMockRead(*resp2
, 8),
1600 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1603 OrderedSocketData
data(reads
, arraysize(reads
),
1604 writes
, arraysize(writes
));
1605 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1608 TransactionHelperResult out
;
1609 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1610 BoundNetLog(), GetParam(), NULL
);
1611 helper
.RunPreTestSetup();
1612 helper
.AddData(&data
);
1613 // We require placeholder data because three get requests are sent out, so
1614 // there needs to be three sets of SSL connection data.
1615 helper
.AddData(&data_placeholder
);
1616 helper
.AddData(&data_placeholder
);
1617 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1618 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1619 HttpNetworkTransaction
* trans3(
1620 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1622 TestCompletionCallback callback1
;
1623 TestCompletionCallback callback2
;
1624 KillerCallback
callback3(trans3
);
1626 HttpRequestInfo httpreq1
= CreateGetRequest();
1627 HttpRequestInfo httpreq2
= CreateGetRequest();
1628 HttpRequestInfo httpreq3
= CreateGetRequest();
1630 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1631 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1632 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1633 out
.rv
= callback1
.WaitForResult();
1634 ASSERT_EQ(OK
, out
.rv
);
1636 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1637 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1638 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1639 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1640 out
.rv
= callback3
.WaitForResult();
1641 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1643 EXPECT_EQ(6U, data
.read_index());
1645 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1646 ASSERT_TRUE(response1
!= NULL
);
1647 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1648 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1649 out
.status_line
= response1
->headers
->GetStatusLine();
1650 out
.response_info
= *response1
;
1651 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1652 EXPECT_EQ(OK
, out
.rv
);
1654 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1655 ASSERT_TRUE(response2
!= NULL
);
1656 out
.status_line
= response2
->headers
->GetStatusLine();
1657 out
.response_info
= *response2
;
1658 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1659 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1661 helper
.VerifyDataConsumed();
1664 // Test that a simple PUT request works.
1665 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1666 // Setup the request
1667 HttpRequestInfo request
;
1668 request
.method
= "PUT";
1669 request
.url
= GURL("http://www.google.com/");
1671 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1672 spdy_util_
.ConstructPutHeaderBlock("http://www.google.com", 0));
1673 scoped_ptr
<SpdyFrame
> req(
1674 spdy_util_
.ConstructSpdySyn(1, *put_headers
, LOWEST
, false, true));
1675 MockWrite writes
[] = {
1676 CreateMockWrite(*req
),
1679 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1680 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1681 MockRead reads
[] = {
1682 CreateMockRead(*resp
),
1683 CreateMockRead(*body
),
1684 MockRead(ASYNC
, 0, 0) // EOF
1687 DelayedSocketData
data(1, reads
, arraysize(reads
),
1688 writes
, arraysize(writes
));
1689 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1690 BoundNetLog(), GetParam(), NULL
);
1691 helper
.RunToCompletion(&data
);
1692 TransactionHelperResult out
= helper
.output();
1694 EXPECT_EQ(OK
, out
.rv
);
1695 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1698 // Test that a simple HEAD request works.
1699 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1700 // Setup the request
1701 HttpRequestInfo request
;
1702 request
.method
= "HEAD";
1703 request
.url
= GURL("http://www.google.com/");
1705 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1706 spdy_util_
.ConstructHeadHeaderBlock("http://www.google.com", 0));
1707 scoped_ptr
<SpdyFrame
> req(
1708 spdy_util_
.ConstructSpdySyn(1, *head_headers
, LOWEST
, false, true));
1709 MockWrite writes
[] = {
1710 CreateMockWrite(*req
),
1713 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1714 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1715 MockRead reads
[] = {
1716 CreateMockRead(*resp
),
1717 CreateMockRead(*body
),
1718 MockRead(ASYNC
, 0, 0) // EOF
1721 DelayedSocketData
data(1, reads
, arraysize(reads
),
1722 writes
, arraysize(writes
));
1723 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1724 BoundNetLog(), GetParam(), NULL
);
1725 helper
.RunToCompletion(&data
);
1726 TransactionHelperResult out
= helper
.output();
1728 EXPECT_EQ(OK
, out
.rv
);
1729 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1732 // Test that a simple POST works.
1733 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1734 scoped_ptr
<SpdyFrame
> req(
1735 spdy_util_
.ConstructSpdyPost(
1736 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1737 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1738 MockWrite writes
[] = {
1739 CreateMockWrite(*req
),
1740 CreateMockWrite(*body
), // POST upload frame
1743 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1744 MockRead reads
[] = {
1745 CreateMockRead(*resp
),
1746 CreateMockRead(*body
),
1747 MockRead(ASYNC
, 0, 0) // EOF
1750 DelayedSocketData
data(2, reads
, arraysize(reads
),
1751 writes
, arraysize(writes
));
1752 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
1753 BoundNetLog(), GetParam(), NULL
);
1754 helper
.RunToCompletion(&data
);
1755 TransactionHelperResult out
= helper
.output();
1756 EXPECT_EQ(OK
, out
.rv
);
1757 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1758 EXPECT_EQ("hello!", out
.response_data
);
1761 // Test that a POST with a file works.
1762 TEST_P(SpdyNetworkTransactionTest
, FilePost
) {
1763 scoped_ptr
<SpdyFrame
> req(
1764 spdy_util_
.ConstructSpdyPost(
1765 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1766 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1767 MockWrite writes
[] = {
1768 CreateMockWrite(*req
),
1769 CreateMockWrite(*body
), // POST upload frame
1772 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1773 MockRead reads
[] = {
1774 CreateMockRead(*resp
),
1775 CreateMockRead(*body
),
1776 MockRead(ASYNC
, 0, 0) // EOF
1779 DelayedSocketData
data(2, reads
, arraysize(reads
),
1780 writes
, arraysize(writes
));
1781 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(), DEFAULT_PRIORITY
,
1782 BoundNetLog(), GetParam(), NULL
);
1783 helper
.RunToCompletion(&data
);
1784 TransactionHelperResult out
= helper
.output();
1785 EXPECT_EQ(OK
, out
.rv
);
1786 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1787 EXPECT_EQ("hello!", out
.response_data
);
1790 // Test that a POST with a unreadable file fails.
1791 TEST_P(SpdyNetworkTransactionTest
, UnreadableFilePost
) {
1792 MockWrite writes
[] = {
1793 MockWrite(ASYNC
, 0, 0) // EOF
1795 MockRead reads
[] = {
1796 MockRead(ASYNC
, 0, 0) // EOF
1799 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1800 NormalSpdyTransactionHelper
helper(CreateUnreadableFilePostRequest(),
1802 BoundNetLog(), GetParam(), NULL
);
1803 helper
.RunPreTestSetup();
1804 helper
.AddData(&data
);
1805 helper
.RunDefaultTest();
1807 base::RunLoop().RunUntilIdle();
1808 helper
.VerifyDataNotConsumed();
1809 EXPECT_EQ(ERR_ACCESS_DENIED
, helper
.output().rv
);
1812 // Test that a complex POST works.
1813 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1814 scoped_ptr
<SpdyFrame
> req(
1815 spdy_util_
.ConstructSpdyPost(
1816 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1817 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1818 MockWrite writes
[] = {
1819 CreateMockWrite(*req
),
1820 CreateMockWrite(*body
), // POST upload frame
1823 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1824 MockRead reads
[] = {
1825 CreateMockRead(*resp
),
1826 CreateMockRead(*body
),
1827 MockRead(ASYNC
, 0, 0) // EOF
1830 DelayedSocketData
data(2, reads
, arraysize(reads
),
1831 writes
, arraysize(writes
));
1832 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1834 BoundNetLog(), GetParam(), NULL
);
1835 helper
.RunToCompletion(&data
);
1836 TransactionHelperResult out
= helper
.output();
1837 EXPECT_EQ(OK
, out
.rv
);
1838 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1839 EXPECT_EQ("hello!", out
.response_data
);
1842 // Test that a chunked POST works.
1843 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1844 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1845 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1846 MockWrite writes
[] = {
1847 CreateMockWrite(*req
),
1848 CreateMockWrite(*body
),
1851 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1852 MockRead reads
[] = {
1853 CreateMockRead(*resp
),
1854 CreateMockRead(*body
),
1855 MockRead(ASYNC
, 0, 0) // EOF
1858 DelayedSocketData
data(2, reads
, arraysize(reads
),
1859 writes
, arraysize(writes
));
1860 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1862 BoundNetLog(), GetParam(), NULL
);
1864 // These chunks get merged into a single frame when being sent.
1865 const int kFirstChunkSize
= kUploadDataSize
/2;
1866 upload_chunked_data_stream()->AppendData(kUploadData
, kFirstChunkSize
, false);
1867 upload_chunked_data_stream()->AppendData(
1868 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1870 helper
.RunToCompletion(&data
);
1871 TransactionHelperResult out
= helper
.output();
1872 EXPECT_EQ(OK
, out
.rv
);
1873 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1874 EXPECT_EQ(kUploadData
, out
.response_data
);
1877 // Test that a chunked POST works with chunks appended after transaction starts.
1878 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1879 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1880 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1881 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1882 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1883 MockWrite writes
[] = {
1884 CreateMockWrite(*req
),
1885 CreateMockWrite(*chunk1
),
1886 CreateMockWrite(*chunk2
),
1887 CreateMockWrite(*chunk3
),
1890 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1891 MockRead reads
[] = {
1892 CreateMockRead(*resp
),
1893 CreateMockRead(*chunk1
),
1894 CreateMockRead(*chunk2
),
1895 CreateMockRead(*chunk3
),
1896 MockRead(ASYNC
, 0, 0) // EOF
1899 DelayedSocketData
data(4, reads
, arraysize(reads
),
1900 writes
, arraysize(writes
));
1901 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1903 BoundNetLog(), GetParam(), NULL
);
1905 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1907 helper
.RunPreTestSetup();
1908 helper
.AddData(&data
);
1909 ASSERT_TRUE(helper
.StartDefaultTest());
1911 base::RunLoop().RunUntilIdle();
1912 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1913 base::RunLoop().RunUntilIdle();
1914 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
1916 helper
.FinishDefaultTest();
1917 helper
.VerifyDataConsumed();
1919 std::string expected_response
;
1920 expected_response
+= kUploadData
;
1921 expected_response
+= kUploadData
;
1922 expected_response
+= kUploadData
;
1924 TransactionHelperResult out
= helper
.output();
1925 EXPECT_EQ(OK
, out
.rv
);
1926 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1927 EXPECT_EQ(expected_response
, out
.response_data
);
1930 // Test that a POST without any post data works.
1931 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1932 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1933 // Setup the request
1934 HttpRequestInfo request
;
1935 request
.method
= "POST";
1936 request
.url
= GURL(kRequestUrl
);
1937 // Create an empty UploadData.
1938 request
.upload_data_stream
= NULL
;
1940 // When request.upload_data_stream is NULL for post, content-length is
1941 // expected to be 0.
1942 scoped_ptr
<SpdyHeaderBlock
> req_block(
1943 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, 0));
1944 scoped_ptr
<SpdyFrame
> req(
1945 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1947 MockWrite writes
[] = {
1948 CreateMockWrite(*req
),
1951 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1952 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1953 MockRead reads
[] = {
1954 CreateMockRead(*resp
),
1955 CreateMockRead(*body
),
1956 MockRead(ASYNC
, 0, 0) // EOF
1959 DelayedSocketData
data(1, reads
, arraysize(reads
),
1960 writes
, arraysize(writes
));
1962 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1963 BoundNetLog(), GetParam(), NULL
);
1964 helper
.RunToCompletion(&data
);
1965 TransactionHelperResult out
= helper
.output();
1966 EXPECT_EQ(OK
, out
.rv
);
1967 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1968 EXPECT_EQ("hello!", out
.response_data
);
1971 // Test that a simple POST works.
1972 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1973 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1974 // Create an empty UploadDataStream.
1975 ScopedVector
<UploadElementReader
> element_readers
;
1976 ElementsUploadDataStream
stream(element_readers
.Pass(), 0);
1978 // Setup the request
1979 HttpRequestInfo request
;
1980 request
.method
= "POST";
1981 request
.url
= GURL(kRequestUrl
);
1982 request
.upload_data_stream
= &stream
;
1984 const uint64 kContentLength
= 0;
1986 scoped_ptr
<SpdyHeaderBlock
> req_block(
1987 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, kContentLength
));
1988 scoped_ptr
<SpdyFrame
> req(
1989 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1991 MockWrite writes
[] = {
1992 CreateMockWrite(*req
),
1995 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1996 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1997 MockRead reads
[] = {
1998 CreateMockRead(*resp
),
1999 CreateMockRead(*body
),
2000 MockRead(ASYNC
, 0, 0) // EOF
2003 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
2005 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
2006 BoundNetLog(), GetParam(), NULL
);
2007 helper
.RunToCompletion(&data
);
2008 TransactionHelperResult out
= helper
.output();
2009 EXPECT_EQ(OK
, out
.rv
);
2010 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2011 EXPECT_EQ("hello!", out
.response_data
);
2014 // While we're doing a post, the server sends the reply before upload completes.
2015 TEST_P(SpdyNetworkTransactionTest
, ResponseBeforePostCompletes
) {
2016 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
2017 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2018 MockWrite writes
[] = {
2019 CreateMockWrite(*req
, 0),
2020 CreateMockWrite(*body
, 3),
2022 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2023 MockRead reads
[] = {
2024 CreateMockRead(*resp
, 1),
2025 CreateMockRead(*body
, 2),
2026 MockRead(ASYNC
, 0, 4) // EOF
2029 // Write the request headers, and read the complete response
2030 // while still waiting for chunked request data.
2031 DeterministicSocketData
data(reads
, arraysize(reads
),
2032 writes
, arraysize(writes
));
2033 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
2035 BoundNetLog(), GetParam(), NULL
);
2036 helper
.SetDeterministic();
2037 helper
.RunPreTestSetup();
2038 helper
.AddDeterministicData(&data
);
2040 ASSERT_TRUE(helper
.StartDefaultTest());
2042 // Process the request headers, SYN_REPLY, and response body.
2043 // The request body is still in flight.
2046 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
2047 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2049 // Finish sending the request body.
2050 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
2053 std::string response_body
;
2054 EXPECT_EQ(OK
, ReadTransaction(helper
.trans(), &response_body
));
2055 EXPECT_EQ(kUploadData
, response_body
);
2056 helper
.VerifyDataConsumed();
2059 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2060 // socket causes the TCP write to return zero. This test checks that the client
2061 // tries to queue up the RST_STREAM frame again.
2062 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2063 scoped_ptr
<SpdyFrame
> req(
2064 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2065 scoped_ptr
<SpdyFrame
> rst(
2066 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2067 MockWrite writes
[] = {
2068 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2069 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2070 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2073 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2074 MockRead reads
[] = {
2075 CreateMockRead(*resp
.get(), 1, ASYNC
),
2076 MockRead(ASYNC
, 0, 0, 4) // EOF
2079 DeterministicSocketData
data(reads
, arraysize(reads
),
2080 writes
, arraysize(writes
));
2081 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2082 BoundNetLog(), GetParam(), NULL
);
2083 helper
.SetDeterministic();
2084 helper
.RunPreTestSetup();
2085 helper
.AddDeterministicData(&data
);
2086 HttpNetworkTransaction
* trans
= helper
.trans();
2088 TestCompletionCallback callback
;
2089 int rv
= trans
->Start(
2090 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2091 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2095 helper
.ResetTrans();
2099 helper
.VerifyDataConsumed();
2102 // Test that the transaction doesn't crash when we don't have a reply.
2103 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2104 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2105 MockRead reads
[] = {
2106 CreateMockRead(*body
),
2107 MockRead(ASYNC
, 0, 0) // EOF
2110 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2111 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2112 BoundNetLog(), GetParam(), NULL
);
2113 helper
.RunToCompletion(&data
);
2114 TransactionHelperResult out
= helper
.output();
2115 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2118 // Test that the transaction doesn't crash when we get two replies on the same
2119 // stream ID. See http://crbug.com/45639.
2120 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2121 scoped_ptr
<SpdyFrame
> req(
2122 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2123 scoped_ptr
<SpdyFrame
> rst(
2124 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2125 MockWrite writes
[] = {
2126 CreateMockWrite(*req
),
2127 CreateMockWrite(*rst
),
2130 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2131 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2132 MockRead reads
[] = {
2133 CreateMockRead(*resp
),
2134 CreateMockRead(*resp
),
2135 CreateMockRead(*body
),
2136 MockRead(ASYNC
, 0, 0) // EOF
2139 DelayedSocketData
data(1, reads
, arraysize(reads
),
2140 writes
, arraysize(writes
));
2142 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2143 BoundNetLog(), GetParam(), NULL
);
2144 helper
.RunPreTestSetup();
2145 helper
.AddData(&data
);
2147 HttpNetworkTransaction
* trans
= helper
.trans();
2149 TestCompletionCallback callback
;
2150 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2151 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2152 rv
= callback
.WaitForResult();
2155 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2156 ASSERT_TRUE(response
!= NULL
);
2157 EXPECT_TRUE(response
->headers
.get() != NULL
);
2158 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2159 std::string response_data
;
2160 rv
= ReadTransaction(trans
, &response_data
);
2161 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2163 helper
.VerifyDataConsumed();
2166 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2167 // Construct the request.
2168 scoped_ptr
<SpdyFrame
> req(
2169 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2170 scoped_ptr
<SpdyFrame
> rst(
2171 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2172 MockWrite writes
[] = {
2173 CreateMockWrite(*req
),
2174 CreateMockWrite(*rst
),
2177 const char* const headers
[] = {
2178 "transfer-encoding", "chunked"
2180 scoped_ptr
<SpdyFrame
> resp(
2181 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2182 scoped_ptr
<SpdyFrame
> body(
2183 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2184 MockRead reads
[] = {
2185 CreateMockRead(*resp
),
2186 CreateMockRead(*body
),
2187 MockRead(ASYNC
, 0, 0) // EOF
2190 DelayedSocketData
data(1, reads
, arraysize(reads
),
2191 writes
, arraysize(writes
));
2192 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2193 BoundNetLog(), GetParam(), NULL
);
2194 helper
.RunToCompletion(&data
);
2195 TransactionHelperResult out
= helper
.output();
2196 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2198 helper
.session()->spdy_session_pool()->CloseAllSessions();
2199 helper
.VerifyDataConsumed();
2202 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2203 // Construct the request.
2204 scoped_ptr
<SpdyFrame
> req(
2205 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2206 scoped_ptr
<SpdyFrame
> rst(
2207 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2208 MockWrite writes
[] = {
2209 CreateMockWrite(*req
),
2210 CreateMockWrite(*rst
),
2213 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2214 const char* const headers
[] = {
2215 "transfer-encoding", "chunked"
2217 scoped_ptr
<SpdyFrame
> push(
2218 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2219 2, 1, "http://www.google.com/1"));
2220 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2221 MockRead reads
[] = {
2222 CreateMockRead(*resp
),
2223 CreateMockRead(*push
),
2224 CreateMockRead(*body
),
2225 MockRead(ASYNC
, 0, 0) // EOF
2228 DelayedSocketData
data(1, reads
, arraysize(reads
),
2229 writes
, arraysize(writes
));
2230 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2231 BoundNetLog(), GetParam(), NULL
);
2232 helper
.RunToCompletion(&data
);
2233 TransactionHelperResult out
= helper
.output();
2234 EXPECT_EQ(OK
, out
.rv
);
2235 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2236 EXPECT_EQ("hello!", out
.response_data
);
2238 helper
.session()->spdy_session_pool()->CloseAllSessions();
2239 helper
.VerifyDataConsumed();
2242 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2243 // Construct the request.
2244 scoped_ptr
<SpdyFrame
> req(
2245 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2246 MockWrite writes
[] = {
2247 CreateMockWrite(*req
),
2250 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2251 MockRead reads
[] = {
2252 CreateMockRead(*resp
),
2253 // This following read isn't used by the test, except during the
2254 // RunUntilIdle() call at the end since the SpdySession survives the
2255 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2256 // MockRead will do here.
2257 MockRead(ASYNC
, 0, 0) // EOF
2260 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2261 writes
, arraysize(writes
));
2263 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2264 BoundNetLog(), GetParam(), NULL
);
2265 helper
.RunPreTestSetup();
2266 helper
.AddData(&data
);
2267 HttpNetworkTransaction
* trans
= helper
.trans();
2269 TestCompletionCallback callback
;
2270 int rv
= trans
->Start(
2271 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2273 helper
.ResetTrans(); // Cancel the transaction.
2275 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2276 // MockClientSocketFactory) are still alive.
2277 base::RunLoop().RunUntilIdle();
2278 helper
.VerifyDataNotConsumed();
2281 // Verify that the client sends a Rst Frame upon cancelling the stream.
2282 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2283 scoped_ptr
<SpdyFrame
> req(
2284 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2285 scoped_ptr
<SpdyFrame
> rst(
2286 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2287 MockWrite writes
[] = {
2288 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2289 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2292 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2293 MockRead reads
[] = {
2294 CreateMockRead(*resp
, 1, ASYNC
),
2295 MockRead(ASYNC
, 0, 0, 3) // EOF
2298 DeterministicSocketData
data(reads
, arraysize(reads
),
2299 writes
, arraysize(writes
));
2301 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2304 helper
.SetDeterministic();
2305 helper
.RunPreTestSetup();
2306 helper
.AddDeterministicData(&data
);
2307 HttpNetworkTransaction
* trans
= helper
.trans();
2309 TestCompletionCallback callback
;
2311 int rv
= trans
->Start(
2312 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2313 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2317 helper
.ResetTrans();
2321 helper
.VerifyDataConsumed();
2324 // Verify that the client can correctly deal with the user callback attempting
2325 // to start another transaction on a session that is closing down. See
2326 // http://crbug.com/47455
2327 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2328 scoped_ptr
<SpdyFrame
> req(
2329 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2330 MockWrite writes
[] = { CreateMockWrite(*req
) };
2331 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2333 // The indicated length of this frame is longer than its actual length. When
2334 // the session receives an empty frame after this one, it shuts down the
2335 // session, and calls the read callback with the incomplete data.
2336 const uint8 kGetBodyFrame2
[] = {
2337 0x00, 0x00, 0x00, 0x01,
2338 0x01, 0x00, 0x00, 0x07,
2339 'h', 'e', 'l', 'l', 'o', '!',
2342 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2343 MockRead reads
[] = {
2344 CreateMockRead(*resp
, 2),
2345 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2346 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2347 arraysize(kGetBodyFrame2
), 4),
2348 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2349 MockRead(ASYNC
, 0, 0, 6), // EOF
2351 MockRead reads2
[] = {
2352 CreateMockRead(*resp
, 2),
2353 MockRead(ASYNC
, 0, 0, 3), // EOF
2356 OrderedSocketData
data(reads
, arraysize(reads
),
2357 writes
, arraysize(writes
));
2358 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2359 writes2
, arraysize(writes2
));
2361 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2362 BoundNetLog(), GetParam(), NULL
);
2363 helper
.RunPreTestSetup();
2364 helper
.AddData(&data
);
2365 helper
.AddData(&data2
);
2366 HttpNetworkTransaction
* trans
= helper
.trans();
2368 // Start the transaction with basic parameters.
2369 TestCompletionCallback callback
;
2370 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2371 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2372 rv
= callback
.WaitForResult();
2374 const int kSize
= 3000;
2375 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2379 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2381 // This forces an err_IO_pending, which sets the callback.
2382 data
.CompleteRead();
2383 // This finishes the read.
2384 data
.CompleteRead();
2385 helper
.VerifyDataConsumed();
2388 // Verify that the client can correctly deal with the user callback deleting the
2389 // transaction. Failures will usually be valgrind errors. See
2390 // http://crbug.com/46925
2391 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2392 scoped_ptr
<SpdyFrame
> req(
2393 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2394 MockWrite writes
[] = { CreateMockWrite(*req
) };
2396 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2397 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2398 MockRead reads
[] = {
2399 CreateMockRead(*resp
.get(), 2),
2400 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2401 CreateMockRead(*body
.get(), 4),
2402 MockRead(ASYNC
, 0, 0, 5), // EOF
2405 OrderedSocketData
data(reads
, arraysize(reads
),
2406 writes
, arraysize(writes
));
2408 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2409 BoundNetLog(), GetParam(), NULL
);
2410 helper
.RunPreTestSetup();
2411 helper
.AddData(&data
);
2412 HttpNetworkTransaction
* trans
= helper
.trans();
2414 // Start the transaction with basic parameters.
2415 TestCompletionCallback callback
;
2416 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2417 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2418 rv
= callback
.WaitForResult();
2420 // Setup a user callback which will delete the session, and clear out the
2421 // memory holding the stream object. Note that the callback deletes trans.
2422 const int kSize
= 3000;
2423 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2427 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2428 base::Unretained(&helper
)));
2429 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2430 data
.CompleteRead();
2432 // Finish running rest of tasks.
2433 base::RunLoop().RunUntilIdle();
2434 helper
.VerifyDataConsumed();
2437 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2438 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2439 scoped_ptr
<SpdyHeaderBlock
> headers(
2440 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2441 (*headers
)["user-agent"] = "";
2442 (*headers
)["accept-encoding"] = "gzip, deflate";
2443 scoped_ptr
<SpdyHeaderBlock
> headers2(
2444 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2445 (*headers2
)["user-agent"] = "";
2446 (*headers2
)["accept-encoding"] = "gzip, deflate";
2448 // Setup writes/reads to www.google.com
2449 scoped_ptr
<SpdyFrame
> req(
2450 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2451 scoped_ptr
<SpdyFrame
> req2(
2452 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2453 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2454 MockWrite writes
[] = {
2455 CreateMockWrite(*req
, 1),
2457 MockRead reads
[] = {
2458 CreateMockRead(*resp
, 2),
2459 MockRead(ASYNC
, 0, 0, 3) // EOF
2462 // Setup writes/reads to www.foo.com
2463 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2464 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2465 MockWrite writes2
[] = {
2466 CreateMockWrite(*req2
, 1),
2468 MockRead reads2
[] = {
2469 CreateMockRead(*resp2
, 2),
2470 CreateMockRead(*body2
, 3),
2471 MockRead(ASYNC
, 0, 0, 4) // EOF
2473 OrderedSocketData
data(reads
, arraysize(reads
),
2474 writes
, arraysize(writes
));
2475 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2476 writes2
, arraysize(writes2
));
2478 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2481 SpdyURLRequestContext
spdy_url_request_context(
2482 GetParam().protocol
,
2483 false /* force_spdy_over_ssl*/,
2484 true /* force_spdy_always */);
2485 scoped_ptr
<URLRequest
> r(
2486 spdy_url_request_context
.CreateRequest(GURL("http://www.google.com/"),
2490 spdy_url_request_context
.socket_factory().
2491 AddSocketDataProvider(&data
);
2492 spdy_url_request_context
.socket_factory().
2493 AddSocketDataProvider(&data2
);
2495 d
.set_quit_on_redirect(true);
2497 base::RunLoop().Run();
2499 EXPECT_EQ(1, d
.received_redirect_count());
2501 r
->FollowDeferredRedirect();
2502 base::RunLoop().Run();
2503 EXPECT_EQ(1, d
.response_started_count());
2504 EXPECT_FALSE(d
.received_data_before_response());
2505 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
->status().status());
2506 std::string
contents("hello!");
2507 EXPECT_EQ(contents
, d
.data_received());
2509 EXPECT_TRUE(data
.at_read_eof());
2510 EXPECT_TRUE(data
.at_write_eof());
2511 EXPECT_TRUE(data2
.at_read_eof());
2512 EXPECT_TRUE(data2
.at_write_eof());
2515 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2517 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2518 scoped_ptr
<SpdyHeaderBlock
> headers(
2519 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2520 (*headers
)["user-agent"] = "";
2521 (*headers
)["accept-encoding"] = "gzip, deflate";
2523 // Setup writes/reads to www.google.com
2524 scoped_ptr
<SpdyFrame
> req(
2525 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2526 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2527 scoped_ptr
<SpdyFrame
> rep(
2528 spdy_util_
.ConstructSpdyPush(NULL
,
2532 "http://www.google.com/foo.dat",
2533 "301 Moved Permanently",
2534 "http://www.foo.com/index.php"));
2535 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2536 scoped_ptr
<SpdyFrame
> rst(
2537 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
2538 MockWrite writes
[] = {
2539 CreateMockWrite(*req
, 1),
2540 CreateMockWrite(*rst
, 6),
2542 MockRead reads
[] = {
2543 CreateMockRead(*resp
, 2),
2544 CreateMockRead(*rep
, 3),
2545 CreateMockRead(*body
, 4),
2546 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2547 MockRead(ASYNC
, 0, 0, 7) // EOF
2550 // Setup writes/reads to www.foo.com
2551 scoped_ptr
<SpdyHeaderBlock
> headers2(
2552 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2553 (*headers2
)["user-agent"] = "";
2554 (*headers2
)["accept-encoding"] = "gzip, deflate";
2555 scoped_ptr
<SpdyFrame
> req2(
2556 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2557 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2558 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2559 MockWrite writes2
[] = {
2560 CreateMockWrite(*req2
, 1),
2562 MockRead reads2
[] = {
2563 CreateMockRead(*resp2
, 2),
2564 CreateMockRead(*body2
, 3),
2565 MockRead(ASYNC
, 0, 0, 5) // EOF
2567 OrderedSocketData
data(reads
, arraysize(reads
),
2568 writes
, arraysize(writes
));
2569 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2570 writes2
, arraysize(writes2
));
2572 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2575 SpdyURLRequestContext
spdy_url_request_context(
2576 GetParam().protocol
,
2577 false /* force_spdy_over_ssl*/,
2578 true /* force_spdy_always */);
2580 scoped_ptr
<URLRequest
> r(
2581 spdy_url_request_context
.CreateRequest(GURL("http://www.google.com/"),
2585 spdy_url_request_context
.socket_factory().
2586 AddSocketDataProvider(&data
);
2589 base::RunLoop().Run();
2591 EXPECT_EQ(0, d
.received_redirect_count());
2592 std::string
contents("hello!");
2593 EXPECT_EQ(contents
, d
.data_received());
2595 scoped_ptr
<URLRequest
> r2(
2596 spdy_url_request_context
.CreateRequest(
2597 GURL("http://www.google.com/foo.dat"),
2601 spdy_url_request_context
.socket_factory().
2602 AddSocketDataProvider(&data2
);
2604 d2
.set_quit_on_redirect(true);
2606 base::RunLoop().Run();
2607 EXPECT_EQ(1, d2
.received_redirect_count());
2609 r2
->FollowDeferredRedirect();
2610 base::RunLoop().Run();
2611 EXPECT_EQ(1, d2
.response_started_count());
2612 EXPECT_FALSE(d2
.received_data_before_response());
2613 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
->status().status());
2614 std::string
contents2("hello!");
2615 EXPECT_EQ(contents2
, d2
.data_received());
2617 data
.CompleteRead();
2618 data2
.CompleteRead();
2619 EXPECT_TRUE(data
.at_read_eof());
2620 EXPECT_TRUE(data
.at_write_eof());
2621 EXPECT_TRUE(data2
.at_read_eof());
2622 EXPECT_TRUE(data2
.at_write_eof());
2625 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2626 scoped_ptr
<SpdyFrame
> stream1_syn(
2627 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2628 scoped_ptr
<SpdyFrame
> stream1_body(
2629 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2630 MockWrite writes
[] = {
2631 CreateMockWrite(*stream1_syn
, 1),
2634 scoped_ptr
<SpdyFrame
>
2635 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2636 scoped_ptr
<SpdyFrame
>
2637 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2641 "http://www.google.com/foo.dat"));
2642 const char kPushedData
[] = "pushed";
2643 scoped_ptr
<SpdyFrame
> stream2_body(
2644 spdy_util_
.ConstructSpdyBodyFrame(
2645 2, kPushedData
, strlen(kPushedData
), true));
2646 MockRead reads
[] = {
2647 CreateMockRead(*stream1_reply
, 2),
2648 CreateMockRead(*stream2_syn
, 3),
2649 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2650 CreateMockRead(*stream2_body
, 5),
2651 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2654 HttpResponseInfo response
;
2655 HttpResponseInfo response2
;
2656 std::string
expected_push_result("pushed");
2657 OrderedSocketData
data(reads
, arraysize(reads
),
2658 writes
, arraysize(writes
));
2659 RunServerPushTest(&data
,
2662 expected_push_result
);
2664 // Verify the SYN_REPLY.
2665 EXPECT_TRUE(response
.headers
.get() != NULL
);
2666 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2668 // Verify the pushed stream.
2669 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2670 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2673 TEST_P(SpdyNetworkTransactionTest
, ServerPushBeforeSynReply
) {
2674 scoped_ptr
<SpdyFrame
> stream1_syn(
2675 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2676 scoped_ptr
<SpdyFrame
> stream1_body(
2677 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2678 MockWrite writes
[] = {
2679 CreateMockWrite(*stream1_syn
, 1),
2682 scoped_ptr
<SpdyFrame
>
2683 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2684 scoped_ptr
<SpdyFrame
>
2685 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2689 "http://www.google.com/foo.dat"));
2690 const char kPushedData
[] = "pushed";
2691 scoped_ptr
<SpdyFrame
> stream2_body(
2692 spdy_util_
.ConstructSpdyBodyFrame(
2693 2, kPushedData
, strlen(kPushedData
), true));
2694 MockRead reads
[] = {
2695 CreateMockRead(*stream2_syn
, 2),
2696 CreateMockRead(*stream1_reply
, 3),
2697 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2698 CreateMockRead(*stream2_body
, 5),
2699 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2702 HttpResponseInfo response
;
2703 HttpResponseInfo response2
;
2704 std::string
expected_push_result("pushed");
2705 OrderedSocketData
data(reads
, arraysize(reads
),
2706 writes
, arraysize(writes
));
2707 RunServerPushTest(&data
,
2710 expected_push_result
);
2712 // Verify the SYN_REPLY.
2713 EXPECT_TRUE(response
.headers
.get() != NULL
);
2714 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2716 // Verify the pushed stream.
2717 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2718 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2721 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2722 scoped_ptr
<SpdyFrame
> stream1_syn(
2723 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2724 MockWrite writes
[] = { CreateMockWrite(*stream1_syn
, 1), };
2726 scoped_ptr
<SpdyFrame
>
2727 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2728 scoped_ptr
<SpdyFrame
>
2729 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2733 "http://www.google.com/foo.dat"));
2734 const char kPushedData
[] = "pushed";
2735 scoped_ptr
<SpdyFrame
> stream2_body(
2736 spdy_util_
.ConstructSpdyBodyFrame(
2737 2, kPushedData
, strlen(kPushedData
), true));
2738 scoped_ptr
<SpdyFrame
>
2739 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2740 MockRead reads
[] = {
2741 CreateMockRead(*stream1_reply
, 2),
2742 CreateMockRead(*stream2_syn
, 3),
2743 CreateMockRead(*stream2_body
, 4),
2744 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2745 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2748 HttpResponseInfo response
;
2749 HttpResponseInfo response2
;
2750 std::string
expected_push_result("pushed");
2751 OrderedSocketData
data(reads
, arraysize(reads
),
2752 writes
, arraysize(writes
));
2753 RunServerPushTest(&data
,
2756 expected_push_result
);
2758 // Verify the SYN_REPLY.
2759 EXPECT_TRUE(response
.headers
.get() != NULL
);
2760 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2762 // Verify the pushed stream.
2763 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2764 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2767 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2768 scoped_ptr
<SpdyFrame
> stream1_syn(
2769 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2770 scoped_ptr
<SpdyFrame
> stream1_body(
2771 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2772 MockWrite writes
[] = {
2773 CreateMockWrite(*stream1_syn
, 1),
2776 scoped_ptr
<SpdyFrame
>
2777 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2778 scoped_ptr
<SpdyFrame
>
2779 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2783 "http://www.google.com/foo.dat"));
2784 scoped_ptr
<SpdyFrame
> stream2_rst(
2785 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2786 MockRead reads
[] = {
2787 CreateMockRead(*stream1_reply
, 2),
2788 CreateMockRead(*stream2_syn
, 3),
2789 CreateMockRead(*stream2_rst
, 4),
2790 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2791 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2794 OrderedSocketData
data(reads
, arraysize(reads
),
2795 writes
, arraysize(writes
));
2796 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2797 BoundNetLog(), GetParam(), NULL
);
2799 helper
.RunPreTestSetup();
2800 helper
.AddData(&data
);
2802 HttpNetworkTransaction
* trans
= helper
.trans();
2804 // Start the transaction with basic parameters.
2805 TestCompletionCallback callback
;
2806 int rv
= trans
->Start(
2807 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2808 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2809 rv
= callback
.WaitForResult();
2812 // Verify that we consumed all test data.
2813 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2814 << data
.read_count()
2816 << data
.read_index();
2817 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2818 << data
.write_count()
2820 << data
.write_index();
2822 // Verify the SYN_REPLY.
2823 HttpResponseInfo response
= *trans
->GetResponseInfo();
2824 EXPECT_TRUE(response
.headers
.get() != NULL
);
2825 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2828 // Verify that we don't leak streams and that we properly send a reset
2829 // if the server pushes the same stream twice.
2830 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2831 scoped_ptr
<SpdyFrame
> stream1_syn(
2832 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2833 scoped_ptr
<SpdyFrame
> stream1_body(
2834 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2835 scoped_ptr
<SpdyFrame
> stream3_rst(
2836 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR
));
2837 MockWrite writes
[] = {
2838 CreateMockWrite(*stream1_syn
, 1),
2839 CreateMockWrite(*stream3_rst
, 5),
2842 scoped_ptr
<SpdyFrame
>
2843 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2844 scoped_ptr
<SpdyFrame
>
2845 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2849 "http://www.google.com/foo.dat"));
2850 const char kPushedData
[] = "pushed";
2851 scoped_ptr
<SpdyFrame
> stream2_body(
2852 spdy_util_
.ConstructSpdyBodyFrame(
2853 2, kPushedData
, strlen(kPushedData
), true));
2854 scoped_ptr
<SpdyFrame
>
2855 stream3_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2859 "http://www.google.com/foo.dat"));
2860 MockRead reads
[] = {
2861 CreateMockRead(*stream1_reply
, 2),
2862 CreateMockRead(*stream2_syn
, 3),
2863 CreateMockRead(*stream3_syn
, 4),
2864 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
2865 CreateMockRead(*stream2_body
, 7),
2866 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
2869 HttpResponseInfo response
;
2870 HttpResponseInfo response2
;
2871 std::string
expected_push_result("pushed");
2872 OrderedSocketData
data(reads
, arraysize(reads
),
2873 writes
, arraysize(writes
));
2874 RunServerPushTest(&data
,
2877 expected_push_result
);
2879 // Verify the SYN_REPLY.
2880 EXPECT_TRUE(response
.headers
.get() != NULL
);
2881 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2883 // Verify the pushed stream.
2884 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2885 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2888 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2889 scoped_ptr
<SpdyFrame
> stream1_syn(
2890 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2891 scoped_ptr
<SpdyFrame
> stream1_body(
2892 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2893 MockWrite writes
[] = {
2894 CreateMockWrite(*stream1_syn
, 1),
2897 scoped_ptr
<SpdyFrame
>
2898 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2899 scoped_ptr
<SpdyFrame
>
2900 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2904 "http://www.google.com/foo.dat"));
2905 static const char kPushedData
[] = "pushed my darling hello my baby";
2906 scoped_ptr
<SpdyFrame
> stream2_body_base(
2907 spdy_util_
.ConstructSpdyBodyFrame(
2908 2, kPushedData
, strlen(kPushedData
), true));
2909 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2910 scoped_ptr
<SpdyFrame
> stream2_body1(
2911 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2912 scoped_ptr
<SpdyFrame
> stream2_body2(
2913 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2914 scoped_ptr
<SpdyFrame
> stream2_body3(
2915 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2916 kChunkSize
, false));
2917 scoped_ptr
<SpdyFrame
> stream2_body4(
2918 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2919 stream2_body_base
->size() - 3 * kChunkSize
, false));
2920 MockRead reads
[] = {
2921 CreateMockRead(*stream1_reply
, 2),
2922 CreateMockRead(*stream2_syn
, 3),
2923 CreateMockRead(*stream2_body1
, 4),
2924 CreateMockRead(*stream2_body2
, 5),
2925 CreateMockRead(*stream2_body3
, 6),
2926 CreateMockRead(*stream2_body4
, 7),
2927 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
2928 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
2931 HttpResponseInfo response
;
2932 HttpResponseInfo response2
;
2933 std::string
expected_push_result("pushed my darling hello my baby");
2934 OrderedSocketData
data(reads
, arraysize(reads
),
2935 writes
, arraysize(writes
));
2936 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2938 // Verify the SYN_REPLY.
2939 EXPECT_TRUE(response
.headers
.get() != NULL
);
2940 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2942 // Verify the pushed stream.
2943 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2944 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2947 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2948 scoped_ptr
<SpdyFrame
> stream1_syn(
2949 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2950 scoped_ptr
<SpdyFrame
> stream1_body(
2951 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2952 MockWrite writes
[] = {
2953 CreateMockWrite(*stream1_syn
, 1),
2956 scoped_ptr
<SpdyFrame
>
2957 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2958 scoped_ptr
<SpdyFrame
>
2959 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2963 "http://www.google.com/foo.dat"));
2964 static const char kPushedData
[] = "pushed my darling hello my baby";
2965 scoped_ptr
<SpdyFrame
> stream2_body_base(
2966 spdy_util_
.ConstructSpdyBodyFrame(
2967 2, kPushedData
, strlen(kPushedData
), true));
2968 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2969 scoped_ptr
<SpdyFrame
> stream2_body1(
2970 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2971 scoped_ptr
<SpdyFrame
> stream2_body2(
2972 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2973 scoped_ptr
<SpdyFrame
> stream2_body3(
2974 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2975 kChunkSize
, false));
2976 scoped_ptr
<SpdyFrame
> stream2_body4(
2977 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2978 stream2_body_base
->size() - 3 * kChunkSize
, false));
2979 MockRead reads
[] = {
2980 CreateMockRead(*stream1_reply
, 2),
2981 CreateMockRead(*stream2_syn
, 3),
2982 CreateMockRead(*stream2_body1
, 4),
2983 CreateMockRead(*stream2_body2
, 5),
2984 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2985 CreateMockRead(*stream2_body3
, 7),
2986 CreateMockRead(*stream2_body4
, 8),
2987 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
2988 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
2991 HttpResponseInfo response
;
2992 HttpResponseInfo response2
;
2993 OrderedSocketData
data(reads
, arraysize(reads
),
2994 writes
, arraysize(writes
));
2995 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2997 // Verify the SYN_REPLY.
2998 EXPECT_TRUE(response
.headers
.get() != NULL
);
2999 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3001 // Verify the pushed stream.
3002 EXPECT_TRUE(response2
.headers
.get() != NULL
);
3003 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3006 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
3007 if (spdy_util_
.spdy_version() == SPDY4
) {
3008 // PUSH_PROMISE with stream id 0 is connection-level error.
3009 // TODO(baranovich): Test session going away.
3013 scoped_ptr
<SpdyFrame
> stream1_syn(
3014 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3015 scoped_ptr
<SpdyFrame
> stream1_body(
3016 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3017 scoped_ptr
<SpdyFrame
> stream2_rst(
3018 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
3019 MockWrite writes
[] = {
3020 CreateMockWrite(*stream1_syn
, 1),
3021 CreateMockWrite(*stream2_rst
, 4),
3024 scoped_ptr
<SpdyFrame
>
3025 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3026 scoped_ptr
<SpdyFrame
>
3027 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3031 "http://www.google.com/foo.dat"));
3032 MockRead reads
[] = {
3033 CreateMockRead(*stream1_reply
, 2),
3034 CreateMockRead(*stream2_syn
, 3),
3035 CreateMockRead(*stream1_body
, 4),
3036 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3039 OrderedSocketData
data(reads
, arraysize(reads
),
3040 writes
, arraysize(writes
));
3041 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3042 BoundNetLog(), GetParam(), NULL
);
3044 helper
.RunPreTestSetup();
3045 helper
.AddData(&data
);
3047 HttpNetworkTransaction
* trans
= helper
.trans();
3049 // Start the transaction with basic parameters.
3050 TestCompletionCallback callback
;
3051 int rv
= trans
->Start(
3052 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3054 rv
= callback
.WaitForResult();
3057 // Verify that we consumed all test data.
3058 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3059 << data
.read_count()
3061 << data
.read_index();
3062 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3063 << data
.write_count()
3065 << data
.write_index();
3067 // Verify the SYN_REPLY.
3068 HttpResponseInfo response
= *trans
->GetResponseInfo();
3069 EXPECT_TRUE(response
.headers
.get() != NULL
);
3070 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3073 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3074 scoped_ptr
<SpdyFrame
> stream1_syn(
3075 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3076 scoped_ptr
<SpdyFrame
> stream1_body(
3077 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3078 scoped_ptr
<SpdyFrame
> stream2_rst(
3079 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM
));
3080 MockWrite writes
[] = {
3081 CreateMockWrite(*stream1_syn
, 1),
3082 CreateMockWrite(*stream2_rst
, 4),
3085 scoped_ptr
<SpdyFrame
>
3086 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3087 scoped_ptr
<SpdyFrame
>
3088 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3092 "http://www.google.com/foo.dat"));
3093 MockRead reads
[] = {
3094 CreateMockRead(*stream1_reply
, 2),
3095 CreateMockRead(*stream2_syn
, 3),
3096 CreateMockRead(*stream1_body
, 4),
3097 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3100 OrderedSocketData
data(reads
, arraysize(reads
),
3101 writes
, arraysize(writes
));
3102 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3103 BoundNetLog(), GetParam(), NULL
);
3105 helper
.RunPreTestSetup();
3106 helper
.AddData(&data
);
3108 HttpNetworkTransaction
* trans
= helper
.trans();
3110 // Start the transaction with basic parameters.
3111 TestCompletionCallback callback
;
3112 int rv
= trans
->Start(
3113 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3115 rv
= callback
.WaitForResult();
3118 // Verify that we consumed all test data.
3119 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3120 << data
.read_count()
3122 << data
.read_index();
3123 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3124 << data
.write_count()
3126 << data
.write_index();
3128 // Verify the SYN_REPLY.
3129 HttpResponseInfo response
= *trans
->GetResponseInfo();
3130 EXPECT_TRUE(response
.headers
.get() != NULL
);
3131 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3134 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3135 scoped_ptr
<SpdyFrame
> stream1_syn(
3136 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3137 scoped_ptr
<SpdyFrame
> stream1_body(
3138 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3139 scoped_ptr
<SpdyFrame
> stream2_rst(
3140 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
3141 MockWrite writes
[] = {
3142 CreateMockWrite(*stream1_syn
, 1),
3143 CreateMockWrite(*stream2_rst
, 4),
3146 scoped_ptr
<SpdyFrame
>
3147 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3148 scoped_ptr
<SpdyHeaderBlock
> incomplete_headers(new SpdyHeaderBlock());
3149 (*incomplete_headers
)["hello"] = "bye";
3150 (*incomplete_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
3151 (*incomplete_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
3152 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructInitialSpdyPushFrame(
3153 incomplete_headers
.Pass(), 2, 1));
3154 MockRead reads
[] = {
3155 CreateMockRead(*stream1_reply
, 2),
3156 CreateMockRead(*stream2_syn
, 3),
3157 CreateMockRead(*stream1_body
, 4),
3158 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3161 OrderedSocketData
data(reads
, arraysize(reads
),
3162 writes
, arraysize(writes
));
3163 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3164 BoundNetLog(), GetParam(), NULL
);
3166 helper
.RunPreTestSetup();
3167 helper
.AddData(&data
);
3169 HttpNetworkTransaction
* trans
= helper
.trans();
3171 // Start the transaction with basic parameters.
3172 TestCompletionCallback callback
;
3173 int rv
= trans
->Start(
3174 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3175 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3176 rv
= callback
.WaitForResult();
3178 // Verify that we consumed all test data.
3179 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3180 << data
.read_count()
3182 << data
.read_index();
3183 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3184 << data
.write_count()
3186 << data
.write_index();
3188 // Verify the SYN_REPLY.
3189 HttpResponseInfo response
= *trans
->GetResponseInfo();
3190 EXPECT_TRUE(response
.headers
.get() != NULL
);
3191 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3194 // Verify that various SynReply headers parse correctly through the
3196 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3197 struct SynReplyHeadersTests
{
3199 const char* extra_headers
[5];
3200 SpdyHeaderBlock expected_headers
;
3202 // This uses a multi-valued cookie header.
3205 "cookie", "val2", // will get appended separated by NULL
3209 // This is the minimalist set of headers.
3213 // Headers with a comma separated list.
3215 { "cookie", "val1,val2",
3221 test_cases
[0].expected_headers
["cookie"] = "val1";
3222 test_cases
[0].expected_headers
["cookie"] += '\0';
3223 test_cases
[0].expected_headers
["cookie"] += "val2";
3224 test_cases
[0].expected_headers
["hello"] = "bye";
3225 test_cases
[0].expected_headers
["status"] = "200";
3227 test_cases
[1].expected_headers
["hello"] = "bye";
3228 test_cases
[1].expected_headers
["status"] = "200";
3230 test_cases
[2].expected_headers
["cookie"] = "val1,val2";
3231 test_cases
[2].expected_headers
["hello"] = "bye";
3232 test_cases
[2].expected_headers
["status"] = "200";
3234 if (spdy_util_
.spdy_version() < SPDY4
) {
3235 // SPDY4/HTTP2 eliminates use of the :version header.
3236 test_cases
[0].expected_headers
["version"] = "HTTP/1.1";
3237 test_cases
[1].expected_headers
["version"] = "HTTP/1.1";
3238 test_cases
[2].expected_headers
["version"] = "HTTP/1.1";
3241 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3242 scoped_ptr
<SpdyFrame
> req(
3243 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3244 MockWrite writes
[] = { CreateMockWrite(*req
) };
3246 scoped_ptr
<SpdyFrame
> resp(
3247 spdy_util_
.ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3248 test_cases
[i
].num_headers
,
3250 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3251 MockRead reads
[] = {
3252 CreateMockRead(*resp
),
3253 CreateMockRead(*body
),
3254 MockRead(ASYNC
, 0, 0) // EOF
3257 DelayedSocketData
data(1, reads
, arraysize(reads
),
3258 writes
, arraysize(writes
));
3259 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3260 BoundNetLog(), GetParam(), NULL
);
3261 helper
.RunToCompletion(&data
);
3262 TransactionHelperResult out
= helper
.output();
3264 EXPECT_EQ(OK
, out
.rv
);
3265 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3266 EXPECT_EQ("hello!", out
.response_data
);
3268 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3269 EXPECT_TRUE(headers
.get() != NULL
);
3271 std::string name
, value
;
3272 SpdyHeaderBlock header_block
;
3273 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3274 if (header_block
[name
].empty()) {
3275 header_block
[name
] = value
;
3277 header_block
[name
] += '\0';
3278 header_block
[name
] += value
;
3281 EXPECT_EQ(test_cases
[i
].expected_headers
, header_block
);
3285 // Verify that various SynReply headers parse vary fields correctly
3286 // through the HTTP layer, and the response matches the request.
3287 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3288 // Modify the following data to change/add test cases:
3289 struct SynReplyTests
{
3292 const char* extra_headers
[2][16];
3294 // Test the case of a multi-valued cookie. When the value is delimited
3295 // with NUL characters, it needs to be unfolded into multiple headers.
3299 { { "cookie", "val1,val2",
3303 spdy_util_
.GetStatusKey(), "200",
3304 spdy_util_
.GetPathKey(), "/index.php",
3305 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3309 }, { // Multiple vary fields.
3312 { { "friend", "barney",
3313 "enemy", "snaggletooth",
3318 spdy_util_
.GetStatusKey(), "200",
3319 spdy_util_
.GetPathKey(), "/index.php",
3320 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3324 }, { // Test a '*' vary field.
3327 { { "cookie", "val1,val2",
3331 spdy_util_
.GetStatusKey(), "200",
3332 spdy_util_
.GetPathKey(), "/index.php",
3333 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3337 }, { // Multiple comma-separated vary fields.
3340 { { "friend", "barney",
3341 "enemy", "snaggletooth",
3344 { "vary", "friend,enemy",
3345 spdy_util_
.GetStatusKey(), "200",
3346 spdy_util_
.GetPathKey(), "/index.php",
3347 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3354 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3355 // Construct the request.
3356 scoped_ptr
<SpdyFrame
> frame_req(
3357 spdy_util_
.ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3358 test_cases
[i
].num_headers
[0],
3359 false, 1, LOWEST
, true));
3361 MockWrite writes
[] = {
3362 CreateMockWrite(*frame_req
),
3365 // Construct the reply.
3366 SpdyHeaderBlock reply_headers
;
3367 AppendToHeaderBlock(test_cases
[i
].extra_headers
[1],
3368 test_cases
[i
].num_headers
[1],
3370 scoped_ptr
<SpdyFrame
> frame_reply(
3371 spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3373 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3374 MockRead reads
[] = {
3375 CreateMockRead(*frame_reply
),
3376 CreateMockRead(*body
),
3377 MockRead(ASYNC
, 0, 0) // EOF
3380 // Attach the headers to the request.
3381 int header_count
= test_cases
[i
].num_headers
[0];
3383 HttpRequestInfo request
= CreateGetRequest();
3384 for (int ct
= 0; ct
< header_count
; ct
++) {
3385 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3386 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3387 request
.extra_headers
.SetHeader(header_key
, header_value
);
3390 DelayedSocketData
data(1, reads
, arraysize(reads
),
3391 writes
, arraysize(writes
));
3392 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
3393 BoundNetLog(), GetParam(), NULL
);
3394 helper
.RunToCompletion(&data
);
3395 TransactionHelperResult out
= helper
.output();
3397 EXPECT_EQ(OK
, out
.rv
) << i
;
3398 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3399 EXPECT_EQ("hello!", out
.response_data
) << i
;
3401 // Test the response information.
3402 EXPECT_TRUE(out
.response_info
.response_time
>
3403 out
.response_info
.request_time
) << i
;
3404 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3405 out
.response_info
.request_time
;
3406 base::TimeDelta min_expected_delay
;
3407 min_expected_delay
.FromMilliseconds(10);
3408 EXPECT_GT(test_delay
.InMillisecondsF(),
3409 min_expected_delay
.InMillisecondsF()) << i
;
3410 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3411 test_cases
[i
].vary_matches
) << i
;
3413 // Check the headers.
3414 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3415 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3417 std::string name
, value
, lines
;
3418 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3421 lines
.append(value
);
3425 // Construct the expected header reply string.
3426 std::string expected_reply
=
3427 spdy_util_
.ConstructSpdyReplyString(reply_headers
);
3428 EXPECT_EQ(expected_reply
, lines
) << i
;
3432 // Verify that we don't crash on invalid SynReply responses.
3433 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3434 struct InvalidSynReplyTests
{
3436 const char* headers
[10];
3438 // SYN_REPLY missing status header
3442 spdy_util_
.GetPathKey(), "/index.php",
3443 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3447 // SYN_REPLY missing version header
3450 spdy_util_
.GetPathKey(), "/index.php",
3454 // SYN_REPLY with no headers
3458 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3459 scoped_ptr
<SpdyFrame
> req(
3460 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3461 scoped_ptr
<SpdyFrame
> rst(
3462 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3463 MockWrite writes
[] = {
3464 CreateMockWrite(*req
),
3465 CreateMockWrite(*rst
),
3468 // Construct the reply.
3469 SpdyHeaderBlock reply_headers
;
3470 AppendToHeaderBlock(
3471 test_cases
[i
].headers
, test_cases
[i
].num_headers
, &reply_headers
);
3472 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3473 MockRead reads
[] = {
3474 CreateMockRead(*resp
),
3475 MockRead(ASYNC
, 0, 0) // EOF
3478 DelayedSocketData
data(1, reads
, arraysize(reads
),
3479 writes
, arraysize(writes
));
3480 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3481 BoundNetLog(), GetParam(), NULL
);
3482 helper
.RunToCompletion(&data
);
3483 TransactionHelperResult out
= helper
.output();
3484 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3488 // Verify that we don't crash on some corrupt frames.
3489 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3490 // connection error. I'd like to backport this behavior to SPDY3 as well.
3491 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3492 if (spdy_util_
.spdy_version() >= SPDY4
) {
3495 // This is the length field that's too short.
3496 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3497 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3498 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3500 (spdy_util_
.spdy_version() < SPDY4
) ?
3501 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize() :
3502 syn_reply_wrong_length
->size();
3503 size_t wrong_size
= right_size
- 4;
3504 test::SetFrameLength(syn_reply_wrong_length
.get(),
3506 spdy_util_
.spdy_version());
3508 struct SynReplyTests
{
3509 const SpdyFrame
* syn_reply
;
3511 { syn_reply_wrong_length
.get(), },
3514 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3515 scoped_ptr
<SpdyFrame
> req(
3516 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3517 scoped_ptr
<SpdyFrame
> rst(
3518 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3519 MockWrite writes
[] = {
3520 CreateMockWrite(*req
),
3521 CreateMockWrite(*rst
),
3524 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3525 MockRead reads
[] = {
3526 MockRead(ASYNC
, test_cases
[i
].syn_reply
->data(), wrong_size
),
3527 CreateMockRead(*body
),
3528 MockRead(ASYNC
, 0, 0) // EOF
3531 DelayedSocketData
data(1, reads
, arraysize(reads
),
3532 writes
, arraysize(writes
));
3533 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3534 BoundNetLog(), GetParam(), NULL
);
3535 helper
.RunToCompletion(&data
);
3536 TransactionHelperResult out
= helper
.output();
3537 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3541 // SPDY4 treats a header decompression failure as a connection-level error.
3542 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionErrorSpdy4
) {
3543 if (spdy_util_
.spdy_version() < SPDY4
) {
3546 // This is the length field that's too short.
3547 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3548 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3549 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3551 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize();
3552 size_t wrong_size
= right_size
- 4;
3553 test::SetFrameLength(syn_reply_wrong_length
.get(),
3555 spdy_util_
.spdy_version());
3557 scoped_ptr
<SpdyFrame
> req(
3558 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3559 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3560 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3561 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3563 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3564 MockRead reads
[] = {
3565 MockRead(ASYNC
, syn_reply_wrong_length
->data(),
3566 syn_reply_wrong_length
->size() - 4),
3569 DelayedSocketData
data(1, reads
, arraysize(reads
),
3570 writes
, arraysize(writes
));
3571 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3572 BoundNetLog(), GetParam(), NULL
);
3573 helper
.RunToCompletion(&data
);
3574 TransactionHelperResult out
= helper
.output();
3575 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3578 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnDecompressionFailure
) {
3579 if (GetParam().protocol
< kProtoSPDY4
) {
3580 // Decompression failures are a stream error in SPDY3 and above.
3583 scoped_ptr
<SpdyFrame
> req(
3584 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3585 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3586 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3587 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3589 // Read HEADERS with corrupted payload.
3590 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3591 memset(resp
->data() + 12, 0xff, resp
->size() - 12);
3592 MockRead reads
[] = {CreateMockRead(*resp
)};
3594 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3595 NormalSpdyTransactionHelper
helper(
3596 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3597 helper
.RunToCompletion(&data
);
3598 TransactionHelperResult out
= helper
.output();
3599 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3602 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnFrameSizeError
) {
3603 scoped_ptr
<SpdyFrame
> req(
3604 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3605 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3606 0, GOAWAY_PROTOCOL_ERROR
, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3607 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3609 // Read WINDOW_UPDATE with incorrectly-sized payload.
3610 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3611 // which is mapped to a protocol error, and not a frame size error.
3612 scoped_ptr
<SpdyFrame
> bad_window_update(
3613 spdy_util_
.ConstructSpdyWindowUpdate(1, 1));
3614 test::SetFrameLength(bad_window_update
.get(),
3615 bad_window_update
->size() - 1,
3616 spdy_util_
.spdy_version());
3617 MockRead reads
[] = {CreateMockRead(*bad_window_update
)};
3619 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3620 NormalSpdyTransactionHelper
helper(
3621 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3622 helper
.RunToCompletion(&data
);
3623 TransactionHelperResult out
= helper
.output();
3624 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3627 // Test that we shutdown correctly on write errors.
3628 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3629 scoped_ptr
<SpdyFrame
> req(
3630 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3631 MockWrite writes
[] = {
3632 // We'll write 10 bytes successfully
3633 MockWrite(ASYNC
, req
->data(), 10, 0),
3634 // Followed by ERROR!
3635 MockWrite(ASYNC
, ERR_FAILED
, 1),
3636 // Session drains and attempts to write a GOAWAY: Another ERROR!
3637 MockWrite(ASYNC
, ERR_FAILED
, 2),
3640 MockRead reads
[] = {
3641 MockRead(ASYNC
, 0, 3) // EOF
3644 DeterministicSocketData
data(reads
, arraysize(reads
),
3645 writes
, arraysize(writes
));
3647 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3648 BoundNetLog(), GetParam(), NULL
);
3649 helper
.SetDeterministic();
3650 helper
.RunPreTestSetup();
3651 helper
.AddDeterministicData(&data
);
3652 EXPECT_TRUE(helper
.StartDefaultTest());
3654 helper
.FinishDefaultTest();
3655 EXPECT_TRUE(data
.at_write_eof());
3656 EXPECT_TRUE(!data
.at_read_eof());
3657 TransactionHelperResult out
= helper
.output();
3658 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3661 // Test that partial writes work.
3662 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3663 // Chop the SYN_STREAM frame into 5 chunks.
3664 scoped_ptr
<SpdyFrame
> req(
3665 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3666 const int kChunks
= 5;
3667 scoped_ptr
<MockWrite
[]> writes(ChopWriteFrame(*req
.get(), kChunks
));
3669 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3670 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3671 MockRead reads
[] = {
3672 CreateMockRead(*resp
),
3673 CreateMockRead(*body
),
3674 MockRead(ASYNC
, 0, 0) // EOF
3677 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
3678 writes
.get(), kChunks
);
3679 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3680 BoundNetLog(), GetParam(), NULL
);
3681 helper
.RunToCompletion(&data
);
3682 TransactionHelperResult out
= helper
.output();
3683 EXPECT_EQ(OK
, out
.rv
);
3684 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3685 EXPECT_EQ("hello!", out
.response_data
);
3688 // In this test, we enable compression, but get a uncompressed SynReply from
3689 // the server. Verify that teardown is all clean.
3690 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3691 if (spdy_util_
.spdy_version() >= SPDY4
) {
3692 // HPACK doesn't use deflate compression.
3695 scoped_ptr
<SpdyFrame
> compressed(
3696 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
, true));
3697 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3698 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3699 MockWrite writes
[] = {CreateMockWrite(*compressed
), CreateMockWrite(*goaway
)};
3701 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3702 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3703 MockRead reads
[] = {
3704 CreateMockRead(*resp
),
3707 DelayedSocketData
data(1, reads
, arraysize(reads
),
3708 writes
, arraysize(writes
));
3709 SpdySessionDependencies
* session_deps
=
3710 CreateSpdySessionDependencies(GetParam());
3711 session_deps
->enable_compression
= true;
3712 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3713 BoundNetLog(), GetParam(), session_deps
);
3714 helper
.RunToCompletion(&data
);
3715 TransactionHelperResult out
= helper
.output();
3716 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3720 // Test that the NetLog contains good data for a simple GET request.
3721 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3722 static const char* const kExtraHeaders
[] = {
3723 "user-agent", "Chrome",
3725 scoped_ptr
<SpdyFrame
> req(
3726 spdy_util_
.ConstructSpdyGet(kExtraHeaders
, 1, false, 1, LOWEST
, true));
3727 MockWrite writes
[] = { CreateMockWrite(*req
) };
3729 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3730 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3731 MockRead reads
[] = {
3732 CreateMockRead(*resp
),
3733 CreateMockRead(*body
),
3734 MockRead(ASYNC
, 0, 0) // EOF
3737 CapturingBoundNetLog log
;
3739 DelayedSocketData
data(1, reads
, arraysize(reads
),
3740 writes
, arraysize(writes
));
3741 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3743 log
.bound(), GetParam(), NULL
);
3744 helper
.RunToCompletion(&data
);
3745 TransactionHelperResult out
= helper
.output();
3746 EXPECT_EQ(OK
, out
.rv
);
3747 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3748 EXPECT_EQ("hello!", out
.response_data
);
3750 // Check that the NetLog was filled reasonably.
3751 // This test is intentionally non-specific about the exact ordering of the
3752 // log; instead we just check to make sure that certain events exist, and that
3753 // they are in the right order.
3754 net::CapturingNetLog::CapturedEntryList entries
;
3755 log
.GetEntries(&entries
);
3757 EXPECT_LT(0u, entries
.size());
3759 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3760 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3761 net::NetLog::PHASE_BEGIN
);
3762 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3763 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3764 net::NetLog::PHASE_END
);
3765 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3766 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3767 net::NetLog::PHASE_BEGIN
);
3768 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3770 net::NetLog::PHASE_END
);
3771 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3773 net::NetLog::PHASE_BEGIN
);
3774 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3775 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3776 net::NetLog::PHASE_END
);
3778 // Check that we logged all the headers correctly
3779 pos
= net::ExpectLogContainsSomewhere(
3781 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3782 net::NetLog::PHASE_NONE
);
3784 base::ListValue
* header_list
;
3785 ASSERT_TRUE(entries
[pos
].params
.get());
3786 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3788 std::vector
<std::string
> expected
;
3789 expected
.push_back(std::string(spdy_util_
.GetHostKey()) + ": www.google.com");
3790 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3791 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": http");
3792 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3793 expected
.push_back("user-agent: Chrome");
3794 if (spdy_util_
.spdy_version() < SPDY4
) {
3795 // SPDY4/HTTP2 eliminates use of the :version header.
3796 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3798 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3799 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3800 it
!= expected
.end();
3802 base::StringValue
header(*it
);
3803 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3804 "Header not found: " << *it
;
3808 // Since we buffer the IO from the stream to the renderer, this test verifies
3809 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3810 // on the network, but issued a Read for only 5 of those bytes) that the data
3811 // flow still works correctly.
3812 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3813 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3815 scoped_ptr
<SpdyFrame
> req(
3816 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3817 MockWrite writes
[] = { CreateMockWrite(*req
) };
3819 // 2 data frames in a single read.
3820 scoped_ptr
<SpdyFrame
> data_frame_1(
3821 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3822 scoped_ptr
<SpdyFrame
> data_frame_2(
3823 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3824 const SpdyFrame
* data_frames
[2] = {
3828 char combined_data_frames
[100];
3829 int combined_data_frames_len
=
3830 CombineFrames(data_frames
, arraysize(data_frames
),
3831 combined_data_frames
, arraysize(combined_data_frames
));
3832 scoped_ptr
<SpdyFrame
> last_frame(
3833 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3835 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3836 MockRead reads
[] = {
3837 CreateMockRead(*resp
),
3838 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3839 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3840 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3841 CreateMockRead(*last_frame
),
3842 MockRead(ASYNC
, 0, 0) // EOF
3845 DelayedSocketData
data(1, reads
, arraysize(reads
),
3846 writes
, arraysize(writes
));
3848 TestCompletionCallback callback
;
3850 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3851 BoundNetLog(), GetParam(), NULL
);
3852 helper
.RunPreTestSetup();
3853 helper
.AddData(&data
);
3854 HttpNetworkTransaction
* trans
= helper
.trans();
3855 int rv
= trans
->Start(
3856 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3857 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3859 TransactionHelperResult out
= helper
.output();
3860 out
.rv
= callback
.WaitForResult();
3861 EXPECT_EQ(out
.rv
, OK
);
3863 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3864 EXPECT_TRUE(response
->headers
.get() != NULL
);
3865 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3866 out
.status_line
= response
->headers
->GetStatusLine();
3867 out
.response_info
= *response
; // Make a copy so we can verify.
3870 TestCompletionCallback read_callback
;
3872 std::string content
;
3874 // Read small chunks at a time.
3875 const int kSmallReadSize
= 3;
3876 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3877 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3878 if (rv
== net::ERR_IO_PENDING
) {
3879 data
.CompleteRead();
3880 rv
= read_callback
.WaitForResult();
3883 content
.append(buf
->data(), rv
);
3884 } else if (rv
< 0) {
3889 out
.response_data
.swap(content
);
3891 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3892 // MockClientSocketFactory) are still alive.
3893 base::RunLoop().RunUntilIdle();
3895 // Verify that we consumed all test data.
3896 helper
.VerifyDataConsumed();
3898 EXPECT_EQ(OK
, out
.rv
);
3899 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3900 EXPECT_EQ("goodbye world", out
.response_data
);
3903 // Verify that basic buffering works; when multiple data frames arrive
3904 // at the same time, ensure that we don't notify a read completion for
3905 // each data frame individually.
3906 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3907 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3909 scoped_ptr
<SpdyFrame
> req(
3910 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3911 MockWrite writes
[] = { CreateMockWrite(*req
) };
3913 // 4 data frames in a single read.
3914 scoped_ptr
<SpdyFrame
> data_frame(
3915 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3916 scoped_ptr
<SpdyFrame
> data_frame_fin(
3917 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3918 const SpdyFrame
* data_frames
[4] = {
3922 data_frame_fin
.get()
3924 char combined_data_frames
[100];
3925 int combined_data_frames_len
=
3926 CombineFrames(data_frames
, arraysize(data_frames
),
3927 combined_data_frames
, arraysize(combined_data_frames
));
3929 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3930 MockRead reads
[] = {
3931 CreateMockRead(*resp
),
3932 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3933 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3934 MockRead(ASYNC
, 0, 0) // EOF
3937 DelayedSocketData
data(1, reads
, arraysize(reads
),
3938 writes
, arraysize(writes
));
3940 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3941 BoundNetLog(), GetParam(), NULL
);
3942 helper
.RunPreTestSetup();
3943 helper
.AddData(&data
);
3944 HttpNetworkTransaction
* trans
= helper
.trans();
3946 TestCompletionCallback callback
;
3947 int rv
= trans
->Start(
3948 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3949 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3951 TransactionHelperResult out
= helper
.output();
3952 out
.rv
= callback
.WaitForResult();
3953 EXPECT_EQ(out
.rv
, OK
);
3955 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3956 EXPECT_TRUE(response
->headers
.get() != NULL
);
3957 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3958 out
.status_line
= response
->headers
->GetStatusLine();
3959 out
.response_info
= *response
; // Make a copy so we can verify.
3962 TestCompletionCallback read_callback
;
3964 std::string content
;
3965 int reads_completed
= 0;
3967 // Read small chunks at a time.
3968 const int kSmallReadSize
= 14;
3969 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3970 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3971 if (rv
== net::ERR_IO_PENDING
) {
3972 data
.CompleteRead();
3973 rv
= read_callback
.WaitForResult();
3976 EXPECT_EQ(kSmallReadSize
, rv
);
3977 content
.append(buf
->data(), rv
);
3978 } else if (rv
< 0) {
3979 FAIL() << "Unexpected read error: " << rv
;
3984 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3986 out
.response_data
.swap(content
);
3988 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3989 // MockClientSocketFactory) are still alive.
3990 base::RunLoop().RunUntilIdle();
3992 // Verify that we consumed all test data.
3993 helper
.VerifyDataConsumed();
3995 EXPECT_EQ(OK
, out
.rv
);
3996 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3997 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4000 // Verify the case where we buffer data but read it after it has been buffered.
4001 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
4002 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4004 scoped_ptr
<SpdyFrame
> req(
4005 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4006 MockWrite writes
[] = { CreateMockWrite(*req
) };
4008 // 5 data frames in a single read.
4009 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4010 scoped_ptr
<SpdyFrame
> data_frame(
4011 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4012 scoped_ptr
<SpdyFrame
> data_frame_fin(
4013 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4014 const SpdyFrame
* frames
[5] = {reply
.get(), data_frame
.get(), data_frame
.get(),
4015 data_frame
.get(), data_frame_fin
.get()};
4016 char combined_frames
[200];
4017 int combined_frames_len
=
4018 CombineFrames(frames
, arraysize(frames
),
4019 combined_frames
, arraysize(combined_frames
));
4021 MockRead reads
[] = {
4022 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4023 MockRead(ASYNC
, 0, 0) // EOF
4026 DelayedSocketData
data(1, reads
, arraysize(reads
),
4027 writes
, arraysize(writes
));
4029 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4030 BoundNetLog(), GetParam(), NULL
);
4031 helper
.RunPreTestSetup();
4032 helper
.AddData(&data
);
4033 HttpNetworkTransaction
* trans
= helper
.trans();
4035 TestCompletionCallback callback
;
4036 int rv
= trans
->Start(
4037 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4038 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4040 TransactionHelperResult out
= helper
.output();
4041 out
.rv
= callback
.WaitForResult();
4042 EXPECT_EQ(out
.rv
, OK
);
4044 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4045 EXPECT_TRUE(response
->headers
.get() != NULL
);
4046 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4047 out
.status_line
= response
->headers
->GetStatusLine();
4048 out
.response_info
= *response
; // Make a copy so we can verify.
4051 TestCompletionCallback read_callback
;
4053 std::string content
;
4054 int reads_completed
= 0;
4056 // Read small chunks at a time.
4057 const int kSmallReadSize
= 14;
4058 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4059 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4061 EXPECT_EQ(kSmallReadSize
, rv
);
4062 content
.append(buf
->data(), rv
);
4063 } else if (rv
< 0) {
4064 FAIL() << "Unexpected read error: " << rv
;
4069 EXPECT_EQ(3, reads_completed
);
4071 out
.response_data
.swap(content
);
4073 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4074 // MockClientSocketFactory) are still alive.
4075 base::RunLoop().RunUntilIdle();
4077 // Verify that we consumed all test data.
4078 helper
.VerifyDataConsumed();
4080 EXPECT_EQ(OK
, out
.rv
);
4081 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4082 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4085 // Verify the case where we buffer data and close the connection.
4086 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4087 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4089 scoped_ptr
<SpdyFrame
> req(
4090 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4091 MockWrite writes
[] = { CreateMockWrite(*req
) };
4093 // All data frames in a single read.
4094 // NOTE: We don't FIN the stream.
4095 scoped_ptr
<SpdyFrame
> data_frame(
4096 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4097 const SpdyFrame
* data_frames
[4] = {
4103 char combined_data_frames
[100];
4104 int combined_data_frames_len
=
4105 CombineFrames(data_frames
, arraysize(data_frames
),
4106 combined_data_frames
, arraysize(combined_data_frames
));
4107 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4108 MockRead reads
[] = {
4109 CreateMockRead(*resp
),
4110 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4111 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4112 MockRead(ASYNC
, 0, 0) // EOF
4115 DelayedSocketData
data(1, reads
, arraysize(reads
),
4116 writes
, arraysize(writes
));
4118 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4119 BoundNetLog(), GetParam(), NULL
);
4120 helper
.RunPreTestSetup();
4121 helper
.AddData(&data
);
4122 HttpNetworkTransaction
* trans
= helper
.trans();
4124 TestCompletionCallback callback
;
4126 int rv
= trans
->Start(
4127 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4128 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4130 TransactionHelperResult out
= helper
.output();
4131 out
.rv
= callback
.WaitForResult();
4132 EXPECT_EQ(out
.rv
, OK
);
4134 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4135 EXPECT_TRUE(response
->headers
.get() != NULL
);
4136 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4137 out
.status_line
= response
->headers
->GetStatusLine();
4138 out
.response_info
= *response
; // Make a copy so we can verify.
4141 TestCompletionCallback read_callback
;
4143 std::string content
;
4144 int reads_completed
= 0;
4146 // Read small chunks at a time.
4147 const int kSmallReadSize
= 14;
4148 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4149 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4150 if (rv
== net::ERR_IO_PENDING
) {
4151 data
.CompleteRead();
4152 rv
= read_callback
.WaitForResult();
4155 content
.append(buf
->data(), rv
);
4156 } else if (rv
< 0) {
4157 // This test intentionally closes the connection, and will get an error.
4158 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4164 EXPECT_EQ(0, reads_completed
);
4166 out
.response_data
.swap(content
);
4168 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4169 // MockClientSocketFactory) are still alive.
4170 base::RunLoop().RunUntilIdle();
4172 // Verify that we consumed all test data.
4173 helper
.VerifyDataConsumed();
4176 // Verify the case where we buffer data and cancel the transaction.
4177 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4178 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4180 scoped_ptr
<SpdyFrame
> req(
4181 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4182 scoped_ptr
<SpdyFrame
> rst(
4183 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
4184 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*rst
)};
4186 // NOTE: We don't FIN the stream.
4187 scoped_ptr
<SpdyFrame
> data_frame(
4188 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4190 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4191 MockRead reads
[] = {
4192 CreateMockRead(*resp
),
4193 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4194 CreateMockRead(*data_frame
),
4195 MockRead(ASYNC
, 0, 0) // EOF
4198 DelayedSocketData
data(1, reads
, arraysize(reads
),
4199 writes
, arraysize(writes
));
4201 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4202 BoundNetLog(), GetParam(), NULL
);
4203 helper
.RunPreTestSetup();
4204 helper
.AddData(&data
);
4205 HttpNetworkTransaction
* trans
= helper
.trans();
4206 TestCompletionCallback callback
;
4208 int rv
= trans
->Start(
4209 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4212 TransactionHelperResult out
= helper
.output();
4213 out
.rv
= callback
.WaitForResult();
4214 EXPECT_EQ(out
.rv
, OK
);
4216 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4217 EXPECT_TRUE(response
->headers
.get() != NULL
);
4218 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4219 out
.status_line
= response
->headers
->GetStatusLine();
4220 out
.response_info
= *response
; // Make a copy so we can verify.
4223 TestCompletionCallback read_callback
;
4225 const int kReadSize
= 256;
4226 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4227 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4228 ASSERT_EQ(net::ERR_IO_PENDING
, rv
) << "Unexpected read: " << rv
;
4230 // Complete the read now, which causes buffering to start.
4231 data
.CompleteRead();
4232 // Destroy the transaction, causing the stream to get cancelled
4233 // and orphaning the buffered IO task.
4234 helper
.ResetTrans();
4236 // Flush the MessageLoop; this will cause the buffered IO task
4237 // to run for the final time.
4238 base::RunLoop().RunUntilIdle();
4240 // Verify that we consumed all test data.
4241 helper
.VerifyDataConsumed();
4244 // Test that if the server requests persistence of settings, that we save
4245 // the settings in the HttpServerProperties.
4246 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4247 if (spdy_util_
.spdy_version() >= SPDY4
) {
4248 // SPDY4 doesn't support settings persistence.
4251 static const SpdyHeaderInfo kSynReplyInfo
= {
4252 SYN_REPLY
, // Syn Reply
4254 0, // Associated Stream ID
4255 ConvertRequestPriorityToSpdyPriority(
4256 LOWEST
, spdy_util_
.spdy_version()),
4257 kSpdyCredentialSlotUnused
,
4258 CONTROL_FLAG_NONE
, // Control Flags
4259 false, // Compressed
4260 RST_STREAM_INVALID
, // Status
4263 DATA_FLAG_NONE
// Data Flags
4266 BoundNetLog net_log
;
4267 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4268 net_log
, GetParam(), NULL
);
4269 helper
.RunPreTestSetup();
4271 // Verify that no settings exist initially.
4272 HostPortPair
host_port_pair("www.google.com", helper
.port());
4273 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4274 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4275 host_port_pair
).empty());
4277 // Construct the request.
4278 scoped_ptr
<SpdyFrame
> req(
4279 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4280 MockWrite writes
[] = { CreateMockWrite(*req
) };
4282 // Construct the reply.
4283 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4284 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4285 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4286 scoped_ptr
<SpdyFrame
> reply(
4287 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4289 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4290 unsigned int kSampleValue1
= 0x0a0a0a0a;
4291 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4292 unsigned int kSampleValue2
= 0x0b0b0b0b;
4293 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4294 unsigned int kSampleValue3
= 0x0c0c0c0c;
4295 scoped_ptr
<SpdyFrame
> settings_frame
;
4297 // Construct the SETTINGS frame.
4298 SettingsMap settings
;
4299 // First add a persisted setting.
4300 settings
[kSampleId1
] =
4301 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4302 // Next add a non-persisted setting.
4303 settings
[kSampleId2
] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4305 // Next add another persisted setting.
4306 settings
[kSampleId3
] =
4307 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4308 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4311 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4312 MockRead reads
[] = {
4313 CreateMockRead(*reply
),
4314 CreateMockRead(*body
),
4315 CreateMockRead(*settings_frame
),
4316 MockRead(ASYNC
, 0, 0) // EOF
4319 DelayedSocketData
data(1, reads
, arraysize(reads
),
4320 writes
, arraysize(writes
));
4321 helper
.AddData(&data
);
4322 helper
.RunDefaultTest();
4323 helper
.VerifyDataConsumed();
4324 TransactionHelperResult out
= helper
.output();
4325 EXPECT_EQ(OK
, out
.rv
);
4326 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4327 EXPECT_EQ("hello!", out
.response_data
);
4330 // Verify we had two persisted settings.
4331 const SettingsMap
& settings_map
=
4332 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4334 ASSERT_EQ(2u, settings_map
.size());
4336 // Verify the first persisted setting.
4337 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4338 EXPECT_TRUE(it1
!= settings_map
.end());
4339 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4340 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4341 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4343 // Verify the second persisted setting.
4344 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4345 EXPECT_TRUE(it3
!= settings_map
.end());
4346 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4347 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4348 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4352 // Test that when there are settings saved that they are sent back to the
4353 // server upon session establishment.
4354 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4355 if (spdy_util_
.spdy_version() >= SPDY4
) {
4356 // SPDY4 doesn't support settings persistence.
4359 static const SpdyHeaderInfo kSynReplyInfo
= {
4360 SYN_REPLY
, // Syn Reply
4362 0, // Associated Stream ID
4363 ConvertRequestPriorityToSpdyPriority(
4364 LOWEST
, spdy_util_
.spdy_version()),
4365 kSpdyCredentialSlotUnused
,
4366 CONTROL_FLAG_NONE
, // Control Flags
4367 false, // Compressed
4368 RST_STREAM_INVALID
, // Status
4371 DATA_FLAG_NONE
// Data Flags
4374 BoundNetLog net_log
;
4375 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4376 net_log
, GetParam(), NULL
);
4377 helper
.RunPreTestSetup();
4379 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4381 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4382 pool_peer
.SetEnableSendingInitialData(true);
4384 // Verify that no settings exist initially.
4385 HostPortPair
host_port_pair("www.google.com", helper
.port());
4386 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4387 host_port_pair
).empty());
4389 const SpdySettingsIds kSampleId1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
4390 unsigned int kSampleValue1
= 0x0a0a0a0a;
4391 const SpdySettingsIds kSampleId2
= SETTINGS_INITIAL_WINDOW_SIZE
;
4392 unsigned int kSampleValue2
= 0x0c0c0c0c;
4394 // First add a persisted setting.
4395 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4398 SETTINGS_FLAG_PLEASE_PERSIST
,
4401 // Next add another persisted setting.
4402 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4405 SETTINGS_FLAG_PLEASE_PERSIST
,
4408 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4409 host_port_pair
).size());
4411 // Construct the initial SETTINGS frame.
4412 SettingsMap initial_settings
;
4413 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4414 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4415 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4416 spdy_util_
.ConstructSpdySettings(initial_settings
));
4418 // Construct the initial window update.
4419 scoped_ptr
<SpdyFrame
> initial_window_update(
4420 spdy_util_
.ConstructSpdyWindowUpdate(
4421 kSessionFlowControlStreamId
,
4422 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
4424 // Construct the persisted SETTINGS frame.
4425 const SettingsMap
& settings
=
4426 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4428 scoped_ptr
<SpdyFrame
> settings_frame(
4429 spdy_util_
.ConstructSpdySettings(settings
));
4431 // Construct the request.
4432 scoped_ptr
<SpdyFrame
> req(
4433 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4435 std::vector
<MockWrite
> writes
;
4436 if (GetParam().protocol
== kProtoSPDY4
) {
4439 kHttp2ConnectionHeaderPrefix
,
4440 kHttp2ConnectionHeaderPrefixSize
));
4442 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4443 if (GetParam().protocol
>= kProtoSPDY31
) {
4444 writes
.push_back(CreateMockWrite(*initial_window_update
));
4446 writes
.push_back(CreateMockWrite(*settings_frame
));
4447 writes
.push_back(CreateMockWrite(*req
));
4449 // Construct the reply.
4450 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4451 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4452 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4453 scoped_ptr
<SpdyFrame
> reply(
4454 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4456 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4457 MockRead reads
[] = {
4458 CreateMockRead(*reply
),
4459 CreateMockRead(*body
),
4460 MockRead(ASYNC
, 0, 0) // EOF
4463 DelayedSocketData
data(2, reads
, arraysize(reads
),
4464 vector_as_array(&writes
), writes
.size());
4465 helper
.AddData(&data
);
4466 helper
.RunDefaultTest();
4467 helper
.VerifyDataConsumed();
4468 TransactionHelperResult out
= helper
.output();
4469 EXPECT_EQ(OK
, out
.rv
);
4470 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4471 EXPECT_EQ("hello!", out
.response_data
);
4474 // Verify we had two persisted settings.
4475 const SettingsMap
& settings_map
=
4476 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4478 ASSERT_EQ(2u, settings_map
.size());
4480 // Verify the first persisted setting.
4481 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4482 EXPECT_TRUE(it1
!= settings_map
.end());
4483 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4484 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4485 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4487 // Verify the second persisted setting.
4488 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4489 EXPECT_TRUE(it2
!= settings_map
.end());
4490 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4491 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4492 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4496 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4497 scoped_ptr
<SpdyFrame
> req(
4498 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4499 MockWrite writes
[] = { CreateMockWrite(*req
) };
4501 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4502 MockRead reads
[] = {
4503 CreateMockRead(*go_away
),
4506 DelayedSocketData
data(1, reads
, arraysize(reads
),
4507 writes
, arraysize(writes
));
4508 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4509 BoundNetLog(), GetParam(), NULL
);
4510 helper
.AddData(&data
);
4511 helper
.RunToCompletion(&data
);
4512 TransactionHelperResult out
= helper
.output();
4513 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4516 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4517 scoped_ptr
<SpdyFrame
> req(
4518 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4519 MockWrite writes
[] = { CreateMockWrite(*req
) };
4521 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4522 MockRead reads
[] = {
4523 CreateMockRead(*resp
),
4524 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4527 DelayedSocketData
data(1, reads
, arraysize(reads
),
4528 writes
, arraysize(writes
));
4530 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4531 log
, GetParam(), NULL
);
4532 helper
.RunPreTestSetup();
4533 helper
.AddData(&data
);
4534 HttpNetworkTransaction
* trans
= helper
.trans();
4536 TestCompletionCallback callback
;
4537 TransactionHelperResult out
;
4538 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4540 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4541 out
.rv
= callback
.WaitForResult();
4542 EXPECT_EQ(out
.rv
, OK
);
4544 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4545 EXPECT_TRUE(response
->headers
.get() != NULL
);
4546 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4547 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4548 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4550 // Verify that we consumed all test data.
4551 helper
.VerifyDataConsumed();
4554 // Test to make sure we can correctly connect through a proxy.
4555 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4556 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4557 BoundNetLog(), GetParam(), NULL
);
4558 helper
.session_deps().reset(CreateSpdySessionDependencies(
4560 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4561 helper
.SetSession(make_scoped_refptr(
4562 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4563 helper
.RunPreTestSetup();
4564 HttpNetworkTransaction
* trans
= helper
.trans();
4566 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4567 "Host: www.google.com\r\n"
4568 "Proxy-Connection: keep-alive\r\n\r\n"};
4569 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4570 "Host: www.google.com\r\n"
4571 "Proxy-Connection: keep-alive\r\n\r\n"};
4572 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4573 scoped_ptr
<SpdyFrame
> req(
4574 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4575 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4576 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4578 MockWrite writes_SPDYNPN
[] = {
4579 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4580 CreateMockWrite(*req
, 2),
4582 MockRead reads_SPDYNPN
[] = {
4583 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4584 CreateMockRead(*resp
, 3),
4585 CreateMockRead(*body
.get(), 4),
4586 MockRead(ASYNC
, 0, 0, 5),
4589 MockWrite writes_SPDYSSL
[] = {
4590 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4591 CreateMockWrite(*req
, 2),
4593 MockRead reads_SPDYSSL
[] = {
4594 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4595 CreateMockRead(*resp
, 3),
4596 CreateMockRead(*body
.get(), 4),
4597 MockRead(ASYNC
, 0, 0, 5),
4600 MockWrite writes_SPDYNOSSL
[] = {
4601 CreateMockWrite(*req
, 0),
4604 MockRead reads_SPDYNOSSL
[] = {
4605 CreateMockRead(*resp
, 1),
4606 CreateMockRead(*body
.get(), 2),
4607 MockRead(ASYNC
, 0, 0, 3),
4610 scoped_ptr
<OrderedSocketData
> data
;
4611 switch (GetParam().ssl_type
) {
4613 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4614 arraysize(reads_SPDYNOSSL
),
4616 arraysize(writes_SPDYNOSSL
)));
4619 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4620 arraysize(reads_SPDYSSL
),
4622 arraysize(writes_SPDYSSL
)));
4625 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4626 arraysize(reads_SPDYNPN
),
4628 arraysize(writes_SPDYNPN
)));
4634 helper
.AddData(data
.get());
4635 TestCompletionCallback callback
;
4637 int rv
= trans
->Start(
4638 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4641 rv
= callback
.WaitForResult();
4644 // Verify the SYN_REPLY.
4645 HttpResponseInfo response
= *trans
->GetResponseInfo();
4646 EXPECT_TRUE(response
.headers
.get() != NULL
);
4647 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4649 std::string response_data
;
4650 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4651 EXPECT_EQ("hello!", response_data
);
4652 helper
.VerifyDataConsumed();
4655 // Test to make sure we can correctly connect through a proxy to www.google.com,
4656 // if there already exists a direct spdy connection to www.google.com. See
4657 // http://crbug.com/49874
4658 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4659 // When setting up the first transaction, we store the SpdySessionPool so that
4660 // we can use the same pool in the second transaction.
4661 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4662 BoundNetLog(), GetParam(), NULL
);
4664 // Use a proxy service which returns a proxy fallback list from DIRECT to
4665 // myproxy:70. For this test there will be no fallback, so it is equivalent
4666 // to simply DIRECT. The reason for appending the second proxy is to verify
4667 // that the session pool key used does is just "DIRECT".
4668 helper
.session_deps().reset(CreateSpdySessionDependencies(
4670 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4671 helper
.SetSession(make_scoped_refptr(
4672 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4674 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4675 helper
.RunPreTestSetup();
4677 // Construct and send a simple GET request.
4678 scoped_ptr
<SpdyFrame
> req(
4679 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4680 MockWrite writes
[] = {
4681 CreateMockWrite(*req
, 1),
4684 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4685 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4686 MockRead reads
[] = {
4687 CreateMockRead(*resp
, 2),
4688 CreateMockRead(*body
, 3),
4689 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4690 MockRead(ASYNC
, 0, 5) // EOF
4692 OrderedSocketData
data(reads
, arraysize(reads
),
4693 writes
, arraysize(writes
));
4694 helper
.AddData(&data
);
4695 HttpNetworkTransaction
* trans
= helper
.trans();
4697 TestCompletionCallback callback
;
4698 TransactionHelperResult out
;
4699 out
.rv
= trans
->Start(
4700 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4702 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4703 out
.rv
= callback
.WaitForResult();
4704 EXPECT_EQ(out
.rv
, OK
);
4706 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4707 EXPECT_TRUE(response
->headers
.get() != NULL
);
4708 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4709 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4710 EXPECT_EQ(OK
, out
.rv
);
4711 out
.status_line
= response
->headers
->GetStatusLine();
4712 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4713 EXPECT_EQ("hello!", out
.response_data
);
4715 // Check that the SpdySession is still in the SpdySessionPool.
4716 HostPortPair
host_port_pair("www.google.com", helper
.port());
4717 SpdySessionKey
session_pool_key_direct(
4718 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4719 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4720 SpdySessionKey
session_pool_key_proxy(
4722 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4723 PRIVACY_MODE_DISABLED
);
4724 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4726 // Set up data for the proxy connection.
4727 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4728 "Host: www.google.com\r\n"
4729 "Proxy-Connection: keep-alive\r\n\r\n"};
4730 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4731 "Host: www.google.com\r\n"
4732 "Proxy-Connection: keep-alive\r\n\r\n"};
4733 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4734 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4735 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4736 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4737 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4739 MockWrite writes_SPDYNPN
[] = {
4740 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4741 CreateMockWrite(*req2
, 2),
4743 MockRead reads_SPDYNPN
[] = {
4744 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4745 CreateMockRead(*resp2
, 3),
4746 CreateMockRead(*body2
, 4),
4747 MockRead(ASYNC
, 0, 5) // EOF
4750 MockWrite writes_SPDYNOSSL
[] = {
4751 CreateMockWrite(*req2
, 0),
4753 MockRead reads_SPDYNOSSL
[] = {
4754 CreateMockRead(*resp2
, 1),
4755 CreateMockRead(*body2
, 2),
4756 MockRead(ASYNC
, 0, 3) // EOF
4759 MockWrite writes_SPDYSSL
[] = {
4760 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4761 CreateMockWrite(*req2
, 2),
4763 MockRead reads_SPDYSSL
[] = {
4764 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4765 CreateMockRead(*resp2
, 3),
4766 CreateMockRead(*body2
, 4),
4767 MockRead(ASYNC
, 0, 0, 5),
4770 scoped_ptr
<OrderedSocketData
> data_proxy
;
4771 switch (GetParam().ssl_type
) {
4773 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
4774 arraysize(reads_SPDYNPN
),
4776 arraysize(writes_SPDYNPN
)));
4779 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4780 arraysize(reads_SPDYNOSSL
),
4782 arraysize(writes_SPDYNOSSL
)));
4785 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
4786 arraysize(reads_SPDYSSL
),
4788 arraysize(writes_SPDYSSL
)));
4794 // Create another request to www.google.com, but this time through a proxy.
4795 HttpRequestInfo request_proxy
;
4796 request_proxy
.method
= "GET";
4797 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
4798 request_proxy
.load_flags
= 0;
4799 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
4800 CreateSpdySessionDependencies(GetParam()));
4801 // Ensure that this transaction uses the same SpdySessionPool.
4802 scoped_refptr
<HttpNetworkSession
> session_proxy(
4803 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4804 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
4805 BoundNetLog(), GetParam(), NULL
);
4806 HttpNetworkSessionPeer
session_peer(session_proxy
);
4807 scoped_ptr
<net::ProxyService
> proxy_service(
4808 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4809 session_peer
.SetProxyService(proxy_service
.get());
4810 helper_proxy
.session_deps().swap(ssd_proxy
);
4811 helper_proxy
.SetSession(session_proxy
);
4812 helper_proxy
.RunPreTestSetup();
4813 helper_proxy
.AddData(data_proxy
.get());
4815 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4816 TestCompletionCallback callback_proxy
;
4817 int rv
= trans_proxy
->Start(
4818 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
4819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4820 rv
= callback_proxy
.WaitForResult();
4823 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4824 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
4825 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4827 std::string response_data
;
4828 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4829 EXPECT_EQ("hello!", response_data
);
4831 data
.CompleteRead();
4832 helper_proxy
.VerifyDataConsumed();
4835 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4836 // on a new connection, if the connection was previously known to be good.
4837 // This can happen when a server reboots without saying goodbye, or when
4838 // we're behind a NAT that masked the RST.
4839 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4840 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4841 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4842 MockRead reads
[] = {
4843 CreateMockRead(*resp
),
4844 CreateMockRead(*body
),
4845 MockRead(ASYNC
, ERR_IO_PENDING
),
4846 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
4849 MockRead reads2
[] = {
4850 CreateMockRead(*resp
),
4851 CreateMockRead(*body
),
4852 MockRead(ASYNC
, 0, 0) // EOF
4855 // This test has a couple of variants.
4857 // Induce the RST while waiting for our transaction to send.
4858 VARIANT_RST_DURING_SEND_COMPLETION
,
4859 // Induce the RST while waiting for our transaction to read.
4860 // In this case, the send completed - everything copied into the SNDBUF.
4861 VARIANT_RST_DURING_READ_COMPLETION
4864 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4865 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4867 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
4869 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
4871 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4872 BoundNetLog(), GetParam(), NULL
);
4873 helper
.AddData(&data1
);
4874 helper
.AddData(&data2
);
4875 helper
.RunPreTestSetup();
4877 for (int i
= 0; i
< 2; ++i
) {
4878 scoped_ptr
<HttpNetworkTransaction
> trans(
4879 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
4881 TestCompletionCallback callback
;
4882 int rv
= trans
->Start(
4883 &helper
.request(), callback
.callback(), BoundNetLog());
4884 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4885 // On the second transaction, we trigger the RST.
4887 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4888 // Writes to the socket complete asynchronously on SPDY by running
4889 // through the message loop. Complete the write here.
4890 base::RunLoop().RunUntilIdle();
4893 // Now schedule the ERR_CONNECTION_RESET.
4894 EXPECT_EQ(3u, data1
.read_index());
4895 data1
.CompleteRead();
4896 EXPECT_EQ(4u, data1
.read_index());
4898 rv
= callback
.WaitForResult();
4901 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4902 ASSERT_TRUE(response
!= NULL
);
4903 EXPECT_TRUE(response
->headers
.get() != NULL
);
4904 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4905 std::string response_data
;
4906 rv
= ReadTransaction(trans
.get(), &response_data
);
4908 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4909 EXPECT_EQ("hello!", response_data
);
4912 helper
.VerifyDataConsumed();
4916 // Test that turning SPDY on and off works properly.
4917 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4918 HttpStreamFactory::set_spdy_enabled(true);
4919 scoped_ptr
<SpdyFrame
> req(
4920 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4921 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4923 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4924 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4925 MockRead spdy_reads
[] = {
4926 CreateMockRead(*resp
),
4927 CreateMockRead(*body
),
4928 MockRead(ASYNC
, 0, 0) // EOF
4931 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
4932 spdy_writes
, arraysize(spdy_writes
));
4933 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4934 BoundNetLog(), GetParam(), NULL
);
4935 helper
.RunToCompletion(&data
);
4936 TransactionHelperResult out
= helper
.output();
4937 EXPECT_EQ(OK
, out
.rv
);
4938 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4939 EXPECT_EQ("hello!", out
.response_data
);
4941 net::HttpStreamFactory::set_spdy_enabled(false);
4942 MockRead http_reads
[] = {
4943 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4944 MockRead("hello from http"),
4945 MockRead(SYNCHRONOUS
, OK
),
4947 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
4948 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
4949 BoundNetLog(), GetParam(), NULL
);
4950 helper2
.SetSpdyDisabled();
4951 helper2
.RunToCompletion(&data2
);
4952 TransactionHelperResult out2
= helper2
.output();
4953 EXPECT_EQ(OK
, out2
.rv
);
4954 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
4955 EXPECT_EQ("hello from http", out2
.response_data
);
4957 net::HttpStreamFactory::set_spdy_enabled(true);
4960 // Tests that Basic authentication works over SPDY
4961 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
4962 net::HttpStreamFactory::set_spdy_enabled(true);
4964 // The first request will be a bare GET, the second request will be a
4965 // GET with an Authorization header.
4966 scoped_ptr
<SpdyFrame
> req_get(
4967 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4968 const char* const kExtraAuthorizationHeaders
[] = {
4969 "authorization", "Basic Zm9vOmJhcg=="
4971 scoped_ptr
<SpdyFrame
> req_get_authorization(
4972 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
4973 arraysize(kExtraAuthorizationHeaders
) / 2,
4974 false, 3, LOWEST
, true));
4975 MockWrite spdy_writes
[] = {
4976 CreateMockWrite(*req_get
, 1),
4977 CreateMockWrite(*req_get_authorization
, 4),
4980 // The first response is a 401 authentication challenge, and the second
4981 // response will be a 200 response since the second request includes a valid
4982 // Authorization header.
4983 const char* const kExtraAuthenticationHeaders
[] = {
4985 "Basic realm=\"MyRealm\""
4987 scoped_ptr
<SpdyFrame
> resp_authentication(
4988 spdy_util_
.ConstructSpdySynReplyError(
4989 "401 Authentication Required",
4990 kExtraAuthenticationHeaders
,
4991 arraysize(kExtraAuthenticationHeaders
) / 2,
4993 scoped_ptr
<SpdyFrame
> body_authentication(
4994 spdy_util_
.ConstructSpdyBodyFrame(1, true));
4995 scoped_ptr
<SpdyFrame
> resp_data(
4996 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4997 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
4998 MockRead spdy_reads
[] = {
4999 CreateMockRead(*resp_authentication
, 2),
5000 CreateMockRead(*body_authentication
, 3),
5001 CreateMockRead(*resp_data
, 5),
5002 CreateMockRead(*body_data
, 6),
5003 MockRead(ASYNC
, 0, 7),
5006 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5007 spdy_writes
, arraysize(spdy_writes
));
5008 HttpRequestInfo
request(CreateGetRequest());
5009 BoundNetLog net_log
;
5010 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5011 net_log
, GetParam(), NULL
);
5013 helper
.RunPreTestSetup();
5014 helper
.AddData(&data
);
5015 HttpNetworkTransaction
* trans
= helper
.trans();
5016 TestCompletionCallback callback
;
5017 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5018 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5019 const int rv_start_complete
= callback
.WaitForResult();
5020 EXPECT_EQ(OK
, rv_start_complete
);
5022 // Make sure the response has an auth challenge.
5023 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5024 ASSERT_TRUE(response_start
!= NULL
);
5025 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5026 EXPECT_EQ(401, response_start
->headers
->response_code());
5027 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5028 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5029 ASSERT_TRUE(auth_challenge
!= NULL
);
5030 EXPECT_FALSE(auth_challenge
->is_proxy
);
5031 EXPECT_EQ("basic", auth_challenge
->scheme
);
5032 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5034 // Restart with a username/password.
5035 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5036 base::ASCIIToUTF16("bar"));
5037 TestCompletionCallback callback_restart
;
5038 const int rv_restart
= trans
->RestartWithAuth(
5039 credentials
, callback_restart
.callback());
5040 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5041 const int rv_restart_complete
= callback_restart
.WaitForResult();
5042 EXPECT_EQ(OK
, rv_restart_complete
);
5043 // TODO(cbentzel): This is actually the same response object as before, but
5044 // data has changed.
5045 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5046 ASSERT_TRUE(response_restart
!= NULL
);
5047 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5048 EXPECT_EQ(200, response_restart
->headers
->response_code());
5049 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5052 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5053 scoped_ptr
<SpdyFrame
> stream1_syn(
5054 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5055 scoped_ptr
<SpdyFrame
> stream1_body(
5056 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5057 MockWrite writes
[] = {
5058 CreateMockWrite(*stream1_syn
, 1),
5061 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5062 spdy_util_
.AddUrlToHeaderBlock(
5063 "http://www.google.com/foo.dat", initial_headers
.get());
5064 scoped_ptr
<SpdyFrame
> stream2_syn(
5065 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5067 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5068 (*late_headers
)["hello"] = "bye";
5069 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5070 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5071 scoped_ptr
<SpdyFrame
> stream2_headers(
5072 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5080 scoped_ptr
<SpdyFrame
>
5081 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5082 const char kPushedData
[] = "pushed";
5083 scoped_ptr
<SpdyFrame
> stream2_body(
5084 spdy_util_
.ConstructSpdyBodyFrame(
5085 2, kPushedData
, strlen(kPushedData
), true));
5086 MockRead reads
[] = {
5087 CreateMockRead(*stream1_reply
, 2),
5088 CreateMockRead(*stream2_syn
, 3),
5089 CreateMockRead(*stream2_headers
, 4),
5090 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5091 CreateMockRead(*stream2_body
, 5),
5092 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5095 HttpResponseInfo response
;
5096 HttpResponseInfo response2
;
5097 std::string
expected_push_result("pushed");
5098 OrderedSocketData
data(reads
, arraysize(reads
),
5099 writes
, arraysize(writes
));
5100 RunServerPushTest(&data
,
5103 expected_push_result
);
5105 // Verify the SYN_REPLY.
5106 EXPECT_TRUE(response
.headers
.get() != NULL
);
5107 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5109 // Verify the pushed stream.
5110 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5111 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5114 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5115 // We push a stream and attempt to claim it before the headers come down.
5116 scoped_ptr
<SpdyFrame
> stream1_syn(
5117 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5118 scoped_ptr
<SpdyFrame
> stream1_body(
5119 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5120 MockWrite writes
[] = {
5121 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5124 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5125 spdy_util_
.AddUrlToHeaderBlock(
5126 "http://www.google.com/foo.dat", initial_headers
.get());
5127 scoped_ptr
<SpdyFrame
> stream2_syn(
5128 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5130 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5131 (*late_headers
)["hello"] = "bye";
5132 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5133 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5134 scoped_ptr
<SpdyFrame
> stream2_headers(
5135 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5143 scoped_ptr
<SpdyFrame
>
5144 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5145 const char kPushedData
[] = "pushed";
5146 scoped_ptr
<SpdyFrame
> stream2_body(
5147 spdy_util_
.ConstructSpdyBodyFrame(
5148 2, kPushedData
, strlen(kPushedData
), true));
5149 MockRead reads
[] = {
5150 CreateMockRead(*stream1_reply
, 1),
5151 CreateMockRead(*stream2_syn
, 2),
5152 CreateMockRead(*stream1_body
, 3),
5153 CreateMockRead(*stream2_headers
, 4),
5154 CreateMockRead(*stream2_body
, 5),
5155 MockRead(ASYNC
, 0, 6), // EOF
5158 HttpResponseInfo response
;
5159 HttpResponseInfo response2
;
5160 std::string
expected_push_result("pushed");
5161 DeterministicSocketData
data(reads
, arraysize(reads
),
5162 writes
, arraysize(writes
));
5164 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5165 BoundNetLog(), GetParam(), NULL
);
5166 helper
.SetDeterministic();
5167 helper
.AddDeterministicData(&data
);
5168 helper
.RunPreTestSetup();
5170 HttpNetworkTransaction
* trans
= helper
.trans();
5172 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5173 // and the body of the primary stream, but before we've received the HEADERS
5174 // for the pushed stream.
5177 // Start the transaction.
5178 TestCompletionCallback callback
;
5179 int rv
= trans
->Start(
5180 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5183 rv
= callback
.WaitForResult();
5186 // Request the pushed path. At this point, we've received the push, but the
5187 // headers are not yet complete.
5188 scoped_ptr
<HttpNetworkTransaction
> trans2(
5189 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5191 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5192 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5194 base::RunLoop().RunUntilIdle();
5196 // Read the server push body.
5197 std::string result2
;
5198 ReadResult(trans2
.get(), &data
, &result2
);
5199 // Read the response body.
5201 ReadResult(trans
, &data
, &result
);
5203 // Verify that the received push data is same as the expected push data.
5204 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5205 << "Received data: "
5207 << "||||| Expected data: "
5208 << expected_push_result
;
5210 // Verify the SYN_REPLY.
5211 // Copy the response info, because trans goes away.
5212 response
= *trans
->GetResponseInfo();
5213 response2
= *trans2
->GetResponseInfo();
5215 VerifyStreamsClosed(helper
);
5217 // Verify the SYN_REPLY.
5218 EXPECT_TRUE(response
.headers
.get() != NULL
);
5219 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5221 // Verify the pushed stream.
5222 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5223 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5225 // Read the final EOF (which will close the session)
5228 // Verify that we consumed all test data.
5229 EXPECT_TRUE(data
.at_read_eof());
5230 EXPECT_TRUE(data
.at_write_eof());
5233 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5234 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5235 // We push a stream and attempt to claim it before the headers come down.
5236 scoped_ptr
<SpdyFrame
> stream1_syn(
5237 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5238 scoped_ptr
<SpdyFrame
> stream1_body(
5239 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5240 MockWrite writes
[] = {
5241 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5244 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5245 if (spdy_util_
.spdy_version() < SPDY4
) {
5246 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5247 (*initial_headers
)["alpha"] = "beta";
5249 spdy_util_
.AddUrlToHeaderBlock(
5250 "http://www.google.com/foo.dat", initial_headers
.get());
5251 scoped_ptr
<SpdyFrame
> stream2_syn(
5252 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5254 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5255 (*middle_headers
)["hello"] = "bye";
5256 scoped_ptr
<SpdyFrame
> stream2_headers1(
5257 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5265 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5266 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5267 if (spdy_util_
.spdy_version() < SPDY4
) {
5268 // SPDY4/HTTP2 eliminates use of the :version header.
5269 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5271 scoped_ptr
<SpdyFrame
> stream2_headers2(
5272 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5280 scoped_ptr
<SpdyFrame
>
5281 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5282 const char kPushedData
[] = "pushed";
5283 scoped_ptr
<SpdyFrame
> stream2_body(
5284 spdy_util_
.ConstructSpdyBodyFrame(
5285 2, kPushedData
, strlen(kPushedData
), true));
5286 MockRead reads
[] = {
5287 CreateMockRead(*stream1_reply
, 1),
5288 CreateMockRead(*stream2_syn
, 2),
5289 CreateMockRead(*stream1_body
, 3),
5290 CreateMockRead(*stream2_headers1
, 4),
5291 CreateMockRead(*stream2_headers2
, 5),
5292 CreateMockRead(*stream2_body
, 6),
5293 MockRead(ASYNC
, 0, 7), // EOF
5296 HttpResponseInfo response
;
5297 HttpResponseInfo response2
;
5298 std::string
expected_push_result("pushed");
5299 DeterministicSocketData
data(reads
, arraysize(reads
),
5300 writes
, arraysize(writes
));
5302 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5303 BoundNetLog(), GetParam(), NULL
);
5304 helper
.SetDeterministic();
5305 helper
.AddDeterministicData(&data
);
5306 helper
.RunPreTestSetup();
5308 HttpNetworkTransaction
* trans
= helper
.trans();
5310 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5311 // the first HEADERS frame, and the body of the primary stream, but before
5312 // we've received the final HEADERS for the pushed stream.
5315 // Start the transaction.
5316 TestCompletionCallback callback
;
5317 int rv
= trans
->Start(
5318 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5319 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5321 rv
= callback
.WaitForResult();
5324 // Request the pushed path. At this point, we've received the push, but the
5325 // headers are not yet complete.
5326 scoped_ptr
<HttpNetworkTransaction
> trans2(
5327 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5329 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5330 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5332 base::RunLoop().RunUntilIdle();
5334 // Read the server push body.
5335 std::string result2
;
5336 ReadResult(trans2
.get(), &data
, &result2
);
5337 // Read the response body.
5339 ReadResult(trans
, &data
, &result
);
5341 // Verify that the received push data is same as the expected push data.
5342 EXPECT_EQ(expected_push_result
, result2
);
5344 // Verify the SYN_REPLY.
5345 // Copy the response info, because trans goes away.
5346 response
= *trans
->GetResponseInfo();
5347 response2
= *trans2
->GetResponseInfo();
5349 VerifyStreamsClosed(helper
);
5351 // Verify the SYN_REPLY.
5352 EXPECT_TRUE(response
.headers
.get() != NULL
);
5353 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5355 // Verify the pushed stream.
5356 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5357 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5359 // Verify we got all the headers from all header blocks.
5360 if (spdy_util_
.spdy_version() < SPDY4
)
5361 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5362 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5363 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5365 // Read the final EOF (which will close the session)
5368 // Verify that we consumed all test data.
5369 EXPECT_TRUE(data
.at_read_eof());
5370 EXPECT_TRUE(data
.at_write_eof());
5373 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5374 // We push a stream and attempt to claim it before the headers come down.
5375 scoped_ptr
<SpdyFrame
> stream1_syn(
5376 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5377 scoped_ptr
<SpdyFrame
> stream1_body(
5378 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5379 MockWrite writes
[] = {
5380 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5383 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5384 spdy_util_
.AddUrlToHeaderBlock(
5385 "http://www.google.com/foo.dat", initial_headers
.get());
5386 scoped_ptr
<SpdyFrame
> stream2_syn(
5387 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5389 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5390 (*middle_headers
)["hello"] = "bye";
5391 scoped_ptr
<SpdyFrame
> stream2_headers1(
5392 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5400 scoped_ptr
<SpdyFrame
>
5401 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5402 const char kPushedData
[] = "pushed";
5403 scoped_ptr
<SpdyFrame
> stream2_body(
5404 spdy_util_
.ConstructSpdyBodyFrame(
5405 2, kPushedData
, strlen(kPushedData
), true));
5406 MockRead reads
[] = {
5407 CreateMockRead(*stream1_reply
, 1),
5408 CreateMockRead(*stream2_syn
, 2),
5409 CreateMockRead(*stream1_body
, 3),
5410 CreateMockRead(*stream2_headers1
, 4),
5411 CreateMockRead(*stream2_body
, 5),
5412 MockRead(ASYNC
, 0, 6), // EOF
5415 DeterministicSocketData
data(reads
, arraysize(reads
),
5416 writes
, arraysize(writes
));
5418 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5419 BoundNetLog(), GetParam(), NULL
);
5420 helper
.SetDeterministic();
5421 helper
.AddDeterministicData(&data
);
5422 helper
.RunPreTestSetup();
5424 HttpNetworkTransaction
* trans
= helper
.trans();
5426 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5427 // the first HEADERS frame, and the body of the primary stream, but before
5428 // we've received the final HEADERS for the pushed stream.
5431 // Start the transaction.
5432 TestCompletionCallback callback
;
5433 int rv
= trans
->Start(
5434 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5435 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5437 rv
= callback
.WaitForResult();
5440 // Request the pushed path. At this point, we've received the push, but the
5441 // headers are not yet complete.
5442 scoped_ptr
<HttpNetworkTransaction
> trans2(
5443 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5445 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5446 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5448 base::RunLoop().RunUntilIdle();
5450 // Read the server push body.
5451 std::string result2
;
5452 ReadResult(trans2
.get(), &data
, &result2
);
5453 // Read the response body.
5455 ReadResult(trans
, &data
, &result
);
5456 EXPECT_EQ("hello!", result
);
5458 // Verify that we haven't received any push data.
5459 EXPECT_EQ("", result2
);
5461 // Verify the SYN_REPLY.
5462 // Copy the response info, because trans goes away.
5463 HttpResponseInfo response
= *trans
->GetResponseInfo();
5464 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5466 VerifyStreamsClosed(helper
);
5468 // Verify the SYN_REPLY.
5469 EXPECT_TRUE(response
.headers
.get() != NULL
);
5470 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5472 // Read the final EOF (which will close the session).
5475 // Verify that we consumed all test data.
5476 EXPECT_TRUE(data
.at_read_eof());
5477 EXPECT_TRUE(data
.at_write_eof());
5480 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5481 scoped_ptr
<SpdyFrame
> req(
5482 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5483 scoped_ptr
<SpdyFrame
> rst(
5484 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5485 MockWrite writes
[] = {
5486 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5489 scoped_ptr
<SpdyFrame
> stream1_reply(
5490 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5492 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5493 (*late_headers
)["hello"] = "bye";
5494 scoped_ptr
<SpdyFrame
> stream1_headers(
5495 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5502 scoped_ptr
<SpdyFrame
> stream1_body(
5503 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5504 MockRead reads
[] = {
5505 CreateMockRead(*stream1_reply
),
5506 CreateMockRead(*stream1_headers
),
5507 CreateMockRead(*stream1_body
),
5508 MockRead(ASYNC
, 0, 0) // EOF
5511 DelayedSocketData
data(1, reads
, arraysize(reads
),
5512 writes
, arraysize(writes
));
5513 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5514 BoundNetLog(), GetParam(), NULL
);
5515 helper
.RunToCompletion(&data
);
5516 TransactionHelperResult out
= helper
.output();
5517 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5520 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5521 scoped_ptr
<SpdyFrame
> req(
5522 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5523 scoped_ptr
<SpdyFrame
> rst(
5524 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5525 MockWrite writes
[] = {
5526 CreateMockWrite(*req
),
5527 CreateMockWrite(*rst
),
5530 scoped_ptr
<SpdyFrame
> stream1_reply(
5531 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5533 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5534 (*late_headers
)["hello"] = "bye";
5535 scoped_ptr
<SpdyFrame
> stream1_headers(
5536 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5543 scoped_ptr
<SpdyFrame
> stream1_body(
5544 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5545 scoped_ptr
<SpdyFrame
> stream1_body2(
5546 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5547 MockRead reads
[] = {
5548 CreateMockRead(*stream1_reply
),
5549 CreateMockRead(*stream1_body
),
5550 CreateMockRead(*stream1_headers
),
5551 CreateMockRead(*stream1_body2
),
5552 MockRead(ASYNC
, 0, 0) // EOF
5555 DelayedSocketData
data(1, reads
, arraysize(reads
),
5556 writes
, arraysize(writes
));
5557 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5558 BoundNetLog(), GetParam(), NULL
);
5559 helper
.RunToCompletion(&data
);
5560 TransactionHelperResult out
= helper
.output();
5561 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5564 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5565 // In this test we want to verify that we can't accidentally push content
5566 // which can't be pushed by this content server.
5567 // This test assumes that:
5568 // - if we're requesting http://www.foo.com/barbaz
5569 // - the browser has made a connection to "www.foo.com".
5571 // A list of the URL to fetch, followed by the URL being pushed.
5572 static const char* const kTestCases
[] = {
5573 "http://www.google.com/foo.html",
5574 "http://www.google.com:81/foo.js", // Bad port
5576 "http://www.google.com/foo.html",
5577 "https://www.google.com/foo.js", // Bad protocol
5579 "http://www.google.com/foo.html",
5580 "ftp://www.google.com/foo.js", // Invalid Protocol
5582 "http://www.google.com/foo.html",
5583 "http://blat.www.google.com/foo.js", // Cross subdomain
5585 "http://www.google.com/foo.html",
5586 "http://www.foo.com/foo.js", // Cross domain
5589 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5590 const char* url_to_fetch
= kTestCases
[index
];
5591 const char* url_to_push
= kTestCases
[index
+ 1];
5593 scoped_ptr
<SpdyFrame
> stream1_syn(
5594 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5595 scoped_ptr
<SpdyFrame
> stream1_body(
5596 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5597 scoped_ptr
<SpdyFrame
> push_rst(
5598 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5599 MockWrite writes
[] = {
5600 CreateMockWrite(*stream1_syn
, 1),
5601 CreateMockWrite(*push_rst
, 4),
5604 scoped_ptr
<SpdyFrame
>
5605 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5606 scoped_ptr
<SpdyFrame
>
5607 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5612 const char kPushedData
[] = "pushed";
5613 scoped_ptr
<SpdyFrame
> stream2_body(
5614 spdy_util_
.ConstructSpdyBodyFrame(
5615 2, kPushedData
, strlen(kPushedData
), true));
5616 scoped_ptr
<SpdyFrame
> rst(
5617 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5619 MockRead reads
[] = {
5620 CreateMockRead(*stream1_reply
, 2),
5621 CreateMockRead(*stream2_syn
, 3),
5622 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5623 CreateMockRead(*stream2_body
, 6),
5624 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5627 HttpResponseInfo response
;
5628 OrderedSocketData
data(reads
, arraysize(reads
),
5629 writes
, arraysize(writes
));
5631 HttpRequestInfo request
;
5632 request
.method
= "GET";
5633 request
.url
= GURL(url_to_fetch
);
5634 request
.load_flags
= 0;
5636 // Enable cross-origin push. Since we are not using a proxy, this should
5637 // not actually enable cross-origin SPDY push.
5638 scoped_ptr
<SpdySessionDependencies
> session_deps(
5639 CreateSpdySessionDependencies(GetParam()));
5640 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5641 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5642 BoundNetLog(), GetParam(),
5643 session_deps
.release());
5644 helper
.RunPreTestSetup();
5645 helper
.AddData(&data
);
5647 HttpNetworkTransaction
* trans
= helper
.trans();
5649 // Start the transaction with basic parameters.
5650 TestCompletionCallback callback
;
5652 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5653 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5654 rv
= callback
.WaitForResult();
5656 // Read the response body.
5658 ReadResult(trans
, &data
, &result
);
5660 // Verify that we consumed all test data.
5661 EXPECT_TRUE(data
.at_read_eof());
5662 EXPECT_TRUE(data
.at_write_eof());
5664 // Verify the SYN_REPLY.
5665 // Copy the response info, because trans goes away.
5666 response
= *trans
->GetResponseInfo();
5668 VerifyStreamsClosed(helper
);
5670 // Verify the SYN_REPLY.
5671 EXPECT_TRUE(response
.headers
.get() != NULL
);
5672 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5676 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5677 // Construct the request.
5678 scoped_ptr
<SpdyFrame
> req(
5679 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5680 scoped_ptr
<SpdyFrame
> req2(
5681 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5682 MockWrite writes
[] = {
5683 CreateMockWrite(*req
, 1),
5684 CreateMockWrite(*req2
, 3),
5687 scoped_ptr
<SpdyFrame
> refused(
5688 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5689 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5690 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5691 MockRead reads
[] = {
5692 CreateMockRead(*refused
, 2),
5693 CreateMockRead(*resp
, 4),
5694 CreateMockRead(*body
, 5),
5695 MockRead(ASYNC
, 0, 6) // EOF
5698 OrderedSocketData
data(reads
, arraysize(reads
),
5699 writes
, arraysize(writes
));
5700 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5701 BoundNetLog(), GetParam(), NULL
);
5703 helper
.RunPreTestSetup();
5704 helper
.AddData(&data
);
5706 HttpNetworkTransaction
* trans
= helper
.trans();
5708 // Start the transaction with basic parameters.
5709 TestCompletionCallback callback
;
5710 int rv
= trans
->Start(
5711 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5713 rv
= callback
.WaitForResult();
5716 // Verify that we consumed all test data.
5717 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5718 << data
.read_count()
5720 << data
.read_index();
5721 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5722 << data
.write_count()
5724 << data
.write_index();
5726 // Verify the SYN_REPLY.
5727 HttpResponseInfo response
= *trans
->GetResponseInfo();
5728 EXPECT_TRUE(response
.headers
.get() != NULL
);
5729 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5732 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5733 // This first request will start to establish the SpdySession.
5734 // Then we will start the second (MEDIUM priority) and then third
5735 // (HIGHEST priority) request in such a way that the third will actually
5736 // start before the second, causing the second to be numbered differently
5737 // than the order they were created.
5738 scoped_ptr
<SpdyFrame
> req1(
5739 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5740 scoped_ptr
<SpdyFrame
> req2(
5741 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5742 scoped_ptr
<SpdyFrame
> req3(
5743 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5744 MockWrite writes
[] = {
5745 CreateMockWrite(*req1
, 0),
5746 CreateMockWrite(*req2
, 3),
5747 CreateMockWrite(*req3
, 4),
5750 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5751 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5752 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5753 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5754 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5755 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5756 MockRead reads
[] = {
5757 CreateMockRead(*resp1
, 1),
5758 CreateMockRead(*body1
, 2),
5759 CreateMockRead(*resp2
, 5),
5760 CreateMockRead(*body2
, 6),
5761 CreateMockRead(*resp3
, 7),
5762 CreateMockRead(*body3
, 8),
5763 MockRead(ASYNC
, 0, 9) // EOF
5766 DeterministicSocketData
data(reads
, arraysize(reads
),
5767 writes
, arraysize(writes
));
5768 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5769 BoundNetLog(), GetParam(), NULL
);
5770 helper
.SetDeterministic();
5771 helper
.RunPreTestSetup();
5772 helper
.AddDeterministicData(&data
);
5774 // Start the first transaction to set up the SpdySession
5775 HttpNetworkTransaction
* trans
= helper
.trans();
5776 TestCompletionCallback callback
;
5777 HttpRequestInfo info1
= CreateGetRequest();
5778 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
5779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5781 // Run the message loop, but do not allow the write to complete.
5782 // This leaves the SpdySession with a write pending, which prevents
5783 // SpdySession from attempting subsequent writes until this write completes.
5784 base::RunLoop().RunUntilIdle();
5786 // Now, start both new transactions
5787 HttpRequestInfo info2
= CreateGetRequest();
5788 TestCompletionCallback callback2
;
5789 scoped_ptr
<HttpNetworkTransaction
> trans2(
5790 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
5791 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
5792 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5793 base::RunLoop().RunUntilIdle();
5795 HttpRequestInfo info3
= CreateGetRequest();
5796 TestCompletionCallback callback3
;
5797 scoped_ptr
<HttpNetworkTransaction
> trans3(
5798 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
5799 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
5800 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5801 base::RunLoop().RunUntilIdle();
5803 // We now have two SYN_STREAM frames queued up which will be
5804 // dequeued only once the first write completes, which we
5805 // now allow to happen.
5807 EXPECT_EQ(OK
, callback
.WaitForResult());
5809 // And now we can allow everything else to run to completion.
5812 EXPECT_EQ(OK
, callback2
.WaitForResult());
5813 EXPECT_EQ(OK
, callback3
.WaitForResult());
5815 helper
.VerifyDataConsumed();
5818 // The tests below are only for SPDY/3 and above.
5820 // Test that sent data frames and received WINDOW_UPDATE frames change
5821 // the send_window_size_ correctly.
5823 // WINDOW_UPDATE is different than most other frames in that it can arrive
5824 // while the client is still sending the request body. In order to enforce
5825 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5826 // socket data provider, so that initial read that is done as soon as the
5827 // stream is created, succeeds and schedules another read. This way reads
5828 // and writes are interleaved; after doing a full frame write, SpdyStream
5829 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5830 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5831 // since request has not been completely written, therefore we feed
5832 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5833 // write, leading to a complete write of request body; after that we send
5834 // a reply with a body, to cause a graceful shutdown.
5836 // TODO(agayev): develop a socket data provider where both, reads and
5837 // writes are ordered so that writing tests like these are easy and rewrite
5838 // all these tests using it. Right now we are working around the
5839 // limitations as described above and it's not deterministic, tests may
5840 // fail under specific circumstances.
5841 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
5842 if (GetParam().protocol
< kProtoSPDY3
)
5845 static int kFrameCount
= 2;
5846 scoped_ptr
<std::string
> content(
5847 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
5848 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
5849 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
5850 scoped_ptr
<SpdyFrame
> body(
5851 spdy_util_
.ConstructSpdyBodyFrame(
5852 1, content
->c_str(), content
->size(), false));
5853 scoped_ptr
<SpdyFrame
> body_end(
5854 spdy_util_
.ConstructSpdyBodyFrame(
5855 1, content
->c_str(), content
->size(), true));
5857 MockWrite writes
[] = {
5858 CreateMockWrite(*req
, 0),
5859 CreateMockWrite(*body
, 1),
5860 CreateMockWrite(*body_end
, 2),
5863 static const int32 kDeltaWindowSize
= 0xff;
5864 static const int kDeltaCount
= 4;
5865 scoped_ptr
<SpdyFrame
> window_update(
5866 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
5867 scoped_ptr
<SpdyFrame
> window_update_dummy(
5868 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
5869 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
5870 MockRead reads
[] = {
5871 CreateMockRead(*window_update_dummy
, 3),
5872 CreateMockRead(*window_update_dummy
, 4),
5873 CreateMockRead(*window_update_dummy
, 5),
5874 CreateMockRead(*window_update
, 6), // Four updates, therefore window
5875 CreateMockRead(*window_update
, 7), // size should increase by
5876 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
5877 CreateMockRead(*window_update
, 9),
5878 CreateMockRead(*resp
, 10),
5879 CreateMockRead(*body_end
, 11),
5880 MockRead(ASYNC
, 0, 0, 12) // EOF
5883 DeterministicSocketData
data(reads
, arraysize(reads
),
5884 writes
, arraysize(writes
));
5886 ScopedVector
<UploadElementReader
> element_readers
;
5887 for (int i
= 0; i
< kFrameCount
; ++i
) {
5888 element_readers
.push_back(
5889 new UploadBytesElementReader(content
->c_str(), content
->size()));
5891 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5893 // Setup the request
5894 HttpRequestInfo request
;
5895 request
.method
= "POST";
5896 request
.url
= GURL(kDefaultURL
);
5897 request
.upload_data_stream
= &upload_data_stream
;
5899 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5900 BoundNetLog(), GetParam(), NULL
);
5901 helper
.SetDeterministic();
5902 helper
.AddDeterministicData(&data
);
5903 helper
.RunPreTestSetup();
5905 HttpNetworkTransaction
* trans
= helper
.trans();
5907 TestCompletionCallback callback
;
5908 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5914 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5915 ASSERT_TRUE(stream
!= NULL
);
5916 ASSERT_TRUE(stream
->stream() != NULL
);
5917 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
) +
5918 kDeltaWindowSize
* kDeltaCount
-
5919 kMaxSpdyFrameChunkSize
* kFrameCount
,
5920 stream
->stream()->send_window_size());
5924 rv
= callback
.WaitForResult();
5927 helper
.VerifyDataConsumed();
5930 // Test that received data frames and sent WINDOW_UPDATE frames change
5931 // the recv_window_size_ correctly.
5932 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
5933 if (GetParam().protocol
< kProtoSPDY3
)
5936 // Amount of body required to trigger a sent window update.
5937 const size_t kTargetSize
= kSpdyStreamInitialWindowSize
/ 2 + 1;
5939 scoped_ptr
<SpdyFrame
> req(
5940 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5941 scoped_ptr
<SpdyFrame
> session_window_update(
5942 spdy_util_
.ConstructSpdyWindowUpdate(0, kTargetSize
));
5943 scoped_ptr
<SpdyFrame
> window_update(
5944 spdy_util_
.ConstructSpdyWindowUpdate(1, kTargetSize
));
5946 std::vector
<MockWrite
> writes
;
5947 writes
.push_back(CreateMockWrite(*req
));
5948 if (GetParam().protocol
>= kProtoSPDY31
)
5949 writes
.push_back(CreateMockWrite(*session_window_update
));
5950 writes
.push_back(CreateMockWrite(*window_update
));
5952 std::vector
<MockRead
> reads
;
5953 scoped_ptr
<SpdyFrame
> resp(
5954 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5955 reads
.push_back(CreateMockRead(*resp
));
5957 ScopedVector
<SpdyFrame
> body_frames
;
5958 const std::string
body_data(4096, 'x');
5959 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
5960 size_t frame_size
= std::min(remaining
, body_data
.size());
5961 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
5962 1, body_data
.data(), frame_size
, false));
5963 reads
.push_back(CreateMockRead(*body_frames
.back()));
5964 remaining
-= frame_size
;
5966 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
5968 DelayedSocketData
data(1, vector_as_array(&reads
), reads
.size(),
5969 vector_as_array(&writes
), writes
.size());
5971 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5972 BoundNetLog(), GetParam(), NULL
);
5973 helper
.AddData(&data
);
5974 helper
.RunPreTestSetup();
5975 HttpNetworkTransaction
* trans
= helper
.trans();
5977 TestCompletionCallback callback
;
5978 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5980 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5981 rv
= callback
.WaitForResult();
5984 SpdyHttpStream
* stream
=
5985 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5986 ASSERT_TRUE(stream
!= NULL
);
5987 ASSERT_TRUE(stream
->stream() != NULL
);
5989 // All data has been read, but not consumed. The window reflects this.
5990 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
- kTargetSize
),
5991 stream
->stream()->recv_window_size());
5993 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5994 ASSERT_TRUE(response
!= NULL
);
5995 ASSERT_TRUE(response
->headers
.get() != NULL
);
5996 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5997 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5999 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6000 // size increased to default.
6001 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kTargetSize
));
6002 EXPECT_EQ(static_cast<int>(kTargetSize
),
6003 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
6004 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
),
6005 stream
->stream()->recv_window_size());
6006 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6008 // Allow scheduled WINDOW_UPDATE frames to write.
6009 base::RunLoop().RunUntilIdle();
6010 helper
.VerifyDataConsumed();
6013 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6014 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6015 if (GetParam().protocol
< kProtoSPDY3
)
6018 // Number of full frames we hope to write (but will not, used to
6019 // set content-length header correctly)
6020 static int kFrameCount
= 3;
6022 scoped_ptr
<std::string
> content(
6023 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6024 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6025 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6026 scoped_ptr
<SpdyFrame
> body(
6027 spdy_util_
.ConstructSpdyBodyFrame(
6028 1, content
->c_str(), content
->size(), false));
6029 scoped_ptr
<SpdyFrame
> rst(
6030 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6032 // We're not going to write a data frame with FIN, we'll receive a bad
6033 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6034 MockWrite writes
[] = {
6035 CreateMockWrite(*req
, 0),
6036 CreateMockWrite(*body
, 2),
6037 CreateMockWrite(*rst
, 3),
6040 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6041 scoped_ptr
<SpdyFrame
> window_update(
6042 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6043 MockRead reads
[] = {
6044 CreateMockRead(*window_update
, 1),
6045 MockRead(ASYNC
, 0, 4) // EOF
6048 DeterministicSocketData
data(reads
, arraysize(reads
),
6049 writes
, arraysize(writes
));
6051 ScopedVector
<UploadElementReader
> element_readers
;
6052 for (int i
= 0; i
< kFrameCount
; ++i
) {
6053 element_readers
.push_back(
6054 new UploadBytesElementReader(content
->c_str(), content
->size()));
6056 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6058 // Setup the request
6059 HttpRequestInfo request
;
6060 request
.method
= "POST";
6061 request
.url
= GURL("http://www.google.com/");
6062 request
.upload_data_stream
= &upload_data_stream
;
6064 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6065 BoundNetLog(), GetParam(), NULL
);
6066 helper
.SetDeterministic();
6067 helper
.RunPreTestSetup();
6068 helper
.AddDeterministicData(&data
);
6069 HttpNetworkTransaction
* trans
= helper
.trans();
6071 TestCompletionCallback callback
;
6072 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6073 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6076 ASSERT_TRUE(callback
.have_result());
6077 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6078 helper
.VerifyDataConsumed();
6081 // Test that after hitting a send window size of 0, the write process
6082 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6084 // This test constructs a POST request followed by enough data frames
6085 // containing 'a' that would make the window size 0, followed by another
6086 // data frame containing default content (which is "hello!") and this frame
6087 // also contains a FIN flag. DelayedSocketData is used to enforce all
6088 // writes go through before a read could happen. However, the last frame
6089 // ("hello!") is not supposed to go through since by the time its turn
6090 // arrives, window size is 0. At this point MessageLoop::Run() called via
6091 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6092 // which returns after performing all possible writes. We use DCHECKS to
6093 // ensure that last data frame is still there and stream has stalled.
6094 // After that, next read is artifically enforced, which causes a
6095 // WINDOW_UPDATE to be read and I/O process resumes.
6096 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6097 if (GetParam().protocol
< kProtoSPDY3
)
6100 // Number of frames we need to send to zero out the window size: data
6101 // frames plus SYN_STREAM plus the last data frame; also we need another
6102 // data frame that we will send once the WINDOW_UPDATE is received,
6104 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6106 // Calculate last frame's size; 0 size data frame is legal.
6107 size_t last_frame_size
=
6108 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6110 // Construct content for a data frame of maximum size.
6111 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6113 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6114 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6118 scoped_ptr
<SpdyFrame
> body1(
6119 spdy_util_
.ConstructSpdyBodyFrame(
6120 1, content
.c_str(), content
.size(), false));
6122 // Last frame to zero out the window size.
6123 scoped_ptr
<SpdyFrame
> body2(
6124 spdy_util_
.ConstructSpdyBodyFrame(
6125 1, content
.c_str(), last_frame_size
, false));
6127 // Data frame to be sent once WINDOW_UPDATE frame is received.
6128 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6130 // Fill in mock writes.
6131 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6133 writes
[i
] = CreateMockWrite(*req
);
6134 for (i
= 1; i
< num_writes
- 2; i
++)
6135 writes
[i
] = CreateMockWrite(*body1
);
6136 writes
[i
++] = CreateMockWrite(*body2
);
6137 writes
[i
] = CreateMockWrite(*body3
);
6139 // Construct read frame, give enough space to upload the rest of the
6141 scoped_ptr
<SpdyFrame
> session_window_update(
6142 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6143 scoped_ptr
<SpdyFrame
> window_update(
6144 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6145 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6146 MockRead reads
[] = {
6147 CreateMockRead(*session_window_update
),
6148 CreateMockRead(*session_window_update
),
6149 CreateMockRead(*window_update
),
6150 CreateMockRead(*window_update
),
6151 CreateMockRead(*reply
),
6152 CreateMockRead(*body2
),
6153 CreateMockRead(*body3
),
6154 MockRead(ASYNC
, 0, 0) // EOF
6157 // Skip the session window updates unless we're using SPDY/3.1 and
6159 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6160 size_t num_reads
= arraysize(reads
) - read_offset
;
6162 // Force all writes to happen before any read, last write will not
6163 // actually queue a frame, due to window size being 0.
6164 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6165 writes
.get(), num_writes
);
6167 ScopedVector
<UploadElementReader
> element_readers
;
6168 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6169 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6170 element_readers
.push_back(new UploadBytesElementReader(
6171 upload_data_string
.c_str(), upload_data_string
.size()));
6172 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6174 HttpRequestInfo request
;
6175 request
.method
= "POST";
6176 request
.url
= GURL("http://www.google.com/");
6177 request
.upload_data_stream
= &upload_data_stream
;
6178 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6179 BoundNetLog(), GetParam(), NULL
);
6180 helper
.AddData(&data
);
6181 helper
.RunPreTestSetup();
6183 HttpNetworkTransaction
* trans
= helper
.trans();
6185 TestCompletionCallback callback
;
6186 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6187 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6189 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6191 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6192 ASSERT_TRUE(stream
!= NULL
);
6193 ASSERT_TRUE(stream
->stream() != NULL
);
6194 EXPECT_EQ(0, stream
->stream()->send_window_size());
6195 // All the body data should have been read.
6196 // TODO(satorux): This is because of the weirdness in reading the request
6197 // body in OnSendBodyComplete(). See crbug.com/113107.
6198 EXPECT_TRUE(upload_data_stream
.IsEOF());
6199 // But the body is not yet fully sent (kUploadData is not yet sent)
6200 // since we're send-stalled.
6201 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6203 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6204 rv
= callback
.WaitForResult();
6205 helper
.VerifyDataConsumed();
6208 // Test we correctly handle the case where the SETTINGS frame results in
6209 // unstalling the send window.
6210 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6211 if (GetParam().protocol
< kProtoSPDY3
)
6214 // Number of frames we need to send to zero out the window size: data
6215 // frames plus SYN_STREAM plus the last data frame; also we need another
6216 // data frame that we will send once the SETTING is received, therefore +3.
6217 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6219 // Calculate last frame's size; 0 size data frame is legal.
6220 size_t last_frame_size
=
6221 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6223 // Construct content for a data frame of maximum size.
6224 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6226 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6227 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6231 scoped_ptr
<SpdyFrame
> body1(
6232 spdy_util_
.ConstructSpdyBodyFrame(
6233 1, content
.c_str(), content
.size(), false));
6235 // Last frame to zero out the window size.
6236 scoped_ptr
<SpdyFrame
> body2(
6237 spdy_util_
.ConstructSpdyBodyFrame(
6238 1, content
.c_str(), last_frame_size
, false));
6240 // Data frame to be sent once SETTINGS frame is received.
6241 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6243 // Fill in mock reads/writes.
6244 std::vector
<MockRead
> reads
;
6245 std::vector
<MockWrite
> writes
;
6247 writes
.push_back(CreateMockWrite(*req
, i
++));
6248 while (i
< num_writes
- 2)
6249 writes
.push_back(CreateMockWrite(*body1
, i
++));
6250 writes
.push_back(CreateMockWrite(*body2
, i
++));
6252 // Construct read frame for SETTINGS that gives enough space to upload the
6253 // rest of the data.
6254 SettingsMap settings
;
6255 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6256 SettingsFlagsAndValue(
6257 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
* 2);
6258 scoped_ptr
<SpdyFrame
> settings_frame_large(
6259 spdy_util_
.ConstructSpdySettings(settings
));
6261 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6263 scoped_ptr
<SpdyFrame
> session_window_update(
6264 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6265 if (GetParam().protocol
>= kProtoSPDY31
)
6266 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6268 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6269 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6271 writes
.push_back(CreateMockWrite(*body3
, i
++));
6273 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6274 reads
.push_back(CreateMockRead(*reply
, i
++));
6275 reads
.push_back(CreateMockRead(*body2
, i
++));
6276 reads
.push_back(CreateMockRead(*body3
, i
++));
6277 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6279 // Force all writes to happen before any read, last write will not
6280 // actually queue a frame, due to window size being 0.
6281 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6282 vector_as_array(&writes
), writes
.size());
6284 ScopedVector
<UploadElementReader
> element_readers
;
6285 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6286 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6287 element_readers
.push_back(new UploadBytesElementReader(
6288 upload_data_string
.c_str(), upload_data_string
.size()));
6289 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6291 HttpRequestInfo request
;
6292 request
.method
= "POST";
6293 request
.url
= GURL("http://www.google.com/");
6294 request
.upload_data_stream
= &upload_data_stream
;
6295 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6296 BoundNetLog(), GetParam(), NULL
);
6297 helper
.SetDeterministic();
6298 helper
.RunPreTestSetup();
6299 helper
.AddDeterministicData(&data
);
6301 HttpNetworkTransaction
* trans
= helper
.trans();
6303 TestCompletionCallback callback
;
6304 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6307 data
.RunFor(num_writes
- 1); // Write as much as we can.
6309 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6310 ASSERT_TRUE(stream
!= NULL
);
6311 ASSERT_TRUE(stream
->stream() != NULL
);
6312 EXPECT_EQ(0, stream
->stream()->send_window_size());
6314 // All the body data should have been read.
6315 // TODO(satorux): This is because of the weirdness in reading the request
6316 // body in OnSendBodyComplete(). See crbug.com/113107.
6317 EXPECT_TRUE(upload_data_stream
.IsEOF());
6318 // But the body is not yet fully sent (kUploadData is not yet sent)
6319 // since we're send-stalled.
6320 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6322 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6323 rv
= callback
.WaitForResult();
6324 helper
.VerifyDataConsumed();
6325 // If stream is NULL, that means it was unstalled and closed.
6326 EXPECT_TRUE(stream
->stream() == NULL
);
6329 // Test we correctly handle the case where the SETTINGS frame results in a
6330 // negative send window size.
6331 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6332 if (GetParam().protocol
< kProtoSPDY3
)
6335 // Number of frames we need to send to zero out the window size: data
6336 // frames plus SYN_STREAM plus the last data frame; also we need another
6337 // data frame that we will send once the SETTING is received, therefore +3.
6338 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6340 // Calculate last frame's size; 0 size data frame is legal.
6341 size_t last_frame_size
=
6342 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6344 // Construct content for a data frame of maximum size.
6345 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6347 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6348 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6352 scoped_ptr
<SpdyFrame
> body1(
6353 spdy_util_
.ConstructSpdyBodyFrame(
6354 1, content
.c_str(), content
.size(), false));
6356 // Last frame to zero out the window size.
6357 scoped_ptr
<SpdyFrame
> body2(
6358 spdy_util_
.ConstructSpdyBodyFrame(
6359 1, content
.c_str(), last_frame_size
, false));
6361 // Data frame to be sent once SETTINGS frame is received.
6362 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6364 // Fill in mock reads/writes.
6365 std::vector
<MockRead
> reads
;
6366 std::vector
<MockWrite
> writes
;
6368 writes
.push_back(CreateMockWrite(*req
, i
++));
6369 while (i
< num_writes
- 2)
6370 writes
.push_back(CreateMockWrite(*body1
, i
++));
6371 writes
.push_back(CreateMockWrite(*body2
, i
++));
6373 // Construct read frame for SETTINGS that makes the send_window_size
6375 SettingsMap new_settings
;
6376 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6377 SettingsFlagsAndValue(
6378 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
/ 2);
6379 scoped_ptr
<SpdyFrame
> settings_frame_small(
6380 spdy_util_
.ConstructSpdySettings(new_settings
));
6381 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6383 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6384 spdy_util_
.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize
));
6385 scoped_ptr
<SpdyFrame
> window_update_init_size(
6386 spdy_util_
.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize
));
6388 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6390 if (GetParam().protocol
>= kProtoSPDY3
)
6391 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6393 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6395 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6396 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6398 writes
.push_back(CreateMockWrite(*body3
, i
++));
6400 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6401 reads
.push_back(CreateMockRead(*reply
, i
++));
6402 reads
.push_back(CreateMockRead(*body2
, i
++));
6403 reads
.push_back(CreateMockRead(*body3
, i
++));
6404 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6406 // Force all writes to happen before any read, last write will not
6407 // actually queue a frame, due to window size being 0.
6408 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6409 vector_as_array(&writes
), writes
.size());
6411 ScopedVector
<UploadElementReader
> element_readers
;
6412 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6413 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6414 element_readers
.push_back(new UploadBytesElementReader(
6415 upload_data_string
.c_str(), upload_data_string
.size()));
6416 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6418 HttpRequestInfo request
;
6419 request
.method
= "POST";
6420 request
.url
= GURL("http://www.google.com/");
6421 request
.upload_data_stream
= &upload_data_stream
;
6422 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6423 BoundNetLog(), GetParam(), NULL
);
6424 helper
.SetDeterministic();
6425 helper
.RunPreTestSetup();
6426 helper
.AddDeterministicData(&data
);
6428 HttpNetworkTransaction
* trans
= helper
.trans();
6430 TestCompletionCallback callback
;
6431 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6432 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6434 data
.RunFor(num_writes
- 1); // Write as much as we can.
6436 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6437 ASSERT_TRUE(stream
!= NULL
);
6438 ASSERT_TRUE(stream
->stream() != NULL
);
6439 EXPECT_EQ(0, stream
->stream()->send_window_size());
6441 // All the body data should have been read.
6442 // TODO(satorux): This is because of the weirdness in reading the request
6443 // body in OnSendBodyComplete(). See crbug.com/113107.
6444 EXPECT_TRUE(upload_data_stream
.IsEOF());
6445 // But the body is not yet fully sent (kUploadData is not yet sent)
6446 // since we're send-stalled.
6447 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6449 // Read in WINDOW_UPDATE or SETTINGS frame.
6450 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6451 rv
= callback
.WaitForResult();
6452 helper
.VerifyDataConsumed();
6455 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnOddPushStreamId
) {
6456 if (spdy_util_
.spdy_version() < SPDY3
)
6459 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
6460 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6461 push_headers
.get());
6462 scoped_ptr
<SpdyFrame
> push(
6463 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 3, 1));
6464 MockRead reads
[] = {CreateMockRead(*push
, 1)};
6466 scoped_ptr
<SpdyFrame
> req(
6467 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6468 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6469 0, GOAWAY_PROTOCOL_ERROR
, "Odd push stream id."));
6470 MockWrite writes
[] = {
6471 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 2),
6474 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6475 NormalSpdyTransactionHelper
helper(
6476 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6477 helper
.RunToCompletion(&data
);
6478 TransactionHelperResult out
= helper
.output();
6479 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6482 TEST_P(SpdyNetworkTransactionTest
,
6483 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted
) {
6484 if (spdy_util_
.spdy_version() < SPDY3
)
6487 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
6488 NULL
, 0, 4, 1, "http://www.google.com/a.dat"));
6489 scoped_ptr
<SpdyHeaderBlock
> push_b_headers(new SpdyHeaderBlock
);
6490 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6491 push_b_headers
.get());
6492 scoped_ptr
<SpdyFrame
> push_b(
6493 spdy_util_
.ConstructInitialSpdyPushFrame(push_b_headers
.Pass(), 2, 1));
6494 MockRead reads
[] = {
6495 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
6498 scoped_ptr
<SpdyFrame
> req(
6499 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6500 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6502 GOAWAY_PROTOCOL_ERROR
,
6503 "New push stream id must be greater than the last accepted."));
6504 MockWrite writes
[] = {
6505 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
6508 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6509 NormalSpdyTransactionHelper
helper(
6510 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6511 helper
.RunToCompletion(&data
);
6512 TransactionHelperResult out
= helper
.output();
6513 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6516 class SpdyNetworkTransactionNoTLSUsageCheckTest
6517 : public SpdyNetworkTransactionTest
{
6519 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6520 // Construct the request.
6521 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyGet(
6522 "https://www.google.com/", false, 1, LOWEST
));
6523 MockWrite writes
[] = {CreateMockWrite(*req
)};
6525 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6526 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6527 MockRead reads
[] = {
6528 CreateMockRead(*resp
), CreateMockRead(*body
),
6529 MockRead(ASYNC
, 0, 0) // EOF
6532 DelayedSocketData
data(
6533 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6534 HttpRequestInfo request
;
6535 request
.method
= "GET";
6536 request
.url
= GURL("https://www.google.com/");
6537 NormalSpdyTransactionHelper
helper(
6538 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6539 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6540 TransactionHelperResult out
= helper
.output();
6541 EXPECT_EQ(OK
, out
.rv
);
6542 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6543 EXPECT_EQ("hello!", out
.response_data
);
6547 //-----------------------------------------------------------------------------
6548 // All tests are run with three different connection types: SPDY after NPN
6549 // negotiation, SPDY without SSL, and SPDY with SSL.
6551 // TODO(akalin): Use ::testing::Combine() when we are able to use
6553 INSTANTIATE_TEST_CASE_P(
6555 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6556 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
,
6558 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNPN
),
6559 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
)));
6561 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6562 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6563 new SSLSocketDataProvider(ASYNC
, OK
));
6564 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6565 &ssl_provider
->connection_status
);
6567 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6570 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6571 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6572 new SSLSocketDataProvider(ASYNC
, OK
));
6573 // Set to TLS_RSA_WITH_NULL_MD5
6574 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6576 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6579 class SpdyNetworkTransactionTLSUsageCheckTest
6580 : public SpdyNetworkTransactionTest
{
6582 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6583 scoped_ptr
<SpdyFrame
> goaway(
6584 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6585 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6587 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6588 HttpRequestInfo request
;
6589 request
.method
= "GET";
6590 request
.url
= GURL("https://www.google.com/");
6591 NormalSpdyTransactionHelper
helper(
6592 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6593 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6594 TransactionHelperResult out
= helper
.output();
6595 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6599 INSTANTIATE_TEST_CASE_P(
6601 SpdyNetworkTransactionTLSUsageCheckTest
,
6602 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNPN
)));
6604 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6605 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6606 new SSLSocketDataProvider(ASYNC
, OK
));
6607 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6608 &ssl_provider
->connection_status
);
6610 RunTLSUsageCheckTest(ssl_provider
.Pass());
6613 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6614 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6615 new SSLSocketDataProvider(ASYNC
, OK
));
6616 // Set to TLS_RSA_WITH_NULL_MD5
6617 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6619 RunTLSUsageCheckTest(ssl_provider
.Pass());