1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/bind_helpers.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_piece.h"
16 #include "base/test/test_file_util.h"
17 #include "net/base/auth.h"
18 #include "net/base/chunked_upload_data_stream.h"
19 #include "net/base/elements_upload_data_stream.h"
20 #include "net/base/net_log_unittest.h"
21 #include "net/base/request_priority.h"
22 #include "net/base/upload_bytes_element_reader.h"
23 #include "net/base/upload_file_element_reader.h"
24 #include "net/http/http_network_session_peer.h"
25 #include "net/http/http_network_transaction.h"
26 #include "net/http/http_server_properties.h"
27 #include "net/http/http_transaction_test_util.h"
28 #include "net/socket/client_socket_pool_base.h"
29 #include "net/socket/next_proto.h"
30 #include "net/spdy/buffered_spdy_framer.h"
31 #include "net/spdy/spdy_http_stream.h"
32 #include "net/spdy/spdy_http_utils.h"
33 #include "net/spdy/spdy_session.h"
34 #include "net/spdy/spdy_session_pool.h"
35 #include "net/spdy/spdy_test_util_common.h"
36 #include "net/spdy/spdy_test_utils.h"
37 #include "net/ssl/ssl_connection_status_flags.h"
38 #include "net/url_request/url_request_test_util.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/platform_test.h"
42 //-----------------------------------------------------------------------------
51 const char kRequestUrl
[] = "http://www.google.com/";
53 enum SpdyNetworkTransactionTestSSLType
{
59 struct SpdyNetworkTransactionTestParams
{
60 SpdyNetworkTransactionTestParams()
61 : protocol(kProtoSPDY31
),
64 SpdyNetworkTransactionTestParams(
66 SpdyNetworkTransactionTestSSLType ssl_type
)
71 SpdyNetworkTransactionTestSSLType ssl_type
;
74 void UpdateSpdySessionDependencies(
75 SpdyNetworkTransactionTestParams test_params
,
76 SpdySessionDependencies
* session_deps
) {
77 switch (test_params
.ssl_type
) {
79 session_deps
->http_server_properties
.SetAlternateProtocol(
80 HostPortPair("www.google.com", 80), 443,
81 AlternateProtocolFromNextProto(test_params
.protocol
), 1);
82 session_deps
->use_alternate_protocols
= true;
83 session_deps
->next_protos
= SpdyNextProtos();
86 session_deps
->force_spdy_over_ssl
= false;
87 session_deps
->force_spdy_always
= true;
90 session_deps
->force_spdy_over_ssl
= true;
91 session_deps
->force_spdy_always
= true;
98 SpdySessionDependencies
* CreateSpdySessionDependencies(
99 SpdyNetworkTransactionTestParams test_params
) {
100 SpdySessionDependencies
* session_deps
=
101 new SpdySessionDependencies(test_params
.protocol
);
102 UpdateSpdySessionDependencies(test_params
, session_deps
);
106 SpdySessionDependencies
* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params
,
108 ProxyService
* proxy_service
) {
109 SpdySessionDependencies
* session_deps
=
110 new SpdySessionDependencies(test_params
.protocol
, proxy_service
);
111 UpdateSpdySessionDependencies(test_params
, session_deps
);
117 class SpdyNetworkTransactionTest
118 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestParams
> {
120 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol
) {
123 virtual ~SpdyNetworkTransactionTest() {
124 // UploadDataStream may post a deletion tasks back to the message loop on
126 upload_data_stream_
.reset();
127 base::RunLoop().RunUntilIdle();
130 void SetUp() override
{
131 google_get_request_initialized_
= false;
132 google_post_request_initialized_
= false;
133 google_chunked_post_request_initialized_
= false;
134 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
137 struct TransactionHelperResult
{
139 std::string status_line
;
140 std::string response_data
;
141 HttpResponseInfo response_info
;
144 // A helper class that handles all the initial npn/ssl setup.
145 class NormalSpdyTransactionHelper
{
147 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
148 RequestPriority priority
,
149 const BoundNetLog
& log
,
150 SpdyNetworkTransactionTestParams test_params
,
151 SpdySessionDependencies
* session_deps
)
154 session_deps_(session_deps
== NULL
?
155 CreateSpdySessionDependencies(test_params
) :
157 session_(SpdySessionDependencies::SpdyCreateSession(
158 session_deps_
.get())),
160 test_params_(test_params
),
161 deterministic_(false),
162 spdy_enabled_(true) {
163 switch (test_params_
.ssl_type
) {
176 ~NormalSpdyTransactionHelper() {
177 // Any test which doesn't close the socket by sending it an EOF will
178 // have a valid session left open, which leaks the entire session pool.
179 // This is just fine - in fact, some of our tests intentionally do this
180 // so that we can check consistency of the SpdySessionPool as the test
181 // finishes. If we had put an EOF on the socket, the SpdySession would
182 // have closed and we wouldn't be able to check the consistency.
184 // Forcefully close existing sessions here.
185 session()->spdy_session_pool()->CloseAllSessions();
188 void SetDeterministic() {
189 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
190 session_deps_
.get());
191 deterministic_
= true;
194 void SetSpdyDisabled() {
195 spdy_enabled_
= false;
199 void RunPreTestSetup() {
200 if (!session_deps_
.get())
201 session_deps_
.reset(CreateSpdySessionDependencies(test_params_
));
202 if (!session_
.get()) {
203 session_
= SpdySessionDependencies::SpdyCreateSession(
204 session_deps_
.get());
207 // We're now ready to use SSL-npn SPDY.
208 trans_
.reset(new HttpNetworkTransaction(priority_
, session_
.get()));
211 // Start the transaction, read some data, finish.
212 void RunDefaultTest() {
213 if (!StartDefaultTest())
218 bool StartDefaultTest() {
219 output_
.rv
= trans_
->Start(&request_
, callback_
.callback(), log_
);
221 // We expect an IO Pending or some sort of error.
222 EXPECT_LT(output_
.rv
, 0);
223 return output_
.rv
== ERR_IO_PENDING
;
226 void FinishDefaultTest() {
227 output_
.rv
= callback_
.WaitForResult();
228 if (output_
.rv
!= OK
) {
229 session_
->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED
);
234 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
235 ASSERT_TRUE(response
!= NULL
);
236 ASSERT_TRUE(response
->headers
.get() != NULL
);
237 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
238 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
239 if (HttpStreamFactory::spdy_enabled()) {
241 HttpResponseInfo::ConnectionInfoFromNextProto(
242 test_params_
.protocol
),
243 response
->connection_info
);
245 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
,
246 response
->connection_info
);
248 if (test_params_
.ssl_type
== SPDYNPN
&& spdy_enabled_
) {
249 EXPECT_TRUE(response
->was_npn_negotiated
);
251 EXPECT_TRUE(!response
->was_npn_negotiated
);
253 // If SPDY is not enabled, a HTTP request should not be diverted
254 // over a SSL session.
255 if (!spdy_enabled_
) {
256 EXPECT_EQ(request_
.url
.SchemeIs("https"),
257 response
->was_npn_negotiated
);
259 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
260 EXPECT_EQ(port_
, response
->socket_address
.port());
261 output_
.status_line
= response
->headers
->GetStatusLine();
262 output_
.response_info
= *response
; // Make a copy so we can verify.
263 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
266 void FinishDefaultTestWithoutVerification() {
267 output_
.rv
= callback_
.WaitForResult();
268 if (output_
.rv
!= OK
)
269 session_
->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED
);
272 // Most tests will want to call this function. In particular, the MockReads
273 // should end with an empty read, and that read needs to be processed to
274 // ensure proper deletion of the spdy_session_pool.
275 void VerifyDataConsumed() {
276 for (DataVector::iterator it
= data_vector_
.begin();
277 it
!= data_vector_
.end(); ++it
) {
278 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
279 << (*it
)->read_count()
281 << (*it
)->read_index();
282 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
283 << (*it
)->write_count()
285 << (*it
)->write_index();
289 // Occasionally a test will expect to error out before certain reads are
290 // processed. In that case we want to explicitly ensure that the reads were
292 void VerifyDataNotConsumed() {
293 for (DataVector::iterator it
= data_vector_
.begin();
294 it
!= data_vector_
.end(); ++it
) {
295 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
296 << (*it
)->read_count()
298 << (*it
)->read_index();
299 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
300 << (*it
)->write_count()
302 << (*it
)->write_index();
306 void RunToCompletion(StaticSocketDataProvider
* data
) {
310 VerifyDataConsumed();
313 void RunToCompletionWithSSLData(
314 StaticSocketDataProvider
* data
,
315 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
317 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
319 VerifyDataConsumed();
322 void AddData(StaticSocketDataProvider
* data
) {
323 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
324 new SSLSocketDataProvider(ASYNC
, OK
));
325 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
328 void AddDataWithSSLSocketDataProvider(
329 StaticSocketDataProvider
* data
,
330 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
331 DCHECK(!deterministic_
);
332 data_vector_
.push_back(data
);
333 if (test_params_
.ssl_type
== SPDYNPN
)
334 ssl_provider
->SetNextProto(test_params_
.protocol
);
336 if (test_params_
.ssl_type
== SPDYNPN
||
337 test_params_
.ssl_type
== SPDYSSL
) {
338 session_deps_
->socket_factory
->AddSSLSocketDataProvider(
341 ssl_vector_
.push_back(ssl_provider
.release());
343 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
344 if (test_params_
.ssl_type
== SPDYNPN
) {
345 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
346 StaticSocketDataProvider
* hanging_non_alternate_protocol_socket
=
347 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
348 hanging_non_alternate_protocol_socket
->set_connect_data(
349 never_finishing_connect
);
350 session_deps_
->socket_factory
->AddSocketDataProvider(
351 hanging_non_alternate_protocol_socket
);
352 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
356 void AddDeterministicData(DeterministicSocketData
* data
) {
357 DCHECK(deterministic_
);
358 data_vector_
.push_back(data
);
359 SSLSocketDataProvider
* ssl_provider
=
360 new SSLSocketDataProvider(ASYNC
, OK
);
361 if (test_params_
.ssl_type
== SPDYNPN
)
362 ssl_provider
->SetNextProto(test_params_
.protocol
);
364 ssl_vector_
.push_back(ssl_provider
);
365 if (test_params_
.ssl_type
== SPDYNPN
||
366 test_params_
.ssl_type
== SPDYSSL
) {
367 session_deps_
->deterministic_socket_factory
->
368 AddSSLSocketDataProvider(ssl_provider
);
370 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
371 if (test_params_
.ssl_type
== SPDYNPN
) {
372 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
373 DeterministicSocketData
* hanging_non_alternate_protocol_socket
=
374 new DeterministicSocketData(NULL
, 0, NULL
, 0);
375 hanging_non_alternate_protocol_socket
->set_connect_data(
376 never_finishing_connect
);
377 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
378 hanging_non_alternate_protocol_socket
);
379 alternate_deterministic_vector_
.push_back(
380 hanging_non_alternate_protocol_socket
);
384 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
387 HttpNetworkTransaction
* trans() { return trans_
.get(); }
388 void ResetTrans() { trans_
.reset(); }
389 TransactionHelperResult
& output() { return output_
; }
390 const HttpRequestInfo
& request() const { return request_
; }
391 const scoped_refptr
<HttpNetworkSession
>& session() const {
394 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
395 return session_deps_
;
397 int port() const { return port_
; }
398 SpdyNetworkTransactionTestParams
test_params() const {
403 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
404 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
405 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
406 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
407 HttpRequestInfo request_
;
408 RequestPriority priority_
;
409 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
410 scoped_refptr
<HttpNetworkSession
> session_
;
411 TransactionHelperResult output_
;
412 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
413 SSLVector ssl_vector_
;
414 TestCompletionCallback callback_
;
415 scoped_ptr
<HttpNetworkTransaction
> trans_
;
416 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
417 DataVector data_vector_
;
418 AlternateVector alternate_vector_
;
419 AlternateDeterministicVector alternate_deterministic_vector_
;
420 const BoundNetLog log_
;
421 SpdyNetworkTransactionTestParams test_params_
;
427 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
428 int expected_status
);
430 void ConnectStatusHelper(const MockRead
& status
);
432 const HttpRequestInfo
& CreateGetPushRequest() {
433 google_get_push_request_
.method
= "GET";
434 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
435 google_get_push_request_
.load_flags
= 0;
436 return google_get_push_request_
;
439 const HttpRequestInfo
& CreateGetRequest() {
440 if (!google_get_request_initialized_
) {
441 google_get_request_
.method
= "GET";
442 google_get_request_
.url
= GURL(kDefaultURL
);
443 google_get_request_
.load_flags
= 0;
444 google_get_request_initialized_
= true;
446 return google_get_request_
;
449 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
450 if (!google_get_request_initialized_
) {
451 google_get_request_
.method
= "GET";
452 google_get_request_
.url
= GURL(kDefaultURL
);
453 google_get_request_
.load_flags
= 0;
454 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
455 google_get_request_initialized_
= true;
457 return google_get_request_
;
460 const HttpRequestInfo
& CreatePostRequest() {
461 if (!google_post_request_initialized_
) {
462 ScopedVector
<UploadElementReader
> element_readers
;
463 element_readers
.push_back(
464 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
465 upload_data_stream_
.reset(
466 new ElementsUploadDataStream(element_readers
.Pass(), 0));
468 google_post_request_
.method
= "POST";
469 google_post_request_
.url
= GURL(kDefaultURL
);
470 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
471 google_post_request_initialized_
= true;
473 return google_post_request_
;
476 const HttpRequestInfo
& CreateFilePostRequest() {
477 if (!google_post_request_initialized_
) {
478 base::FilePath file_path
;
479 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
480 CHECK_EQ(static_cast<int>(kUploadDataSize
),
481 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
483 ScopedVector
<UploadElementReader
> element_readers
;
484 element_readers
.push_back(
485 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
490 upload_data_stream_
.reset(
491 new ElementsUploadDataStream(element_readers
.Pass(), 0));
493 google_post_request_
.method
= "POST";
494 google_post_request_
.url
= GURL(kDefaultURL
);
495 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
496 google_post_request_initialized_
= true;
498 return google_post_request_
;
501 const HttpRequestInfo
& CreateUnreadableFilePostRequest() {
502 if (google_post_request_initialized_
)
503 return google_post_request_
;
505 base::FilePath file_path
;
506 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
507 CHECK_EQ(static_cast<int>(kUploadDataSize
),
508 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
509 CHECK(base::MakeFileUnreadable(file_path
));
511 ScopedVector
<UploadElementReader
> element_readers
;
512 element_readers
.push_back(
513 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
518 upload_data_stream_
.reset(
519 new ElementsUploadDataStream(element_readers
.Pass(), 0));
521 google_post_request_
.method
= "POST";
522 google_post_request_
.url
= GURL(kDefaultURL
);
523 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
524 google_post_request_initialized_
= true;
525 return google_post_request_
;
528 const HttpRequestInfo
& CreateComplexPostRequest() {
529 if (!google_post_request_initialized_
) {
530 const int kFileRangeOffset
= 1;
531 const int kFileRangeLength
= 3;
532 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
534 base::FilePath file_path
;
535 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
536 CHECK_EQ(static_cast<int>(kUploadDataSize
),
537 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
539 ScopedVector
<UploadElementReader
> element_readers
;
540 element_readers
.push_back(
541 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
542 element_readers
.push_back(
543 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
548 element_readers
.push_back(new UploadBytesElementReader(
549 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
550 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
551 upload_data_stream_
.reset(
552 new ElementsUploadDataStream(element_readers
.Pass(), 0));
554 google_post_request_
.method
= "POST";
555 google_post_request_
.url
= GURL(kDefaultURL
);
556 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
557 google_post_request_initialized_
= true;
559 return google_post_request_
;
562 const HttpRequestInfo
& CreateChunkedPostRequest() {
563 if (!google_chunked_post_request_initialized_
) {
564 upload_chunked_data_stream_
.reset(new ChunkedUploadDataStream(0));
565 google_chunked_post_request_
.method
= "POST";
566 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
567 google_chunked_post_request_
.upload_data_stream
=
568 upload_chunked_data_stream_
.get();
569 google_chunked_post_request_initialized_
= true;
571 return google_chunked_post_request_
;
574 // Read the result of a particular transaction, knowing that we've got
575 // multiple transactions in the read pipeline; so as we read, we may have
576 // to skip over data destined for other transactions while we consume
577 // the data for |trans|.
578 int ReadResult(HttpNetworkTransaction
* trans
,
579 StaticSocketDataProvider
* data
,
580 std::string
* result
) {
581 const int kSize
= 3000;
584 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
585 TestCompletionCallback callback
;
587 int rv
= trans
->Read(buf
.get(), kSize
, callback
.callback());
588 if (rv
== ERR_IO_PENDING
) {
589 // Multiple transactions may be in the data set. Keep pulling off
590 // reads until we complete our callback.
591 while (!callback
.have_result()) {
592 data
->CompleteRead();
593 base::RunLoop().RunUntilIdle();
595 rv
= callback
.WaitForResult();
596 } else if (rv
<= 0) {
599 result
->append(buf
->data(), rv
);
605 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
606 // This lengthy block is reaching into the pool to dig out the active
607 // session. Once we have the session, we verify that the streams are
608 // all closed and not leaked at this point.
609 const GURL
& url
= helper
.request().url
;
610 int port
= helper
.test_params().ssl_type
== SPDYNPN
? 443 : 80;
611 HostPortPair
host_port_pair(url
.host(), port
);
612 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
613 PRIVACY_MODE_DISABLED
);
615 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
616 base::WeakPtr
<SpdySession
> spdy_session
=
617 session
->spdy_session_pool()->FindAvailableSession(key
, log
);
618 ASSERT_TRUE(spdy_session
!= NULL
);
619 EXPECT_EQ(0u, spdy_session
->num_active_streams());
620 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
623 void RunServerPushTest(OrderedSocketData
* data
,
624 HttpResponseInfo
* response
,
625 HttpResponseInfo
* push_response
,
626 const std::string
& expected
) {
627 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
628 BoundNetLog(), GetParam(), NULL
);
629 helper
.RunPreTestSetup();
630 helper
.AddData(data
);
632 HttpNetworkTransaction
* trans
= helper
.trans();
634 // Start the transaction with basic parameters.
635 TestCompletionCallback callback
;
636 int rv
= trans
->Start(
637 &CreateGetRequest(), callback
.callback(), BoundNetLog());
638 EXPECT_EQ(ERR_IO_PENDING
, rv
);
639 rv
= callback
.WaitForResult();
641 // Request the pushed path.
642 scoped_ptr
<HttpNetworkTransaction
> trans2(
643 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
645 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
646 EXPECT_EQ(ERR_IO_PENDING
, rv
);
647 base::RunLoop().RunUntilIdle();
649 // The data for the pushed path may be coming in more than 1 frame. Compile
650 // the results into a single string.
652 // Read the server push body.
654 ReadResult(trans2
.get(), data
, &result2
);
655 // Read the response body.
657 ReadResult(trans
, data
, &result
);
659 // Verify that we consumed all test data.
660 EXPECT_TRUE(data
->at_read_eof());
661 EXPECT_TRUE(data
->at_write_eof());
663 // Verify that the received push data is same as the expected push data.
664 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
666 << "||||| Expected data: "
669 // Verify the SYN_REPLY.
670 // Copy the response info, because trans goes away.
671 *response
= *trans
->GetResponseInfo();
672 *push_response
= *trans2
->GetResponseInfo();
674 VerifyStreamsClosed(helper
);
677 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
679 helper
->ResetTrans();
682 static void StartTransactionCallback(
683 const scoped_refptr
<HttpNetworkSession
>& session
,
685 scoped_ptr
<HttpNetworkTransaction
> trans(
686 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
687 TestCompletionCallback callback
;
688 HttpRequestInfo request
;
689 request
.method
= "GET";
690 request
.url
= GURL("http://www.google.com/");
691 request
.load_flags
= 0;
692 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
693 EXPECT_EQ(ERR_IO_PENDING
, rv
);
694 callback
.WaitForResult();
697 ChunkedUploadDataStream
* upload_chunked_data_stream() const {
698 return upload_chunked_data_stream_
.get();
701 SpdyTestUtil spdy_util_
;
704 scoped_ptr
<ChunkedUploadDataStream
> upload_chunked_data_stream_
;
705 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
706 bool google_get_request_initialized_
;
707 bool google_post_request_initialized_
;
708 bool google_chunked_post_request_initialized_
;
709 HttpRequestInfo google_get_request_
;
710 HttpRequestInfo google_post_request_
;
711 HttpRequestInfo google_chunked_post_request_
;
712 HttpRequestInfo google_get_push_request_
;
713 base::ScopedTempDir temp_dir_
;
716 //-----------------------------------------------------------------------------
717 // All tests are run with three different connection types: SPDY after NPN
718 // negotiation, SPDY without SSL, and SPDY with SSL.
720 // TODO(akalin): Use ::testing::Combine() when we are able to use
722 INSTANTIATE_TEST_CASE_P(
724 SpdyNetworkTransactionTest
,
726 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNOSSL
),
727 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYSSL
),
728 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
),
729 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNOSSL
),
730 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYSSL
),
731 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
732 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNOSSL
),
733 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYSSL
),
734 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNPN
)));
736 // Verify HttpNetworkTransaction constructor.
737 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
738 scoped_ptr
<SpdySessionDependencies
> session_deps(
739 CreateSpdySessionDependencies(GetParam()));
740 scoped_refptr
<HttpNetworkSession
> session(
741 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
742 scoped_ptr
<HttpTransaction
> trans(
743 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
746 TEST_P(SpdyNetworkTransactionTest
, Get
) {
747 // Construct the request.
748 scoped_ptr
<SpdyFrame
> req(
749 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
750 MockWrite writes
[] = { CreateMockWrite(*req
) };
752 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
753 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
755 CreateMockRead(*resp
),
756 CreateMockRead(*body
),
757 MockRead(ASYNC
, 0, 0) // EOF
760 DelayedSocketData
data(1, reads
, arraysize(reads
),
761 writes
, arraysize(writes
));
762 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
763 BoundNetLog(), GetParam(), NULL
);
764 helper
.RunToCompletion(&data
);
765 TransactionHelperResult out
= helper
.output();
766 EXPECT_EQ(OK
, out
.rv
);
767 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
768 EXPECT_EQ("hello!", out
.response_data
);
771 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
772 for (RequestPriority p
= MINIMUM_PRIORITY
; p
<= MAXIMUM_PRIORITY
;
773 p
= RequestPriority(p
+ 1)) {
774 // Construct the request.
775 scoped_ptr
<SpdyFrame
> req(
776 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
777 MockWrite writes
[] = { CreateMockWrite(*req
) };
779 SpdyPriority spdy_prio
= 0;
780 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
781 // this repeats the RequestPriority-->SpdyPriority mapping from
782 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
783 // sure it's being done right.
784 if (spdy_util_
.spdy_version() < SPDY3
) {
787 EXPECT_EQ(0, spdy_prio
);
790 EXPECT_EQ(1, spdy_prio
);
794 EXPECT_EQ(2, spdy_prio
);
797 EXPECT_EQ(3, spdy_prio
);
805 EXPECT_EQ(0, spdy_prio
);
808 EXPECT_EQ(1, spdy_prio
);
811 EXPECT_EQ(2, spdy_prio
);
814 EXPECT_EQ(3, spdy_prio
);
817 EXPECT_EQ(4, spdy_prio
);
824 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
825 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
827 CreateMockRead(*resp
),
828 CreateMockRead(*body
),
829 MockRead(ASYNC
, 0, 0) // EOF
832 DelayedSocketData
data(1, reads
, arraysize(reads
),
833 writes
, arraysize(writes
));
834 HttpRequestInfo http_req
= CreateGetRequest();
836 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
838 helper
.RunToCompletion(&data
);
839 TransactionHelperResult out
= helper
.output();
840 EXPECT_EQ(OK
, out
.rv
);
841 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
842 EXPECT_EQ("hello!", out
.response_data
);
846 // Start three gets simultaniously; making sure that multiplexed
847 // streams work properly.
849 // This can't use the TransactionHelper method, since it only
850 // handles a single transaction, and finishes them as soon
851 // as it launches them.
853 // TODO(gavinp): create a working generalized TransactionHelper that
854 // can allow multiple streams in flight.
856 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
857 scoped_ptr
<SpdyFrame
> req(
858 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
859 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
860 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
861 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
863 scoped_ptr
<SpdyFrame
> req2(
864 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
865 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
866 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
867 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
869 scoped_ptr
<SpdyFrame
> req3(
870 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
871 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
872 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
873 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
875 MockWrite writes
[] = {
876 CreateMockWrite(*req
),
877 CreateMockWrite(*req2
),
878 CreateMockWrite(*req3
),
881 CreateMockRead(*resp
, 1),
882 CreateMockRead(*body
),
883 CreateMockRead(*resp2
, 4),
884 CreateMockRead(*body2
),
885 CreateMockRead(*resp3
, 7),
886 CreateMockRead(*body3
),
888 CreateMockRead(*fbody
),
889 CreateMockRead(*fbody2
),
890 CreateMockRead(*fbody3
),
892 MockRead(ASYNC
, 0, 0), // EOF
894 OrderedSocketData
data(reads
, arraysize(reads
),
895 writes
, arraysize(writes
));
896 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
899 TransactionHelperResult out
;
900 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
901 BoundNetLog(), GetParam(), NULL
);
902 helper
.RunPreTestSetup();
903 helper
.AddData(&data
);
904 // We require placeholder data because three get requests are sent out, so
905 // there needs to be three sets of SSL connection data.
906 helper
.AddData(&data_placeholder
);
907 helper
.AddData(&data_placeholder
);
908 scoped_ptr
<HttpNetworkTransaction
> trans1(
909 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
910 scoped_ptr
<HttpNetworkTransaction
> trans2(
911 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
912 scoped_ptr
<HttpNetworkTransaction
> trans3(
913 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
915 TestCompletionCallback callback1
;
916 TestCompletionCallback callback2
;
917 TestCompletionCallback callback3
;
919 HttpRequestInfo httpreq1
= CreateGetRequest();
920 HttpRequestInfo httpreq2
= CreateGetRequest();
921 HttpRequestInfo httpreq3
= CreateGetRequest();
923 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
924 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
925 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
926 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
927 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
928 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
930 out
.rv
= callback1
.WaitForResult();
931 ASSERT_EQ(OK
, out
.rv
);
932 out
.rv
= callback3
.WaitForResult();
933 ASSERT_EQ(OK
, out
.rv
);
935 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
936 EXPECT_TRUE(response1
->headers
.get() != NULL
);
937 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
938 out
.status_line
= response1
->headers
->GetStatusLine();
939 out
.response_info
= *response1
;
941 trans2
->GetResponseInfo();
943 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
944 helper
.VerifyDataConsumed();
945 EXPECT_EQ(OK
, out
.rv
);
947 EXPECT_EQ(OK
, out
.rv
);
948 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
949 EXPECT_EQ("hello!hello!", out
.response_data
);
952 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
953 scoped_ptr
<SpdyFrame
> req(
954 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
955 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
956 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
957 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
959 scoped_ptr
<SpdyFrame
> req2(
960 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
961 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
962 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
963 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
965 MockWrite writes
[] = {
966 CreateMockWrite(*req
),
967 CreateMockWrite(*req2
),
970 CreateMockRead(*resp
, 1),
971 CreateMockRead(*body
),
972 CreateMockRead(*resp2
, 4),
973 CreateMockRead(*body2
),
974 CreateMockRead(*fbody
),
975 CreateMockRead(*fbody2
),
976 MockRead(ASYNC
, 0, 0), // EOF
978 OrderedSocketData
data(reads
, arraysize(reads
),
979 writes
, arraysize(writes
));
981 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
983 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
984 data_placeholder
.set_connect_data(never_finishing_connect
);
987 TransactionHelperResult out
;
988 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
989 BoundNetLog(), GetParam(), NULL
);
990 helper
.RunPreTestSetup();
991 helper
.AddData(&data
);
992 // We require placeholder data because two get requests are sent out, so
993 // there needs to be two sets of SSL connection data.
994 helper
.AddData(&data_placeholder
);
995 scoped_ptr
<HttpNetworkTransaction
> trans1(
996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
997 scoped_ptr
<HttpNetworkTransaction
> trans2(
998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1000 TestCompletionCallback callback1
;
1001 TestCompletionCallback callback2
;
1003 HttpRequestInfo httpreq1
= CreateGetRequest();
1004 HttpRequestInfo httpreq2
= CreateGetRequest();
1006 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1007 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1008 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1009 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1011 out
.rv
= callback1
.WaitForResult();
1012 ASSERT_EQ(OK
, out
.rv
);
1013 out
.rv
= callback2
.WaitForResult();
1014 ASSERT_EQ(OK
, out
.rv
);
1016 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1017 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1018 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1019 out
.status_line
= response1
->headers
->GetStatusLine();
1020 out
.response_info
= *response1
;
1021 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1022 EXPECT_EQ(OK
, out
.rv
);
1023 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1024 EXPECT_EQ("hello!hello!", out
.response_data
);
1026 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1027 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1028 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1029 out
.status_line
= response2
->headers
->GetStatusLine();
1030 out
.response_info
= *response2
;
1031 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1032 EXPECT_EQ(OK
, out
.rv
);
1033 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1034 EXPECT_EQ("hello!hello!", out
.response_data
);
1036 helper
.VerifyDataConsumed();
1039 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
1040 scoped_ptr
<SpdyFrame
> req(
1041 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1042 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1043 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1044 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1046 scoped_ptr
<SpdyFrame
> req2(
1047 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1048 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1049 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1050 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1052 MockWrite writes
[] = {
1053 CreateMockWrite(*req
),
1054 CreateMockWrite(*req2
),
1056 MockRead reads
[] = {
1057 CreateMockRead(*resp
, 1),
1058 CreateMockRead(*body
),
1059 CreateMockRead(*resp2
, 4),
1060 CreateMockRead(*body2
),
1061 CreateMockRead(*fbody
),
1062 CreateMockRead(*fbody2
),
1063 MockRead(ASYNC
, 0, 0), // EOF
1065 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
1066 writes
, arraysize(writes
));
1068 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1070 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1071 data_placeholder
.set_connect_data(never_finishing_connect
);
1074 TransactionHelperResult out
;
1075 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1076 BoundNetLog(), GetParam(), NULL
);
1077 helper
.RunPreTestSetup();
1078 helper
.AddData(&preconnect_data
);
1079 // We require placeholder data because 3 connections are attempted (first is
1080 // the preconnect, 2nd and 3rd are the never finished connections.
1081 helper
.AddData(&data_placeholder
);
1082 helper
.AddData(&data_placeholder
);
1084 scoped_ptr
<HttpNetworkTransaction
> trans1(
1085 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1086 scoped_ptr
<HttpNetworkTransaction
> trans2(
1087 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1089 TestCompletionCallback callback1
;
1090 TestCompletionCallback callback2
;
1092 HttpRequestInfo httpreq
= CreateGetRequest();
1094 // Preconnect the first.
1095 SSLConfig preconnect_ssl_config
;
1096 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1097 HttpStreamFactory
* http_stream_factory
=
1098 helper
.session()->http_stream_factory();
1099 helper
.session()->GetNextProtos(&preconnect_ssl_config
.next_protos
);
1101 http_stream_factory
->PreconnectStreams(
1102 1, httpreq
, DEFAULT_PRIORITY
,
1103 preconnect_ssl_config
, preconnect_ssl_config
);
1105 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1106 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1107 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1108 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1110 out
.rv
= callback1
.WaitForResult();
1111 ASSERT_EQ(OK
, out
.rv
);
1112 out
.rv
= callback2
.WaitForResult();
1113 ASSERT_EQ(OK
, out
.rv
);
1115 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1116 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1117 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1118 out
.status_line
= response1
->headers
->GetStatusLine();
1119 out
.response_info
= *response1
;
1120 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1121 EXPECT_EQ(OK
, out
.rv
);
1122 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1123 EXPECT_EQ("hello!hello!", out
.response_data
);
1125 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1126 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1127 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1128 out
.status_line
= response2
->headers
->GetStatusLine();
1129 out
.response_info
= *response2
;
1130 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1131 EXPECT_EQ(OK
, out
.rv
);
1132 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1133 EXPECT_EQ("hello!hello!", out
.response_data
);
1135 helper
.VerifyDataConsumed();
1138 // Similar to ThreeGets above, however this test adds a SETTINGS
1139 // frame. The SETTINGS frame is read during the IO loop waiting on
1140 // the first transaction completion, and sets a maximum concurrent
1141 // stream limit of 1. This means that our IO loop exists after the
1142 // second transaction completes, so we can assert on read_index().
1143 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1144 // Construct the request.
1145 scoped_ptr
<SpdyFrame
> req(
1146 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1147 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1148 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1149 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1151 scoped_ptr
<SpdyFrame
> req2(
1152 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1153 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1154 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1155 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1157 scoped_ptr
<SpdyFrame
> req3(
1158 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1159 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1160 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1161 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1163 SettingsMap settings
;
1164 const uint32 max_concurrent_streams
= 1;
1165 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1166 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1167 scoped_ptr
<SpdyFrame
> settings_frame(
1168 spdy_util_
.ConstructSpdySettings(settings
));
1169 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1171 MockWrite writes
[] = {
1172 CreateMockWrite(*req
),
1173 CreateMockWrite(*settings_ack
, 2),
1174 CreateMockWrite(*req2
),
1175 CreateMockWrite(*req3
),
1178 MockRead reads
[] = {
1179 CreateMockRead(*settings_frame
, 1),
1180 CreateMockRead(*resp
),
1181 CreateMockRead(*body
),
1182 CreateMockRead(*fbody
),
1183 CreateMockRead(*resp2
, 8),
1184 CreateMockRead(*body2
),
1185 CreateMockRead(*fbody2
),
1186 CreateMockRead(*resp3
, 13),
1187 CreateMockRead(*body3
),
1188 CreateMockRead(*fbody3
),
1190 MockRead(ASYNC
, 0, 0), // EOF
1193 OrderedSocketData
data(reads
, arraysize(reads
),
1194 writes
, arraysize(writes
));
1195 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1198 TransactionHelperResult out
;
1200 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1201 BoundNetLog(), GetParam(), NULL
);
1202 helper
.RunPreTestSetup();
1203 helper
.AddData(&data
);
1204 // We require placeholder data because three get requests are sent out, so
1205 // there needs to be three sets of SSL connection data.
1206 helper
.AddData(&data_placeholder
);
1207 helper
.AddData(&data_placeholder
);
1208 scoped_ptr
<HttpNetworkTransaction
> trans1(
1209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1210 scoped_ptr
<HttpNetworkTransaction
> trans2(
1211 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1212 scoped_ptr
<HttpNetworkTransaction
> trans3(
1213 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1215 TestCompletionCallback callback1
;
1216 TestCompletionCallback callback2
;
1217 TestCompletionCallback callback3
;
1219 HttpRequestInfo httpreq1
= CreateGetRequest();
1220 HttpRequestInfo httpreq2
= CreateGetRequest();
1221 HttpRequestInfo httpreq3
= CreateGetRequest();
1223 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1224 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1225 // Run transaction 1 through quickly to force a read of our SETTINGS
1227 out
.rv
= callback1
.WaitForResult();
1228 ASSERT_EQ(OK
, out
.rv
);
1230 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1231 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1232 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1233 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1234 out
.rv
= callback2
.WaitForResult();
1235 ASSERT_EQ(OK
, out
.rv
);
1236 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1238 out
.rv
= callback3
.WaitForResult();
1239 ASSERT_EQ(OK
, out
.rv
);
1241 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1242 ASSERT_TRUE(response1
!= NULL
);
1243 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1244 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1245 out
.status_line
= response1
->headers
->GetStatusLine();
1246 out
.response_info
= *response1
;
1247 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1248 EXPECT_EQ(OK
, out
.rv
);
1249 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1250 EXPECT_EQ("hello!hello!", out
.response_data
);
1252 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1253 out
.status_line
= response2
->headers
->GetStatusLine();
1254 out
.response_info
= *response2
;
1255 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1256 EXPECT_EQ(OK
, out
.rv
);
1257 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1258 EXPECT_EQ("hello!hello!", out
.response_data
);
1260 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1261 out
.status_line
= response3
->headers
->GetStatusLine();
1262 out
.response_info
= *response3
;
1263 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1264 EXPECT_EQ(OK
, out
.rv
);
1265 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1266 EXPECT_EQ("hello!hello!", out
.response_data
);
1268 helper
.VerifyDataConsumed();
1270 EXPECT_EQ(OK
, out
.rv
);
1273 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1274 // a fourth transaction. The third and fourth transactions have
1275 // different data ("hello!" vs "hello!hello!") and because of the
1276 // user specified priority, we expect to see them inverted in
1277 // the response from the server.
1278 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1279 // Construct the request.
1280 scoped_ptr
<SpdyFrame
> req(
1281 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1282 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1283 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1284 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1286 scoped_ptr
<SpdyFrame
> req2(
1287 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1288 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1289 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1290 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1292 scoped_ptr
<SpdyFrame
> req4(
1293 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1294 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1295 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1297 scoped_ptr
<SpdyFrame
> req3(
1298 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1299 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1300 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1301 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1303 SettingsMap settings
;
1304 const uint32 max_concurrent_streams
= 1;
1305 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1306 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1307 scoped_ptr
<SpdyFrame
> settings_frame(
1308 spdy_util_
.ConstructSpdySettings(settings
));
1309 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1311 MockWrite writes
[] = { CreateMockWrite(*req
),
1312 CreateMockWrite(*settings_ack
, 2),
1313 CreateMockWrite(*req2
),
1314 CreateMockWrite(*req4
),
1315 CreateMockWrite(*req3
),
1317 MockRead reads
[] = {
1318 CreateMockRead(*settings_frame
, 1),
1319 CreateMockRead(*resp
),
1320 CreateMockRead(*body
),
1321 CreateMockRead(*fbody
),
1322 CreateMockRead(*resp2
, 8),
1323 CreateMockRead(*body2
),
1324 CreateMockRead(*fbody2
),
1325 CreateMockRead(*resp4
, 14),
1326 CreateMockRead(*fbody4
),
1327 CreateMockRead(*resp3
, 17),
1328 CreateMockRead(*body3
),
1329 CreateMockRead(*fbody3
),
1331 MockRead(ASYNC
, 0, 0), // EOF
1334 OrderedSocketData
data(reads
, arraysize(reads
),
1335 writes
, arraysize(writes
));
1336 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1339 TransactionHelperResult out
;
1340 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1341 BoundNetLog(), GetParam(), NULL
);
1342 helper
.RunPreTestSetup();
1343 helper
.AddData(&data
);
1344 // We require placeholder data because four get requests are sent out, so
1345 // there needs to be four sets of SSL connection data.
1346 helper
.AddData(&data_placeholder
);
1347 helper
.AddData(&data_placeholder
);
1348 helper
.AddData(&data_placeholder
);
1349 scoped_ptr
<HttpNetworkTransaction
> trans1(
1350 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1351 scoped_ptr
<HttpNetworkTransaction
> trans2(
1352 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1353 scoped_ptr
<HttpNetworkTransaction
> trans3(
1354 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1355 scoped_ptr
<HttpNetworkTransaction
> trans4(
1356 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1358 TestCompletionCallback callback1
;
1359 TestCompletionCallback callback2
;
1360 TestCompletionCallback callback3
;
1361 TestCompletionCallback callback4
;
1363 HttpRequestInfo httpreq1
= CreateGetRequest();
1364 HttpRequestInfo httpreq2
= CreateGetRequest();
1365 HttpRequestInfo httpreq3
= CreateGetRequest();
1366 HttpRequestInfo httpreq4
= CreateGetRequest();
1368 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1369 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1370 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1371 out
.rv
= callback1
.WaitForResult();
1372 ASSERT_EQ(OK
, out
.rv
);
1374 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1375 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1376 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1377 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1378 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1379 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1381 out
.rv
= callback2
.WaitForResult();
1382 ASSERT_EQ(OK
, out
.rv
);
1383 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1385 out
.rv
= callback3
.WaitForResult();
1386 ASSERT_EQ(OK
, out
.rv
);
1388 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1389 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1390 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1391 out
.status_line
= response1
->headers
->GetStatusLine();
1392 out
.response_info
= *response1
;
1393 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1394 EXPECT_EQ(OK
, out
.rv
);
1395 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1396 EXPECT_EQ("hello!hello!", out
.response_data
);
1398 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1399 out
.status_line
= response2
->headers
->GetStatusLine();
1400 out
.response_info
= *response2
;
1401 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1402 EXPECT_EQ(OK
, out
.rv
);
1403 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1404 EXPECT_EQ("hello!hello!", out
.response_data
);
1406 // notice: response3 gets two hellos, response4 gets one
1407 // hello, so we know dequeuing priority was respected.
1408 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1409 out
.status_line
= response3
->headers
->GetStatusLine();
1410 out
.response_info
= *response3
;
1411 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1412 EXPECT_EQ(OK
, out
.rv
);
1413 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1414 EXPECT_EQ("hello!hello!", out
.response_data
);
1416 out
.rv
= callback4
.WaitForResult();
1417 EXPECT_EQ(OK
, out
.rv
);
1418 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1419 out
.status_line
= response4
->headers
->GetStatusLine();
1420 out
.response_info
= *response4
;
1421 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1422 EXPECT_EQ(OK
, out
.rv
);
1423 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1424 EXPECT_EQ("hello!", out
.response_data
);
1425 helper
.VerifyDataConsumed();
1426 EXPECT_EQ(OK
, out
.rv
);
1429 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1430 // deletes a session in the middle of the transaction to insure
1431 // that we properly remove pendingcreatestream objects from
1433 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1434 // Construct the request.
1435 scoped_ptr
<SpdyFrame
> req(
1436 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1437 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1438 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1439 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1441 scoped_ptr
<SpdyFrame
> req2(
1442 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1443 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1444 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1445 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1447 SettingsMap settings
;
1448 const uint32 max_concurrent_streams
= 1;
1449 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1450 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1451 scoped_ptr
<SpdyFrame
> settings_frame(
1452 spdy_util_
.ConstructSpdySettings(settings
));
1453 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1455 MockWrite writes
[] = {
1456 CreateMockWrite(*req
),
1457 CreateMockWrite(*settings_ack
, 2),
1458 CreateMockWrite(*req2
),
1460 MockRead reads
[] = {
1461 CreateMockRead(*settings_frame
, 1),
1462 CreateMockRead(*resp
),
1463 CreateMockRead(*body
),
1464 CreateMockRead(*fbody
),
1465 CreateMockRead(*resp2
, 8),
1466 CreateMockRead(*body2
),
1467 CreateMockRead(*fbody2
),
1468 MockRead(ASYNC
, 0, 0), // EOF
1471 OrderedSocketData
data(reads
, arraysize(reads
),
1472 writes
, arraysize(writes
));
1473 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1476 TransactionHelperResult out
;
1477 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1478 BoundNetLog(), GetParam(), NULL
);
1479 helper
.RunPreTestSetup();
1480 helper
.AddData(&data
);
1481 // We require placeholder data because three get requests are sent out, so
1482 // there needs to be three sets of SSL connection data.
1483 helper
.AddData(&data_placeholder
);
1484 helper
.AddData(&data_placeholder
);
1485 scoped_ptr
<HttpNetworkTransaction
> trans1(
1486 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1487 scoped_ptr
<HttpNetworkTransaction
> trans2(
1488 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1489 scoped_ptr
<HttpNetworkTransaction
> trans3(
1490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1492 TestCompletionCallback callback1
;
1493 TestCompletionCallback callback2
;
1494 TestCompletionCallback callback3
;
1496 HttpRequestInfo httpreq1
= CreateGetRequest();
1497 HttpRequestInfo httpreq2
= CreateGetRequest();
1498 HttpRequestInfo httpreq3
= CreateGetRequest();
1500 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1501 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1502 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1503 out
.rv
= callback1
.WaitForResult();
1504 ASSERT_EQ(OK
, out
.rv
);
1506 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1507 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1508 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1509 delete trans3
.release();
1510 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1511 out
.rv
= callback2
.WaitForResult();
1512 ASSERT_EQ(OK
, out
.rv
);
1514 EXPECT_EQ(8U, data
.read_index());
1516 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1517 ASSERT_TRUE(response1
!= NULL
);
1518 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1519 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1520 out
.status_line
= response1
->headers
->GetStatusLine();
1521 out
.response_info
= *response1
;
1522 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1523 EXPECT_EQ(OK
, out
.rv
);
1524 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1525 EXPECT_EQ("hello!hello!", out
.response_data
);
1527 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1528 ASSERT_TRUE(response2
!= NULL
);
1529 out
.status_line
= response2
->headers
->GetStatusLine();
1530 out
.response_info
= *response2
;
1531 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1532 EXPECT_EQ(OK
, out
.rv
);
1533 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1534 EXPECT_EQ("hello!hello!", out
.response_data
);
1535 helper
.VerifyDataConsumed();
1536 EXPECT_EQ(OK
, out
.rv
);
1541 // The KillerCallback will delete the transaction on error as part of the
1543 class KillerCallback
: public TestCompletionCallbackBase
{
1545 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1546 : transaction_(transaction
),
1547 callback_(base::Bind(&KillerCallback::OnComplete
,
1548 base::Unretained(this))) {
1551 ~KillerCallback() override
{}
1553 const CompletionCallback
& callback() const { return callback_
; }
1556 void OnComplete(int result
) {
1558 delete transaction_
;
1563 HttpNetworkTransaction
* transaction_
;
1564 CompletionCallback callback_
;
1569 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1570 // closes the socket while we have a pending transaction waiting for
1571 // a pending stream creation. http://crbug.com/52901
1572 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1573 // Construct the request.
1574 scoped_ptr
<SpdyFrame
> req(
1575 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1576 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1577 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1578 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1580 scoped_ptr
<SpdyFrame
> req2(
1581 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1582 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1584 SettingsMap settings
;
1585 const uint32 max_concurrent_streams
= 1;
1586 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1587 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1588 scoped_ptr
<SpdyFrame
> settings_frame(
1589 spdy_util_
.ConstructSpdySettings(settings
));
1590 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1592 MockWrite writes
[] = {
1593 CreateMockWrite(*req
),
1594 CreateMockWrite(*settings_ack
, 2),
1595 CreateMockWrite(*req2
),
1597 MockRead reads
[] = {
1598 CreateMockRead(*settings_frame
, 1),
1599 CreateMockRead(*resp
),
1600 CreateMockRead(*body
),
1601 CreateMockRead(*fin_body
),
1602 CreateMockRead(*resp2
, 8),
1603 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1606 OrderedSocketData
data(reads
, arraysize(reads
),
1607 writes
, arraysize(writes
));
1608 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1611 TransactionHelperResult out
;
1612 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1613 BoundNetLog(), GetParam(), NULL
);
1614 helper
.RunPreTestSetup();
1615 helper
.AddData(&data
);
1616 // We require placeholder data because three get requests are sent out, so
1617 // there needs to be three sets of SSL connection data.
1618 helper
.AddData(&data_placeholder
);
1619 helper
.AddData(&data_placeholder
);
1620 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1621 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1622 HttpNetworkTransaction
* trans3(
1623 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1625 TestCompletionCallback callback1
;
1626 TestCompletionCallback callback2
;
1627 KillerCallback
callback3(trans3
);
1629 HttpRequestInfo httpreq1
= CreateGetRequest();
1630 HttpRequestInfo httpreq2
= CreateGetRequest();
1631 HttpRequestInfo httpreq3
= CreateGetRequest();
1633 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1634 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1635 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1636 out
.rv
= callback1
.WaitForResult();
1637 ASSERT_EQ(OK
, out
.rv
);
1639 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1640 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1641 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1642 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1643 out
.rv
= callback3
.WaitForResult();
1644 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1646 EXPECT_EQ(6U, data
.read_index());
1648 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1649 ASSERT_TRUE(response1
!= NULL
);
1650 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1651 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1652 out
.status_line
= response1
->headers
->GetStatusLine();
1653 out
.response_info
= *response1
;
1654 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1655 EXPECT_EQ(OK
, out
.rv
);
1657 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1658 ASSERT_TRUE(response2
!= NULL
);
1659 out
.status_line
= response2
->headers
->GetStatusLine();
1660 out
.response_info
= *response2
;
1661 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1662 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1664 helper
.VerifyDataConsumed();
1667 // Test that a simple PUT request works.
1668 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1669 // Setup the request
1670 HttpRequestInfo request
;
1671 request
.method
= "PUT";
1672 request
.url
= GURL("http://www.google.com/");
1674 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1675 spdy_util_
.ConstructPutHeaderBlock("http://www.google.com", 0));
1676 scoped_ptr
<SpdyFrame
> req(
1677 spdy_util_
.ConstructSpdySyn(1, *put_headers
, LOWEST
, false, true));
1678 MockWrite writes
[] = {
1679 CreateMockWrite(*req
),
1682 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1683 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1684 MockRead reads
[] = {
1685 CreateMockRead(*resp
),
1686 CreateMockRead(*body
),
1687 MockRead(ASYNC
, 0, 0) // EOF
1690 DelayedSocketData
data(1, reads
, arraysize(reads
),
1691 writes
, arraysize(writes
));
1692 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1693 BoundNetLog(), GetParam(), NULL
);
1694 helper
.RunToCompletion(&data
);
1695 TransactionHelperResult out
= helper
.output();
1697 EXPECT_EQ(OK
, out
.rv
);
1698 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1701 // Test that a simple HEAD request works.
1702 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1703 // Setup the request
1704 HttpRequestInfo request
;
1705 request
.method
= "HEAD";
1706 request
.url
= GURL("http://www.google.com/");
1708 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1709 spdy_util_
.ConstructHeadHeaderBlock("http://www.google.com", 0));
1710 scoped_ptr
<SpdyFrame
> req(
1711 spdy_util_
.ConstructSpdySyn(1, *head_headers
, LOWEST
, false, true));
1712 MockWrite writes
[] = {
1713 CreateMockWrite(*req
),
1716 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1717 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1718 MockRead reads
[] = {
1719 CreateMockRead(*resp
),
1720 CreateMockRead(*body
),
1721 MockRead(ASYNC
, 0, 0) // EOF
1724 DelayedSocketData
data(1, reads
, arraysize(reads
),
1725 writes
, arraysize(writes
));
1726 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1727 BoundNetLog(), GetParam(), NULL
);
1728 helper
.RunToCompletion(&data
);
1729 TransactionHelperResult out
= helper
.output();
1731 EXPECT_EQ(OK
, out
.rv
);
1732 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1735 // Test that a simple POST works.
1736 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1737 scoped_ptr
<SpdyFrame
> req(
1738 spdy_util_
.ConstructSpdyPost(
1739 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1740 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1741 MockWrite writes
[] = {
1742 CreateMockWrite(*req
),
1743 CreateMockWrite(*body
), // POST upload frame
1746 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1747 MockRead reads
[] = {
1748 CreateMockRead(*resp
),
1749 CreateMockRead(*body
),
1750 MockRead(ASYNC
, 0, 0) // EOF
1753 DelayedSocketData
data(2, reads
, arraysize(reads
),
1754 writes
, arraysize(writes
));
1755 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
1756 BoundNetLog(), GetParam(), NULL
);
1757 helper
.RunToCompletion(&data
);
1758 TransactionHelperResult out
= helper
.output();
1759 EXPECT_EQ(OK
, out
.rv
);
1760 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1761 EXPECT_EQ("hello!", out
.response_data
);
1764 // Test that a POST with a file works.
1765 TEST_P(SpdyNetworkTransactionTest
, FilePost
) {
1766 scoped_ptr
<SpdyFrame
> req(
1767 spdy_util_
.ConstructSpdyPost(
1768 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1769 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1770 MockWrite writes
[] = {
1771 CreateMockWrite(*req
),
1772 CreateMockWrite(*body
), // POST upload frame
1775 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1776 MockRead reads
[] = {
1777 CreateMockRead(*resp
),
1778 CreateMockRead(*body
),
1779 MockRead(ASYNC
, 0, 0) // EOF
1782 DelayedSocketData
data(2, reads
, arraysize(reads
),
1783 writes
, arraysize(writes
));
1784 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(), DEFAULT_PRIORITY
,
1785 BoundNetLog(), GetParam(), NULL
);
1786 helper
.RunToCompletion(&data
);
1787 TransactionHelperResult out
= helper
.output();
1788 EXPECT_EQ(OK
, out
.rv
);
1789 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1790 EXPECT_EQ("hello!", out
.response_data
);
1793 // Test that a POST with a unreadable file fails.
1794 TEST_P(SpdyNetworkTransactionTest
, UnreadableFilePost
) {
1795 MockWrite writes
[] = {
1796 MockWrite(ASYNC
, 0, 0) // EOF
1798 MockRead reads
[] = {
1799 MockRead(ASYNC
, 0, 0) // EOF
1802 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1803 NormalSpdyTransactionHelper
helper(CreateUnreadableFilePostRequest(),
1805 BoundNetLog(), GetParam(), NULL
);
1806 helper
.RunPreTestSetup();
1807 helper
.AddData(&data
);
1808 helper
.RunDefaultTest();
1810 base::RunLoop().RunUntilIdle();
1811 helper
.VerifyDataNotConsumed();
1812 EXPECT_EQ(ERR_ACCESS_DENIED
, helper
.output().rv
);
1815 // Test that a complex POST works.
1816 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1817 scoped_ptr
<SpdyFrame
> req(
1818 spdy_util_
.ConstructSpdyPost(
1819 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1820 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1821 MockWrite writes
[] = {
1822 CreateMockWrite(*req
),
1823 CreateMockWrite(*body
), // POST upload frame
1826 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1827 MockRead reads
[] = {
1828 CreateMockRead(*resp
),
1829 CreateMockRead(*body
),
1830 MockRead(ASYNC
, 0, 0) // EOF
1833 DelayedSocketData
data(2, reads
, arraysize(reads
),
1834 writes
, arraysize(writes
));
1835 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1837 BoundNetLog(), GetParam(), NULL
);
1838 helper
.RunToCompletion(&data
);
1839 TransactionHelperResult out
= helper
.output();
1840 EXPECT_EQ(OK
, out
.rv
);
1841 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1842 EXPECT_EQ("hello!", out
.response_data
);
1845 // Test that a chunked POST works.
1846 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1847 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1848 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1849 MockWrite writes
[] = {
1850 CreateMockWrite(*req
),
1851 CreateMockWrite(*body
),
1854 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1855 MockRead reads
[] = {
1856 CreateMockRead(*resp
),
1857 CreateMockRead(*body
),
1858 MockRead(ASYNC
, 0, 0) // EOF
1861 DelayedSocketData
data(2, reads
, arraysize(reads
),
1862 writes
, arraysize(writes
));
1863 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1865 BoundNetLog(), GetParam(), NULL
);
1867 // These chunks get merged into a single frame when being sent.
1868 const int kFirstChunkSize
= kUploadDataSize
/2;
1869 upload_chunked_data_stream()->AppendData(kUploadData
, kFirstChunkSize
, false);
1870 upload_chunked_data_stream()->AppendData(
1871 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1873 helper
.RunToCompletion(&data
);
1874 TransactionHelperResult out
= helper
.output();
1875 EXPECT_EQ(OK
, out
.rv
);
1876 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1877 EXPECT_EQ(kUploadData
, out
.response_data
);
1880 // Test that a chunked POST works with chunks appended after transaction starts.
1881 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1882 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1883 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1884 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1885 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1886 MockWrite writes
[] = {
1887 CreateMockWrite(*req
),
1888 CreateMockWrite(*chunk1
),
1889 CreateMockWrite(*chunk2
),
1890 CreateMockWrite(*chunk3
),
1893 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1894 MockRead reads
[] = {
1895 CreateMockRead(*resp
),
1896 CreateMockRead(*chunk1
),
1897 CreateMockRead(*chunk2
),
1898 CreateMockRead(*chunk3
),
1899 MockRead(ASYNC
, 0, 0) // EOF
1902 DelayedSocketData
data(4, reads
, arraysize(reads
),
1903 writes
, arraysize(writes
));
1904 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1906 BoundNetLog(), GetParam(), NULL
);
1908 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1910 helper
.RunPreTestSetup();
1911 helper
.AddData(&data
);
1912 ASSERT_TRUE(helper
.StartDefaultTest());
1914 base::RunLoop().RunUntilIdle();
1915 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1916 base::RunLoop().RunUntilIdle();
1917 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
1919 helper
.FinishDefaultTest();
1920 helper
.VerifyDataConsumed();
1922 std::string expected_response
;
1923 expected_response
+= kUploadData
;
1924 expected_response
+= kUploadData
;
1925 expected_response
+= kUploadData
;
1927 TransactionHelperResult out
= helper
.output();
1928 EXPECT_EQ(OK
, out
.rv
);
1929 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1930 EXPECT_EQ(expected_response
, out
.response_data
);
1933 // Test that a POST without any post data works.
1934 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1935 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1936 // Setup the request
1937 HttpRequestInfo request
;
1938 request
.method
= "POST";
1939 request
.url
= GURL(kRequestUrl
);
1940 // Create an empty UploadData.
1941 request
.upload_data_stream
= NULL
;
1943 // When request.upload_data_stream is NULL for post, content-length is
1944 // expected to be 0.
1945 scoped_ptr
<SpdyHeaderBlock
> req_block(
1946 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, 0));
1947 scoped_ptr
<SpdyFrame
> req(
1948 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1950 MockWrite writes
[] = {
1951 CreateMockWrite(*req
),
1954 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1955 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1956 MockRead reads
[] = {
1957 CreateMockRead(*resp
),
1958 CreateMockRead(*body
),
1959 MockRead(ASYNC
, 0, 0) // EOF
1962 DelayedSocketData
data(1, reads
, arraysize(reads
),
1963 writes
, arraysize(writes
));
1965 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1966 BoundNetLog(), GetParam(), NULL
);
1967 helper
.RunToCompletion(&data
);
1968 TransactionHelperResult out
= helper
.output();
1969 EXPECT_EQ(OK
, out
.rv
);
1970 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1971 EXPECT_EQ("hello!", out
.response_data
);
1974 // Test that a simple POST works.
1975 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1976 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1977 // Create an empty UploadDataStream.
1978 ScopedVector
<UploadElementReader
> element_readers
;
1979 ElementsUploadDataStream
stream(element_readers
.Pass(), 0);
1981 // Setup the request
1982 HttpRequestInfo request
;
1983 request
.method
= "POST";
1984 request
.url
= GURL(kRequestUrl
);
1985 request
.upload_data_stream
= &stream
;
1987 const uint64 kContentLength
= 0;
1989 scoped_ptr
<SpdyHeaderBlock
> req_block(
1990 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, kContentLength
));
1991 scoped_ptr
<SpdyFrame
> req(
1992 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1994 MockWrite writes
[] = {
1995 CreateMockWrite(*req
),
1998 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1999 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2000 MockRead reads
[] = {
2001 CreateMockRead(*resp
),
2002 CreateMockRead(*body
),
2003 MockRead(ASYNC
, 0, 0) // EOF
2006 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
2008 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
2009 BoundNetLog(), GetParam(), NULL
);
2010 helper
.RunToCompletion(&data
);
2011 TransactionHelperResult out
= helper
.output();
2012 EXPECT_EQ(OK
, out
.rv
);
2013 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2014 EXPECT_EQ("hello!", out
.response_data
);
2017 // While we're doing a post, the server sends the reply before upload completes.
2018 TEST_P(SpdyNetworkTransactionTest
, ResponseBeforePostCompletes
) {
2019 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
2020 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2021 MockWrite writes
[] = {
2022 CreateMockWrite(*req
, 0),
2023 CreateMockWrite(*body
, 3),
2025 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2026 MockRead reads
[] = {
2027 CreateMockRead(*resp
, 1),
2028 CreateMockRead(*body
, 2),
2029 MockRead(ASYNC
, 0, 4) // EOF
2032 // Write the request headers, and read the complete response
2033 // while still waiting for chunked request data.
2034 DeterministicSocketData
data(reads
, arraysize(reads
),
2035 writes
, arraysize(writes
));
2036 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
2038 BoundNetLog(), GetParam(), NULL
);
2039 helper
.SetDeterministic();
2040 helper
.RunPreTestSetup();
2041 helper
.AddDeterministicData(&data
);
2043 ASSERT_TRUE(helper
.StartDefaultTest());
2045 // Process the request headers, SYN_REPLY, and response body.
2046 // The request body is still in flight.
2049 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
2050 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2052 // Finish sending the request body.
2053 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
2056 std::string response_body
;
2057 EXPECT_EQ(OK
, ReadTransaction(helper
.trans(), &response_body
));
2058 EXPECT_EQ(kUploadData
, response_body
);
2059 helper
.VerifyDataConsumed();
2062 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2063 // socket causes the TCP write to return zero. This test checks that the client
2064 // tries to queue up the RST_STREAM frame again.
2065 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2066 scoped_ptr
<SpdyFrame
> req(
2067 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2068 scoped_ptr
<SpdyFrame
> rst(
2069 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2070 MockWrite writes
[] = {
2071 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2072 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2073 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2076 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2077 MockRead reads
[] = {
2078 CreateMockRead(*resp
.get(), 1, ASYNC
),
2079 MockRead(ASYNC
, 0, 0, 4) // EOF
2082 DeterministicSocketData
data(reads
, arraysize(reads
),
2083 writes
, arraysize(writes
));
2084 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2085 BoundNetLog(), GetParam(), NULL
);
2086 helper
.SetDeterministic();
2087 helper
.RunPreTestSetup();
2088 helper
.AddDeterministicData(&data
);
2089 HttpNetworkTransaction
* trans
= helper
.trans();
2091 TestCompletionCallback callback
;
2092 int rv
= trans
->Start(
2093 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2094 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2098 helper
.ResetTrans();
2102 helper
.VerifyDataConsumed();
2105 // Test that the transaction doesn't crash when we don't have a reply.
2106 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2107 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2108 MockRead reads
[] = {
2109 CreateMockRead(*body
),
2110 MockRead(ASYNC
, 0, 0) // EOF
2113 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2114 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2115 BoundNetLog(), GetParam(), NULL
);
2116 helper
.RunToCompletion(&data
);
2117 TransactionHelperResult out
= helper
.output();
2118 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2121 // Test that the transaction doesn't crash when we get two replies on the same
2122 // stream ID. See http://crbug.com/45639.
2123 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2124 scoped_ptr
<SpdyFrame
> req(
2125 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2126 scoped_ptr
<SpdyFrame
> rst(
2127 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2128 MockWrite writes
[] = {
2129 CreateMockWrite(*req
),
2130 CreateMockWrite(*rst
),
2133 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2134 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2135 MockRead reads
[] = {
2136 CreateMockRead(*resp
),
2137 CreateMockRead(*resp
),
2138 CreateMockRead(*body
),
2139 MockRead(ASYNC
, 0, 0) // EOF
2142 DelayedSocketData
data(1, reads
, arraysize(reads
),
2143 writes
, arraysize(writes
));
2145 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2146 BoundNetLog(), GetParam(), NULL
);
2147 helper
.RunPreTestSetup();
2148 helper
.AddData(&data
);
2150 HttpNetworkTransaction
* trans
= helper
.trans();
2152 TestCompletionCallback callback
;
2153 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2154 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2155 rv
= callback
.WaitForResult();
2158 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2159 ASSERT_TRUE(response
!= NULL
);
2160 EXPECT_TRUE(response
->headers
.get() != NULL
);
2161 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2162 std::string response_data
;
2163 rv
= ReadTransaction(trans
, &response_data
);
2164 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2166 helper
.VerifyDataConsumed();
2169 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2170 // Construct the request.
2171 scoped_ptr
<SpdyFrame
> req(
2172 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2173 scoped_ptr
<SpdyFrame
> rst(
2174 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2175 MockWrite writes
[] = {
2176 CreateMockWrite(*req
),
2177 CreateMockWrite(*rst
),
2180 const char* const headers
[] = {
2181 "transfer-encoding", "chunked"
2183 scoped_ptr
<SpdyFrame
> resp(
2184 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2185 scoped_ptr
<SpdyFrame
> body(
2186 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2187 MockRead reads
[] = {
2188 CreateMockRead(*resp
),
2189 CreateMockRead(*body
),
2190 MockRead(ASYNC
, 0, 0) // EOF
2193 DelayedSocketData
data(1, reads
, arraysize(reads
),
2194 writes
, arraysize(writes
));
2195 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2196 BoundNetLog(), GetParam(), NULL
);
2197 helper
.RunToCompletion(&data
);
2198 TransactionHelperResult out
= helper
.output();
2199 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2201 helper
.session()->spdy_session_pool()->CloseAllSessions();
2202 helper
.VerifyDataConsumed();
2205 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2206 // Construct the request.
2207 scoped_ptr
<SpdyFrame
> req(
2208 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2209 scoped_ptr
<SpdyFrame
> rst(
2210 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2211 MockWrite writes
[] = {
2212 CreateMockWrite(*req
),
2213 CreateMockWrite(*rst
),
2216 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2217 const char* const headers
[] = {
2218 "transfer-encoding", "chunked"
2220 scoped_ptr
<SpdyFrame
> push(
2221 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2222 2, 1, "http://www.google.com/1"));
2223 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2224 MockRead reads
[] = {
2225 CreateMockRead(*resp
),
2226 CreateMockRead(*push
),
2227 CreateMockRead(*body
),
2228 MockRead(ASYNC
, 0, 0) // EOF
2231 DelayedSocketData
data(1, reads
, arraysize(reads
),
2232 writes
, arraysize(writes
));
2233 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2234 BoundNetLog(), GetParam(), NULL
);
2235 helper
.RunToCompletion(&data
);
2236 TransactionHelperResult out
= helper
.output();
2237 EXPECT_EQ(OK
, out
.rv
);
2238 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2239 EXPECT_EQ("hello!", out
.response_data
);
2241 helper
.session()->spdy_session_pool()->CloseAllSessions();
2242 helper
.VerifyDataConsumed();
2245 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2246 // Construct the request.
2247 scoped_ptr
<SpdyFrame
> req(
2248 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2249 MockWrite writes
[] = {
2250 CreateMockWrite(*req
),
2253 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2254 MockRead reads
[] = {
2255 CreateMockRead(*resp
),
2256 // This following read isn't used by the test, except during the
2257 // RunUntilIdle() call at the end since the SpdySession survives the
2258 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2259 // MockRead will do here.
2260 MockRead(ASYNC
, 0, 0) // EOF
2263 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2264 writes
, arraysize(writes
));
2266 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2267 BoundNetLog(), GetParam(), NULL
);
2268 helper
.RunPreTestSetup();
2269 helper
.AddData(&data
);
2270 HttpNetworkTransaction
* trans
= helper
.trans();
2272 TestCompletionCallback callback
;
2273 int rv
= trans
->Start(
2274 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2275 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2276 helper
.ResetTrans(); // Cancel the transaction.
2278 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2279 // MockClientSocketFactory) are still alive.
2280 base::RunLoop().RunUntilIdle();
2281 helper
.VerifyDataNotConsumed();
2284 // Verify that the client sends a Rst Frame upon cancelling the stream.
2285 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2286 scoped_ptr
<SpdyFrame
> req(
2287 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2288 scoped_ptr
<SpdyFrame
> rst(
2289 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2290 MockWrite writes
[] = {
2291 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2292 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2295 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2296 MockRead reads
[] = {
2297 CreateMockRead(*resp
, 1, ASYNC
),
2298 MockRead(ASYNC
, 0, 0, 3) // EOF
2301 DeterministicSocketData
data(reads
, arraysize(reads
),
2302 writes
, arraysize(writes
));
2304 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2307 helper
.SetDeterministic();
2308 helper
.RunPreTestSetup();
2309 helper
.AddDeterministicData(&data
);
2310 HttpNetworkTransaction
* trans
= helper
.trans();
2312 TestCompletionCallback callback
;
2314 int rv
= trans
->Start(
2315 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2316 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2320 helper
.ResetTrans();
2324 helper
.VerifyDataConsumed();
2327 // Verify that the client can correctly deal with the user callback attempting
2328 // to start another transaction on a session that is closing down. See
2329 // http://crbug.com/47455
2330 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2331 scoped_ptr
<SpdyFrame
> req(
2332 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2333 MockWrite writes
[] = { CreateMockWrite(*req
) };
2334 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2336 // The indicated length of this frame is longer than its actual length. When
2337 // the session receives an empty frame after this one, it shuts down the
2338 // session, and calls the read callback with the incomplete data.
2339 const uint8 kGetBodyFrame2
[] = {
2340 0x00, 0x00, 0x00, 0x01,
2341 0x01, 0x00, 0x00, 0x07,
2342 'h', 'e', 'l', 'l', 'o', '!',
2345 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2346 MockRead reads
[] = {
2347 CreateMockRead(*resp
, 2),
2348 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2349 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2350 arraysize(kGetBodyFrame2
), 4),
2351 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2352 MockRead(ASYNC
, 0, 0, 6), // EOF
2354 MockRead reads2
[] = {
2355 CreateMockRead(*resp
, 2),
2356 MockRead(ASYNC
, 0, 0, 3), // EOF
2359 OrderedSocketData
data(reads
, arraysize(reads
),
2360 writes
, arraysize(writes
));
2361 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2362 writes2
, arraysize(writes2
));
2364 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2365 BoundNetLog(), GetParam(), NULL
);
2366 helper
.RunPreTestSetup();
2367 helper
.AddData(&data
);
2368 helper
.AddData(&data2
);
2369 HttpNetworkTransaction
* trans
= helper
.trans();
2371 // Start the transaction with basic parameters.
2372 TestCompletionCallback callback
;
2373 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2374 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2375 rv
= callback
.WaitForResult();
2377 const int kSize
= 3000;
2378 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2382 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2384 // This forces an err_IO_pending, which sets the callback.
2385 data
.CompleteRead();
2386 // This finishes the read.
2387 data
.CompleteRead();
2388 helper
.VerifyDataConsumed();
2391 // Verify that the client can correctly deal with the user callback deleting the
2392 // transaction. Failures will usually be valgrind errors. See
2393 // http://crbug.com/46925
2394 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2395 scoped_ptr
<SpdyFrame
> req(
2396 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2397 MockWrite writes
[] = { CreateMockWrite(*req
) };
2399 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2400 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2401 MockRead reads
[] = {
2402 CreateMockRead(*resp
.get(), 2),
2403 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2404 CreateMockRead(*body
.get(), 4),
2405 MockRead(ASYNC
, 0, 0, 5), // EOF
2408 OrderedSocketData
data(reads
, arraysize(reads
),
2409 writes
, arraysize(writes
));
2411 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2412 BoundNetLog(), GetParam(), NULL
);
2413 helper
.RunPreTestSetup();
2414 helper
.AddData(&data
);
2415 HttpNetworkTransaction
* trans
= helper
.trans();
2417 // Start the transaction with basic parameters.
2418 TestCompletionCallback callback
;
2419 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2420 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2421 rv
= callback
.WaitForResult();
2423 // Setup a user callback which will delete the session, and clear out the
2424 // memory holding the stream object. Note that the callback deletes trans.
2425 const int kSize
= 3000;
2426 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2430 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2431 base::Unretained(&helper
)));
2432 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2433 data
.CompleteRead();
2435 // Finish running rest of tasks.
2436 base::RunLoop().RunUntilIdle();
2437 helper
.VerifyDataConsumed();
2440 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2441 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2442 scoped_ptr
<SpdyHeaderBlock
> headers(
2443 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2444 (*headers
)["user-agent"] = "";
2445 (*headers
)["accept-encoding"] = "gzip, deflate";
2446 scoped_ptr
<SpdyHeaderBlock
> headers2(
2447 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2448 (*headers2
)["user-agent"] = "";
2449 (*headers2
)["accept-encoding"] = "gzip, deflate";
2451 // Setup writes/reads to www.google.com
2452 scoped_ptr
<SpdyFrame
> req(
2453 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2454 scoped_ptr
<SpdyFrame
> req2(
2455 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2456 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2457 MockWrite writes
[] = {
2458 CreateMockWrite(*req
, 1),
2460 MockRead reads
[] = {
2461 CreateMockRead(*resp
, 2),
2462 MockRead(ASYNC
, 0, 0, 3) // EOF
2465 // Setup writes/reads to www.foo.com
2466 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2467 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2468 MockWrite writes2
[] = {
2469 CreateMockWrite(*req2
, 1),
2471 MockRead reads2
[] = {
2472 CreateMockRead(*resp2
, 2),
2473 CreateMockRead(*body2
, 3),
2474 MockRead(ASYNC
, 0, 0, 4) // EOF
2476 OrderedSocketData
data(reads
, arraysize(reads
),
2477 writes
, arraysize(writes
));
2478 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2479 writes2
, arraysize(writes2
));
2481 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2484 SpdyURLRequestContext
spdy_url_request_context(
2485 GetParam().protocol
,
2486 false /* force_spdy_over_ssl*/,
2487 true /* force_spdy_always */);
2488 scoped_ptr
<URLRequest
> r(
2489 spdy_url_request_context
.CreateRequest(GURL("http://www.google.com/"),
2493 spdy_url_request_context
.socket_factory().
2494 AddSocketDataProvider(&data
);
2495 spdy_url_request_context
.socket_factory().
2496 AddSocketDataProvider(&data2
);
2498 d
.set_quit_on_redirect(true);
2500 base::RunLoop().Run();
2502 EXPECT_EQ(1, d
.received_redirect_count());
2504 r
->FollowDeferredRedirect();
2505 base::RunLoop().Run();
2506 EXPECT_EQ(1, d
.response_started_count());
2507 EXPECT_FALSE(d
.received_data_before_response());
2508 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
->status().status());
2509 std::string
contents("hello!");
2510 EXPECT_EQ(contents
, d
.data_received());
2512 EXPECT_TRUE(data
.at_read_eof());
2513 EXPECT_TRUE(data
.at_write_eof());
2514 EXPECT_TRUE(data2
.at_read_eof());
2515 EXPECT_TRUE(data2
.at_write_eof());
2518 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2520 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2521 scoped_ptr
<SpdyHeaderBlock
> headers(
2522 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2523 (*headers
)["user-agent"] = "";
2524 (*headers
)["accept-encoding"] = "gzip, deflate";
2526 // Setup writes/reads to www.google.com
2527 scoped_ptr
<SpdyFrame
> req(
2528 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2529 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2530 scoped_ptr
<SpdyFrame
> rep(
2531 spdy_util_
.ConstructSpdyPush(NULL
,
2535 "http://www.google.com/foo.dat",
2536 "301 Moved Permanently",
2537 "http://www.foo.com/index.php"));
2538 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2539 scoped_ptr
<SpdyFrame
> rst(
2540 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
2541 MockWrite writes
[] = {
2542 CreateMockWrite(*req
, 1),
2543 CreateMockWrite(*rst
, 6),
2545 MockRead reads
[] = {
2546 CreateMockRead(*resp
, 2),
2547 CreateMockRead(*rep
, 3),
2548 CreateMockRead(*body
, 4),
2549 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2550 MockRead(ASYNC
, 0, 0, 7) // EOF
2553 // Setup writes/reads to www.foo.com
2554 scoped_ptr
<SpdyHeaderBlock
> headers2(
2555 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2556 (*headers2
)["user-agent"] = "";
2557 (*headers2
)["accept-encoding"] = "gzip, deflate";
2558 scoped_ptr
<SpdyFrame
> req2(
2559 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2560 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2561 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2562 MockWrite writes2
[] = {
2563 CreateMockWrite(*req2
, 1),
2565 MockRead reads2
[] = {
2566 CreateMockRead(*resp2
, 2),
2567 CreateMockRead(*body2
, 3),
2568 MockRead(ASYNC
, 0, 0, 5) // EOF
2570 OrderedSocketData
data(reads
, arraysize(reads
),
2571 writes
, arraysize(writes
));
2572 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2573 writes2
, arraysize(writes2
));
2575 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2578 SpdyURLRequestContext
spdy_url_request_context(
2579 GetParam().protocol
,
2580 false /* force_spdy_over_ssl*/,
2581 true /* force_spdy_always */);
2583 scoped_ptr
<URLRequest
> r(
2584 spdy_url_request_context
.CreateRequest(GURL("http://www.google.com/"),
2588 spdy_url_request_context
.socket_factory().
2589 AddSocketDataProvider(&data
);
2592 base::RunLoop().Run();
2594 EXPECT_EQ(0, d
.received_redirect_count());
2595 std::string
contents("hello!");
2596 EXPECT_EQ(contents
, d
.data_received());
2598 scoped_ptr
<URLRequest
> r2(
2599 spdy_url_request_context
.CreateRequest(
2600 GURL("http://www.google.com/foo.dat"),
2604 spdy_url_request_context
.socket_factory().
2605 AddSocketDataProvider(&data2
);
2607 d2
.set_quit_on_redirect(true);
2609 base::RunLoop().Run();
2610 EXPECT_EQ(1, d2
.received_redirect_count());
2612 r2
->FollowDeferredRedirect();
2613 base::RunLoop().Run();
2614 EXPECT_EQ(1, d2
.response_started_count());
2615 EXPECT_FALSE(d2
.received_data_before_response());
2616 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
->status().status());
2617 std::string
contents2("hello!");
2618 EXPECT_EQ(contents2
, d2
.data_received());
2620 data
.CompleteRead();
2621 data2
.CompleteRead();
2622 EXPECT_TRUE(data
.at_read_eof());
2623 EXPECT_TRUE(data
.at_write_eof());
2624 EXPECT_TRUE(data2
.at_read_eof());
2625 EXPECT_TRUE(data2
.at_write_eof());
2628 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2629 scoped_ptr
<SpdyFrame
> stream1_syn(
2630 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2631 scoped_ptr
<SpdyFrame
> stream1_body(
2632 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2633 MockWrite writes
[] = {
2634 CreateMockWrite(*stream1_syn
, 1),
2637 scoped_ptr
<SpdyFrame
>
2638 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2639 scoped_ptr
<SpdyFrame
>
2640 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2644 "http://www.google.com/foo.dat"));
2645 const char kPushedData
[] = "pushed";
2646 scoped_ptr
<SpdyFrame
> stream2_body(
2647 spdy_util_
.ConstructSpdyBodyFrame(
2648 2, kPushedData
, strlen(kPushedData
), true));
2649 MockRead reads
[] = {
2650 CreateMockRead(*stream1_reply
, 2),
2651 CreateMockRead(*stream2_syn
, 3),
2652 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2653 CreateMockRead(*stream2_body
, 5),
2654 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2657 HttpResponseInfo response
;
2658 HttpResponseInfo response2
;
2659 std::string
expected_push_result("pushed");
2660 OrderedSocketData
data(reads
, arraysize(reads
),
2661 writes
, arraysize(writes
));
2662 RunServerPushTest(&data
,
2665 expected_push_result
);
2667 // Verify the SYN_REPLY.
2668 EXPECT_TRUE(response
.headers
.get() != NULL
);
2669 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2671 // Verify the pushed stream.
2672 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2673 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2676 TEST_P(SpdyNetworkTransactionTest
, ServerPushBeforeSynReply
) {
2677 scoped_ptr
<SpdyFrame
> stream1_syn(
2678 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2679 scoped_ptr
<SpdyFrame
> stream1_body(
2680 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2681 MockWrite writes
[] = {
2682 CreateMockWrite(*stream1_syn
, 1),
2685 scoped_ptr
<SpdyFrame
>
2686 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2687 scoped_ptr
<SpdyFrame
>
2688 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2692 "http://www.google.com/foo.dat"));
2693 const char kPushedData
[] = "pushed";
2694 scoped_ptr
<SpdyFrame
> stream2_body(
2695 spdy_util_
.ConstructSpdyBodyFrame(
2696 2, kPushedData
, strlen(kPushedData
), true));
2697 MockRead reads
[] = {
2698 CreateMockRead(*stream2_syn
, 2),
2699 CreateMockRead(*stream1_reply
, 3),
2700 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2701 CreateMockRead(*stream2_body
, 5),
2702 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2705 HttpResponseInfo response
;
2706 HttpResponseInfo response2
;
2707 std::string
expected_push_result("pushed");
2708 OrderedSocketData
data(reads
, arraysize(reads
),
2709 writes
, arraysize(writes
));
2710 RunServerPushTest(&data
,
2713 expected_push_result
);
2715 // Verify the SYN_REPLY.
2716 EXPECT_TRUE(response
.headers
.get() != NULL
);
2717 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2719 // Verify the pushed stream.
2720 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2721 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2724 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2725 scoped_ptr
<SpdyFrame
> stream1_syn(
2726 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2727 MockWrite writes
[] = { CreateMockWrite(*stream1_syn
, 1), };
2729 scoped_ptr
<SpdyFrame
>
2730 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2731 scoped_ptr
<SpdyFrame
>
2732 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2736 "http://www.google.com/foo.dat"));
2737 const char kPushedData
[] = "pushed";
2738 scoped_ptr
<SpdyFrame
> stream2_body(
2739 spdy_util_
.ConstructSpdyBodyFrame(
2740 2, kPushedData
, strlen(kPushedData
), true));
2741 scoped_ptr
<SpdyFrame
>
2742 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2743 MockRead reads
[] = {
2744 CreateMockRead(*stream1_reply
, 2),
2745 CreateMockRead(*stream2_syn
, 3),
2746 CreateMockRead(*stream2_body
, 4),
2747 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2748 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2751 HttpResponseInfo response
;
2752 HttpResponseInfo response2
;
2753 std::string
expected_push_result("pushed");
2754 OrderedSocketData
data(reads
, arraysize(reads
),
2755 writes
, arraysize(writes
));
2756 RunServerPushTest(&data
,
2759 expected_push_result
);
2761 // Verify the SYN_REPLY.
2762 EXPECT_TRUE(response
.headers
.get() != NULL
);
2763 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2765 // Verify the pushed stream.
2766 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2767 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2770 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2771 scoped_ptr
<SpdyFrame
> stream1_syn(
2772 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2773 scoped_ptr
<SpdyFrame
> stream1_body(
2774 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2775 MockWrite writes
[] = {
2776 CreateMockWrite(*stream1_syn
, 1),
2779 scoped_ptr
<SpdyFrame
>
2780 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2781 scoped_ptr
<SpdyFrame
>
2782 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2786 "http://www.google.com/foo.dat"));
2787 scoped_ptr
<SpdyFrame
> stream2_rst(
2788 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2789 MockRead reads
[] = {
2790 CreateMockRead(*stream1_reply
, 2),
2791 CreateMockRead(*stream2_syn
, 3),
2792 CreateMockRead(*stream2_rst
, 4),
2793 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2794 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2797 OrderedSocketData
data(reads
, arraysize(reads
),
2798 writes
, arraysize(writes
));
2799 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2800 BoundNetLog(), GetParam(), NULL
);
2802 helper
.RunPreTestSetup();
2803 helper
.AddData(&data
);
2805 HttpNetworkTransaction
* trans
= helper
.trans();
2807 // Start the transaction with basic parameters.
2808 TestCompletionCallback callback
;
2809 int rv
= trans
->Start(
2810 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2811 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2812 rv
= callback
.WaitForResult();
2815 // Verify that we consumed all test data.
2816 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2817 << data
.read_count()
2819 << data
.read_index();
2820 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2821 << data
.write_count()
2823 << data
.write_index();
2825 // Verify the SYN_REPLY.
2826 HttpResponseInfo response
= *trans
->GetResponseInfo();
2827 EXPECT_TRUE(response
.headers
.get() != NULL
);
2828 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2831 // Verify that we don't leak streams and that we properly send a reset
2832 // if the server pushes the same stream twice.
2833 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2834 scoped_ptr
<SpdyFrame
> stream1_syn(
2835 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2836 scoped_ptr
<SpdyFrame
> stream1_body(
2837 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2838 scoped_ptr
<SpdyFrame
> stream3_rst(
2839 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR
));
2840 MockWrite writes
[] = {
2841 CreateMockWrite(*stream1_syn
, 1),
2842 CreateMockWrite(*stream3_rst
, 5),
2845 scoped_ptr
<SpdyFrame
>
2846 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2847 scoped_ptr
<SpdyFrame
>
2848 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2852 "http://www.google.com/foo.dat"));
2853 const char kPushedData
[] = "pushed";
2854 scoped_ptr
<SpdyFrame
> stream2_body(
2855 spdy_util_
.ConstructSpdyBodyFrame(
2856 2, kPushedData
, strlen(kPushedData
), true));
2857 scoped_ptr
<SpdyFrame
>
2858 stream3_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2862 "http://www.google.com/foo.dat"));
2863 MockRead reads
[] = {
2864 CreateMockRead(*stream1_reply
, 2),
2865 CreateMockRead(*stream2_syn
, 3),
2866 CreateMockRead(*stream3_syn
, 4),
2867 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
2868 CreateMockRead(*stream2_body
, 7),
2869 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
2872 HttpResponseInfo response
;
2873 HttpResponseInfo response2
;
2874 std::string
expected_push_result("pushed");
2875 OrderedSocketData
data(reads
, arraysize(reads
),
2876 writes
, arraysize(writes
));
2877 RunServerPushTest(&data
,
2880 expected_push_result
);
2882 // Verify the SYN_REPLY.
2883 EXPECT_TRUE(response
.headers
.get() != NULL
);
2884 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2886 // Verify the pushed stream.
2887 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2888 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2891 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2892 scoped_ptr
<SpdyFrame
> stream1_syn(
2893 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2894 scoped_ptr
<SpdyFrame
> stream1_body(
2895 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2896 MockWrite writes
[] = {
2897 CreateMockWrite(*stream1_syn
, 1),
2900 scoped_ptr
<SpdyFrame
>
2901 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2902 scoped_ptr
<SpdyFrame
>
2903 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2907 "http://www.google.com/foo.dat"));
2908 static const char kPushedData
[] = "pushed my darling hello my baby";
2909 scoped_ptr
<SpdyFrame
> stream2_body_base(
2910 spdy_util_
.ConstructSpdyBodyFrame(
2911 2, kPushedData
, strlen(kPushedData
), true));
2912 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2913 scoped_ptr
<SpdyFrame
> stream2_body1(
2914 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2915 scoped_ptr
<SpdyFrame
> stream2_body2(
2916 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2917 scoped_ptr
<SpdyFrame
> stream2_body3(
2918 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2919 kChunkSize
, false));
2920 scoped_ptr
<SpdyFrame
> stream2_body4(
2921 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2922 stream2_body_base
->size() - 3 * kChunkSize
, false));
2923 MockRead reads
[] = {
2924 CreateMockRead(*stream1_reply
, 2),
2925 CreateMockRead(*stream2_syn
, 3),
2926 CreateMockRead(*stream2_body1
, 4),
2927 CreateMockRead(*stream2_body2
, 5),
2928 CreateMockRead(*stream2_body3
, 6),
2929 CreateMockRead(*stream2_body4
, 7),
2930 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
2931 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
2934 HttpResponseInfo response
;
2935 HttpResponseInfo response2
;
2936 std::string
expected_push_result("pushed my darling hello my baby");
2937 OrderedSocketData
data(reads
, arraysize(reads
),
2938 writes
, arraysize(writes
));
2939 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2941 // Verify the SYN_REPLY.
2942 EXPECT_TRUE(response
.headers
.get() != NULL
);
2943 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2945 // Verify the pushed stream.
2946 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2947 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2950 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2951 scoped_ptr
<SpdyFrame
> stream1_syn(
2952 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2953 scoped_ptr
<SpdyFrame
> stream1_body(
2954 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2955 MockWrite writes
[] = {
2956 CreateMockWrite(*stream1_syn
, 1),
2959 scoped_ptr
<SpdyFrame
>
2960 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2961 scoped_ptr
<SpdyFrame
>
2962 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2966 "http://www.google.com/foo.dat"));
2967 static const char kPushedData
[] = "pushed my darling hello my baby";
2968 scoped_ptr
<SpdyFrame
> stream2_body_base(
2969 spdy_util_
.ConstructSpdyBodyFrame(
2970 2, kPushedData
, strlen(kPushedData
), true));
2971 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2972 scoped_ptr
<SpdyFrame
> stream2_body1(
2973 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2974 scoped_ptr
<SpdyFrame
> stream2_body2(
2975 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2976 scoped_ptr
<SpdyFrame
> stream2_body3(
2977 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2978 kChunkSize
, false));
2979 scoped_ptr
<SpdyFrame
> stream2_body4(
2980 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2981 stream2_body_base
->size() - 3 * kChunkSize
, false));
2982 MockRead reads
[] = {
2983 CreateMockRead(*stream1_reply
, 2),
2984 CreateMockRead(*stream2_syn
, 3),
2985 CreateMockRead(*stream2_body1
, 4),
2986 CreateMockRead(*stream2_body2
, 5),
2987 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2988 CreateMockRead(*stream2_body3
, 7),
2989 CreateMockRead(*stream2_body4
, 8),
2990 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
2991 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
2994 HttpResponseInfo response
;
2995 HttpResponseInfo response2
;
2996 OrderedSocketData
data(reads
, arraysize(reads
),
2997 writes
, arraysize(writes
));
2998 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
3000 // Verify the SYN_REPLY.
3001 EXPECT_TRUE(response
.headers
.get() != NULL
);
3002 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3004 // Verify the pushed stream.
3005 EXPECT_TRUE(response2
.headers
.get() != NULL
);
3006 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3009 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
3010 if (spdy_util_
.spdy_version() == SPDY4
) {
3011 // PUSH_PROMISE with stream id 0 is connection-level error.
3012 // TODO(baranovich): Test session going away.
3016 scoped_ptr
<SpdyFrame
> stream1_syn(
3017 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3018 scoped_ptr
<SpdyFrame
> stream1_body(
3019 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3020 scoped_ptr
<SpdyFrame
> stream2_rst(
3021 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
3022 MockWrite writes
[] = {
3023 CreateMockWrite(*stream1_syn
, 1),
3024 CreateMockWrite(*stream2_rst
, 4),
3027 scoped_ptr
<SpdyFrame
>
3028 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3029 scoped_ptr
<SpdyFrame
>
3030 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3034 "http://www.google.com/foo.dat"));
3035 MockRead reads
[] = {
3036 CreateMockRead(*stream1_reply
, 2),
3037 CreateMockRead(*stream2_syn
, 3),
3038 CreateMockRead(*stream1_body
, 4),
3039 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3042 OrderedSocketData
data(reads
, arraysize(reads
),
3043 writes
, arraysize(writes
));
3044 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3045 BoundNetLog(), GetParam(), NULL
);
3047 helper
.RunPreTestSetup();
3048 helper
.AddData(&data
);
3050 HttpNetworkTransaction
* trans
= helper
.trans();
3052 // Start the transaction with basic parameters.
3053 TestCompletionCallback callback
;
3054 int rv
= trans
->Start(
3055 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3056 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3057 rv
= callback
.WaitForResult();
3060 // Verify that we consumed all test data.
3061 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3062 << data
.read_count()
3064 << data
.read_index();
3065 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3066 << data
.write_count()
3068 << data
.write_index();
3070 // Verify the SYN_REPLY.
3071 HttpResponseInfo response
= *trans
->GetResponseInfo();
3072 EXPECT_TRUE(response
.headers
.get() != NULL
);
3073 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3076 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3077 scoped_ptr
<SpdyFrame
> stream1_syn(
3078 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3079 scoped_ptr
<SpdyFrame
> stream1_body(
3080 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3081 scoped_ptr
<SpdyFrame
> stream2_rst(
3082 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM
));
3083 MockWrite writes
[] = {
3084 CreateMockWrite(*stream1_syn
, 1),
3085 CreateMockWrite(*stream2_rst
, 4),
3088 scoped_ptr
<SpdyFrame
>
3089 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3090 scoped_ptr
<SpdyFrame
>
3091 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3095 "http://www.google.com/foo.dat"));
3096 MockRead reads
[] = {
3097 CreateMockRead(*stream1_reply
, 2),
3098 CreateMockRead(*stream2_syn
, 3),
3099 CreateMockRead(*stream1_body
, 4),
3100 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3103 OrderedSocketData
data(reads
, arraysize(reads
),
3104 writes
, arraysize(writes
));
3105 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3106 BoundNetLog(), GetParam(), NULL
);
3108 helper
.RunPreTestSetup();
3109 helper
.AddData(&data
);
3111 HttpNetworkTransaction
* trans
= helper
.trans();
3113 // Start the transaction with basic parameters.
3114 TestCompletionCallback callback
;
3115 int rv
= trans
->Start(
3116 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3117 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3118 rv
= callback
.WaitForResult();
3121 // Verify that we consumed all test data.
3122 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3123 << data
.read_count()
3125 << data
.read_index();
3126 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3127 << data
.write_count()
3129 << data
.write_index();
3131 // Verify the SYN_REPLY.
3132 HttpResponseInfo response
= *trans
->GetResponseInfo();
3133 EXPECT_TRUE(response
.headers
.get() != NULL
);
3134 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3137 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3138 scoped_ptr
<SpdyFrame
> stream1_syn(
3139 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3140 scoped_ptr
<SpdyFrame
> stream1_body(
3141 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3142 scoped_ptr
<SpdyFrame
> stream2_rst(
3143 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
3144 MockWrite writes
[] = {
3145 CreateMockWrite(*stream1_syn
, 1),
3146 CreateMockWrite(*stream2_rst
, 4),
3149 scoped_ptr
<SpdyFrame
>
3150 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3151 scoped_ptr
<SpdyHeaderBlock
> incomplete_headers(new SpdyHeaderBlock());
3152 (*incomplete_headers
)["hello"] = "bye";
3153 (*incomplete_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
3154 (*incomplete_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
3155 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructInitialSpdyPushFrame(
3156 incomplete_headers
.Pass(), 2, 1));
3157 MockRead reads
[] = {
3158 CreateMockRead(*stream1_reply
, 2),
3159 CreateMockRead(*stream2_syn
, 3),
3160 CreateMockRead(*stream1_body
, 4),
3161 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3164 OrderedSocketData
data(reads
, arraysize(reads
),
3165 writes
, arraysize(writes
));
3166 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3167 BoundNetLog(), GetParam(), NULL
);
3169 helper
.RunPreTestSetup();
3170 helper
.AddData(&data
);
3172 HttpNetworkTransaction
* trans
= helper
.trans();
3174 // Start the transaction with basic parameters.
3175 TestCompletionCallback callback
;
3176 int rv
= trans
->Start(
3177 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3178 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3179 rv
= callback
.WaitForResult();
3181 // Verify that we consumed all test data.
3182 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3183 << data
.read_count()
3185 << data
.read_index();
3186 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3187 << data
.write_count()
3189 << data
.write_index();
3191 // Verify the SYN_REPLY.
3192 HttpResponseInfo response
= *trans
->GetResponseInfo();
3193 EXPECT_TRUE(response
.headers
.get() != NULL
);
3194 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3197 // Verify that various SynReply headers parse correctly through the
3199 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3200 struct SynReplyHeadersTests
{
3202 const char* extra_headers
[5];
3203 SpdyHeaderBlock expected_headers
;
3205 // This uses a multi-valued cookie header.
3208 "cookie", "val2", // will get appended separated by NULL
3212 // This is the minimalist set of headers.
3216 // Headers with a comma separated list.
3218 { "cookie", "val1,val2",
3224 test_cases
[0].expected_headers
["cookie"] = "val1";
3225 test_cases
[0].expected_headers
["cookie"] += '\0';
3226 test_cases
[0].expected_headers
["cookie"] += "val2";
3227 test_cases
[0].expected_headers
["hello"] = "bye";
3228 test_cases
[0].expected_headers
["status"] = "200";
3230 test_cases
[1].expected_headers
["hello"] = "bye";
3231 test_cases
[1].expected_headers
["status"] = "200";
3233 test_cases
[2].expected_headers
["cookie"] = "val1,val2";
3234 test_cases
[2].expected_headers
["hello"] = "bye";
3235 test_cases
[2].expected_headers
["status"] = "200";
3237 if (spdy_util_
.spdy_version() < SPDY4
) {
3238 // SPDY4/HTTP2 eliminates use of the :version header.
3239 test_cases
[0].expected_headers
["version"] = "HTTP/1.1";
3240 test_cases
[1].expected_headers
["version"] = "HTTP/1.1";
3241 test_cases
[2].expected_headers
["version"] = "HTTP/1.1";
3244 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3245 scoped_ptr
<SpdyFrame
> req(
3246 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3247 MockWrite writes
[] = { CreateMockWrite(*req
) };
3249 scoped_ptr
<SpdyFrame
> resp(
3250 spdy_util_
.ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3251 test_cases
[i
].num_headers
,
3253 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3254 MockRead reads
[] = {
3255 CreateMockRead(*resp
),
3256 CreateMockRead(*body
),
3257 MockRead(ASYNC
, 0, 0) // EOF
3260 DelayedSocketData
data(1, reads
, arraysize(reads
),
3261 writes
, arraysize(writes
));
3262 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3263 BoundNetLog(), GetParam(), NULL
);
3264 helper
.RunToCompletion(&data
);
3265 TransactionHelperResult out
= helper
.output();
3267 EXPECT_EQ(OK
, out
.rv
);
3268 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3269 EXPECT_EQ("hello!", out
.response_data
);
3271 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3272 EXPECT_TRUE(headers
.get() != NULL
);
3274 std::string name
, value
;
3275 SpdyHeaderBlock header_block
;
3276 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3277 if (header_block
[name
].empty()) {
3278 header_block
[name
] = value
;
3280 header_block
[name
] += '\0';
3281 header_block
[name
] += value
;
3284 EXPECT_EQ(test_cases
[i
].expected_headers
, header_block
);
3288 // Verify that various SynReply headers parse vary fields correctly
3289 // through the HTTP layer, and the response matches the request.
3290 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3291 // Modify the following data to change/add test cases:
3292 struct SynReplyTests
{
3295 const char* extra_headers
[2][16];
3297 // Test the case of a multi-valued cookie. When the value is delimited
3298 // with NUL characters, it needs to be unfolded into multiple headers.
3302 { { "cookie", "val1,val2",
3306 spdy_util_
.GetStatusKey(), "200",
3307 spdy_util_
.GetPathKey(), "/index.php",
3308 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3312 }, { // Multiple vary fields.
3315 { { "friend", "barney",
3316 "enemy", "snaggletooth",
3321 spdy_util_
.GetStatusKey(), "200",
3322 spdy_util_
.GetPathKey(), "/index.php",
3323 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3327 }, { // Test a '*' vary field.
3330 { { "cookie", "val1,val2",
3334 spdy_util_
.GetStatusKey(), "200",
3335 spdy_util_
.GetPathKey(), "/index.php",
3336 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3340 }, { // Multiple comma-separated vary fields.
3343 { { "friend", "barney",
3344 "enemy", "snaggletooth",
3347 { "vary", "friend,enemy",
3348 spdy_util_
.GetStatusKey(), "200",
3349 spdy_util_
.GetPathKey(), "/index.php",
3350 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3357 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3358 // Construct the request.
3359 scoped_ptr
<SpdyFrame
> frame_req(
3360 spdy_util_
.ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3361 test_cases
[i
].num_headers
[0],
3362 false, 1, LOWEST
, true));
3364 MockWrite writes
[] = {
3365 CreateMockWrite(*frame_req
),
3368 // Construct the reply.
3369 SpdyHeaderBlock reply_headers
;
3370 AppendToHeaderBlock(test_cases
[i
].extra_headers
[1],
3371 test_cases
[i
].num_headers
[1],
3373 scoped_ptr
<SpdyFrame
> frame_reply(
3374 spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3376 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3377 MockRead reads
[] = {
3378 CreateMockRead(*frame_reply
),
3379 CreateMockRead(*body
),
3380 MockRead(ASYNC
, 0, 0) // EOF
3383 // Attach the headers to the request.
3384 int header_count
= test_cases
[i
].num_headers
[0];
3386 HttpRequestInfo request
= CreateGetRequest();
3387 for (int ct
= 0; ct
< header_count
; ct
++) {
3388 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3389 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3390 request
.extra_headers
.SetHeader(header_key
, header_value
);
3393 DelayedSocketData
data(1, reads
, arraysize(reads
),
3394 writes
, arraysize(writes
));
3395 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
3396 BoundNetLog(), GetParam(), NULL
);
3397 helper
.RunToCompletion(&data
);
3398 TransactionHelperResult out
= helper
.output();
3400 EXPECT_EQ(OK
, out
.rv
) << i
;
3401 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3402 EXPECT_EQ("hello!", out
.response_data
) << i
;
3404 // Test the response information.
3405 EXPECT_TRUE(out
.response_info
.response_time
>
3406 out
.response_info
.request_time
) << i
;
3407 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3408 out
.response_info
.request_time
;
3409 base::TimeDelta min_expected_delay
;
3410 min_expected_delay
.FromMilliseconds(10);
3411 EXPECT_GT(test_delay
.InMillisecondsF(),
3412 min_expected_delay
.InMillisecondsF()) << i
;
3413 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3414 test_cases
[i
].vary_matches
) << i
;
3416 // Check the headers.
3417 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3418 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3420 std::string name
, value
, lines
;
3421 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3424 lines
.append(value
);
3428 // Construct the expected header reply string.
3429 std::string expected_reply
=
3430 spdy_util_
.ConstructSpdyReplyString(reply_headers
);
3431 EXPECT_EQ(expected_reply
, lines
) << i
;
3435 // Verify that we don't crash on invalid SynReply responses.
3436 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3437 struct InvalidSynReplyTests
{
3439 const char* headers
[10];
3441 // SYN_REPLY missing status header
3445 spdy_util_
.GetPathKey(), "/index.php",
3446 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3450 // SYN_REPLY missing version header
3453 spdy_util_
.GetPathKey(), "/index.php",
3457 // SYN_REPLY with no headers
3461 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3462 scoped_ptr
<SpdyFrame
> req(
3463 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3464 scoped_ptr
<SpdyFrame
> rst(
3465 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3466 MockWrite writes
[] = {
3467 CreateMockWrite(*req
),
3468 CreateMockWrite(*rst
),
3471 // Construct the reply.
3472 SpdyHeaderBlock reply_headers
;
3473 AppendToHeaderBlock(
3474 test_cases
[i
].headers
, test_cases
[i
].num_headers
, &reply_headers
);
3475 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3476 MockRead reads
[] = {
3477 CreateMockRead(*resp
),
3478 MockRead(ASYNC
, 0, 0) // EOF
3481 DelayedSocketData
data(1, reads
, arraysize(reads
),
3482 writes
, arraysize(writes
));
3483 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3484 BoundNetLog(), GetParam(), NULL
);
3485 helper
.RunToCompletion(&data
);
3486 TransactionHelperResult out
= helper
.output();
3487 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3491 // Verify that we don't crash on some corrupt frames.
3492 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3493 // connection error. I'd like to backport this behavior to SPDY3 as well.
3494 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3495 if (spdy_util_
.spdy_version() >= SPDY4
) {
3498 // This is the length field that's too short.
3499 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3500 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3501 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3503 (spdy_util_
.spdy_version() < SPDY4
) ?
3504 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize() :
3505 syn_reply_wrong_length
->size();
3506 size_t wrong_size
= right_size
- 4;
3507 test::SetFrameLength(syn_reply_wrong_length
.get(),
3509 spdy_util_
.spdy_version());
3511 struct SynReplyTests
{
3512 const SpdyFrame
* syn_reply
;
3514 { syn_reply_wrong_length
.get(), },
3517 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3518 scoped_ptr
<SpdyFrame
> req(
3519 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3520 scoped_ptr
<SpdyFrame
> rst(
3521 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3522 MockWrite writes
[] = {
3523 CreateMockWrite(*req
),
3524 CreateMockWrite(*rst
),
3527 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3528 MockRead reads
[] = {
3529 MockRead(ASYNC
, test_cases
[i
].syn_reply
->data(), wrong_size
),
3530 CreateMockRead(*body
),
3531 MockRead(ASYNC
, 0, 0) // EOF
3534 DelayedSocketData
data(1, reads
, arraysize(reads
),
3535 writes
, arraysize(writes
));
3536 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3537 BoundNetLog(), GetParam(), NULL
);
3538 helper
.RunToCompletion(&data
);
3539 TransactionHelperResult out
= helper
.output();
3540 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3544 // SPDY4 treats a header decompression failure as a connection-level error.
3545 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionErrorSpdy4
) {
3546 if (spdy_util_
.spdy_version() < SPDY4
) {
3549 // This is the length field that's too short.
3550 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3551 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3552 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3554 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize();
3555 size_t wrong_size
= right_size
- 4;
3556 test::SetFrameLength(syn_reply_wrong_length
.get(),
3558 spdy_util_
.spdy_version());
3560 scoped_ptr
<SpdyFrame
> req(
3561 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3562 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3563 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3564 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3566 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3567 MockRead reads
[] = {
3568 MockRead(ASYNC
, syn_reply_wrong_length
->data(),
3569 syn_reply_wrong_length
->size() - 4),
3572 DelayedSocketData
data(1, reads
, arraysize(reads
),
3573 writes
, arraysize(writes
));
3574 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3575 BoundNetLog(), GetParam(), NULL
);
3576 helper
.RunToCompletion(&data
);
3577 TransactionHelperResult out
= helper
.output();
3578 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3581 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnDecompressionFailure
) {
3582 if (GetParam().protocol
< kProtoSPDY4MinimumVersion
) {
3583 // Decompression failures are a stream error in SPDY3 and above.
3586 scoped_ptr
<SpdyFrame
> req(
3587 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3588 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3589 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3590 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3592 // Read HEADERS with corrupted payload.
3593 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3594 memset(resp
->data() + 12, 0xff, resp
->size() - 12);
3595 MockRead reads
[] = {CreateMockRead(*resp
)};
3597 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3598 NormalSpdyTransactionHelper
helper(
3599 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3600 helper
.RunToCompletion(&data
);
3601 TransactionHelperResult out
= helper
.output();
3602 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3605 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnFrameSizeError
) {
3606 scoped_ptr
<SpdyFrame
> req(
3607 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3608 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3609 0, GOAWAY_PROTOCOL_ERROR
, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3610 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3612 // Read WINDOW_UPDATE with incorrectly-sized payload.
3613 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3614 // which is mapped to a protocol error, and not a frame size error.
3615 scoped_ptr
<SpdyFrame
> bad_window_update(
3616 spdy_util_
.ConstructSpdyWindowUpdate(1, 1));
3617 test::SetFrameLength(bad_window_update
.get(),
3618 bad_window_update
->size() - 1,
3619 spdy_util_
.spdy_version());
3620 MockRead reads
[] = {CreateMockRead(*bad_window_update
)};
3622 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3623 NormalSpdyTransactionHelper
helper(
3624 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3625 helper
.RunToCompletion(&data
);
3626 TransactionHelperResult out
= helper
.output();
3627 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3630 // Test that we shutdown correctly on write errors.
3631 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3632 scoped_ptr
<SpdyFrame
> req(
3633 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3634 MockWrite writes
[] = {
3635 // We'll write 10 bytes successfully
3636 MockWrite(ASYNC
, req
->data(), 10, 0),
3637 // Followed by ERROR!
3638 MockWrite(ASYNC
, ERR_FAILED
, 1),
3639 // Session drains and attempts to write a GOAWAY: Another ERROR!
3640 MockWrite(ASYNC
, ERR_FAILED
, 2),
3643 MockRead reads
[] = {
3644 MockRead(ASYNC
, 0, 3) // EOF
3647 DeterministicSocketData
data(reads
, arraysize(reads
),
3648 writes
, arraysize(writes
));
3650 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3651 BoundNetLog(), GetParam(), NULL
);
3652 helper
.SetDeterministic();
3653 helper
.RunPreTestSetup();
3654 helper
.AddDeterministicData(&data
);
3655 EXPECT_TRUE(helper
.StartDefaultTest());
3657 helper
.FinishDefaultTest();
3658 EXPECT_TRUE(data
.at_write_eof());
3659 EXPECT_TRUE(!data
.at_read_eof());
3660 TransactionHelperResult out
= helper
.output();
3661 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3664 // Test that partial writes work.
3665 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3666 // Chop the SYN_STREAM frame into 5 chunks.
3667 scoped_ptr
<SpdyFrame
> req(
3668 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3669 const int kChunks
= 5;
3670 scoped_ptr
<MockWrite
[]> writes(ChopWriteFrame(*req
.get(), kChunks
));
3672 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3673 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3674 MockRead reads
[] = {
3675 CreateMockRead(*resp
),
3676 CreateMockRead(*body
),
3677 MockRead(ASYNC
, 0, 0) // EOF
3680 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
3681 writes
.get(), kChunks
);
3682 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3683 BoundNetLog(), GetParam(), NULL
);
3684 helper
.RunToCompletion(&data
);
3685 TransactionHelperResult out
= helper
.output();
3686 EXPECT_EQ(OK
, out
.rv
);
3687 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3688 EXPECT_EQ("hello!", out
.response_data
);
3691 // In this test, we enable compression, but get a uncompressed SynReply from
3692 // the server. Verify that teardown is all clean.
3693 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3694 if (spdy_util_
.spdy_version() >= SPDY4
) {
3695 // HPACK doesn't use deflate compression.
3698 scoped_ptr
<SpdyFrame
> compressed(
3699 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
, true));
3700 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3701 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3702 MockWrite writes
[] = {CreateMockWrite(*compressed
), CreateMockWrite(*goaway
)};
3704 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3705 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3706 MockRead reads
[] = {
3707 CreateMockRead(*resp
),
3710 DelayedSocketData
data(1, reads
, arraysize(reads
),
3711 writes
, arraysize(writes
));
3712 SpdySessionDependencies
* session_deps
=
3713 CreateSpdySessionDependencies(GetParam());
3714 session_deps
->enable_compression
= true;
3715 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3716 BoundNetLog(), GetParam(), session_deps
);
3717 helper
.RunToCompletion(&data
);
3718 TransactionHelperResult out
= helper
.output();
3719 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3723 // Test that the NetLog contains good data for a simple GET request.
3724 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3725 static const char* const kExtraHeaders
[] = {
3726 "user-agent", "Chrome",
3728 scoped_ptr
<SpdyFrame
> req(
3729 spdy_util_
.ConstructSpdyGet(kExtraHeaders
, 1, false, 1, LOWEST
, true));
3730 MockWrite writes
[] = { CreateMockWrite(*req
) };
3732 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3733 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3734 MockRead reads
[] = {
3735 CreateMockRead(*resp
),
3736 CreateMockRead(*body
),
3737 MockRead(ASYNC
, 0, 0) // EOF
3740 CapturingBoundNetLog log
;
3742 DelayedSocketData
data(1, reads
, arraysize(reads
),
3743 writes
, arraysize(writes
));
3744 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3746 log
.bound(), GetParam(), NULL
);
3747 helper
.RunToCompletion(&data
);
3748 TransactionHelperResult out
= helper
.output();
3749 EXPECT_EQ(OK
, out
.rv
);
3750 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3751 EXPECT_EQ("hello!", out
.response_data
);
3753 // Check that the NetLog was filled reasonably.
3754 // This test is intentionally non-specific about the exact ordering of the
3755 // log; instead we just check to make sure that certain events exist, and that
3756 // they are in the right order.
3757 net::CapturingNetLog::CapturedEntryList entries
;
3758 log
.GetEntries(&entries
);
3760 EXPECT_LT(0u, entries
.size());
3762 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3763 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3764 net::NetLog::PHASE_BEGIN
);
3765 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3766 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3767 net::NetLog::PHASE_END
);
3768 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3770 net::NetLog::PHASE_BEGIN
);
3771 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3773 net::NetLog::PHASE_END
);
3774 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3775 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3776 net::NetLog::PHASE_BEGIN
);
3777 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3778 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3779 net::NetLog::PHASE_END
);
3781 // Check that we logged all the headers correctly
3782 const NetLog::EventType type
=
3783 (GetParam().protocol
<= kProtoSPDY31
)
3784 ? net::NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3785 : net::NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS
;
3786 pos
= net::ExpectLogContainsSomewhere(entries
, 0, type
,
3787 net::NetLog::PHASE_NONE
);
3789 base::ListValue
* header_list
;
3790 ASSERT_TRUE(entries
[pos
].params
.get());
3791 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3793 std::vector
<std::string
> expected
;
3794 expected
.push_back(std::string(spdy_util_
.GetHostKey()) + ": www.google.com");
3795 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3796 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": http");
3797 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3798 expected
.push_back("user-agent: Chrome");
3799 if (spdy_util_
.spdy_version() < SPDY4
) {
3800 // SPDY4/HTTP2 eliminates use of the :version header.
3801 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3803 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3804 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3805 it
!= expected
.end();
3807 base::StringValue
header(*it
);
3808 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3809 "Header not found: " << *it
;
3813 // Since we buffer the IO from the stream to the renderer, this test verifies
3814 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3815 // on the network, but issued a Read for only 5 of those bytes) that the data
3816 // flow still works correctly.
3817 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3818 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3820 scoped_ptr
<SpdyFrame
> req(
3821 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3822 MockWrite writes
[] = { CreateMockWrite(*req
) };
3824 // 2 data frames in a single read.
3825 scoped_ptr
<SpdyFrame
> data_frame_1(
3826 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3827 scoped_ptr
<SpdyFrame
> data_frame_2(
3828 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3829 const SpdyFrame
* data_frames
[2] = {
3833 char combined_data_frames
[100];
3834 int combined_data_frames_len
=
3835 CombineFrames(data_frames
, arraysize(data_frames
),
3836 combined_data_frames
, arraysize(combined_data_frames
));
3837 scoped_ptr
<SpdyFrame
> last_frame(
3838 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3840 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3841 MockRead reads
[] = {
3842 CreateMockRead(*resp
),
3843 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3844 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3845 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3846 CreateMockRead(*last_frame
),
3847 MockRead(ASYNC
, 0, 0) // EOF
3850 DelayedSocketData
data(1, reads
, arraysize(reads
),
3851 writes
, arraysize(writes
));
3853 TestCompletionCallback callback
;
3855 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3856 BoundNetLog(), GetParam(), NULL
);
3857 helper
.RunPreTestSetup();
3858 helper
.AddData(&data
);
3859 HttpNetworkTransaction
* trans
= helper
.trans();
3860 int rv
= trans
->Start(
3861 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3862 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3864 TransactionHelperResult out
= helper
.output();
3865 out
.rv
= callback
.WaitForResult();
3866 EXPECT_EQ(out
.rv
, OK
);
3868 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3869 EXPECT_TRUE(response
->headers
.get() != NULL
);
3870 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3871 out
.status_line
= response
->headers
->GetStatusLine();
3872 out
.response_info
= *response
; // Make a copy so we can verify.
3875 TestCompletionCallback read_callback
;
3877 std::string content
;
3879 // Read small chunks at a time.
3880 const int kSmallReadSize
= 3;
3881 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3882 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3883 if (rv
== net::ERR_IO_PENDING
) {
3884 data
.CompleteRead();
3885 rv
= read_callback
.WaitForResult();
3888 content
.append(buf
->data(), rv
);
3889 } else if (rv
< 0) {
3894 out
.response_data
.swap(content
);
3896 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3897 // MockClientSocketFactory) are still alive.
3898 base::RunLoop().RunUntilIdle();
3900 // Verify that we consumed all test data.
3901 helper
.VerifyDataConsumed();
3903 EXPECT_EQ(OK
, out
.rv
);
3904 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3905 EXPECT_EQ("goodbye world", out
.response_data
);
3908 // Verify that basic buffering works; when multiple data frames arrive
3909 // at the same time, ensure that we don't notify a read completion for
3910 // each data frame individually.
3911 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3912 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3914 scoped_ptr
<SpdyFrame
> req(
3915 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3916 MockWrite writes
[] = { CreateMockWrite(*req
) };
3918 // 4 data frames in a single read.
3919 scoped_ptr
<SpdyFrame
> data_frame(
3920 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3921 scoped_ptr
<SpdyFrame
> data_frame_fin(
3922 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3923 const SpdyFrame
* data_frames
[4] = {
3927 data_frame_fin
.get()
3929 char combined_data_frames
[100];
3930 int combined_data_frames_len
=
3931 CombineFrames(data_frames
, arraysize(data_frames
),
3932 combined_data_frames
, arraysize(combined_data_frames
));
3934 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3935 MockRead reads
[] = {
3936 CreateMockRead(*resp
),
3937 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3938 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3939 MockRead(ASYNC
, 0, 0) // EOF
3942 DelayedSocketData
data(1, reads
, arraysize(reads
),
3943 writes
, arraysize(writes
));
3945 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3946 BoundNetLog(), GetParam(), NULL
);
3947 helper
.RunPreTestSetup();
3948 helper
.AddData(&data
);
3949 HttpNetworkTransaction
* trans
= helper
.trans();
3951 TestCompletionCallback callback
;
3952 int rv
= trans
->Start(
3953 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3954 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3956 TransactionHelperResult out
= helper
.output();
3957 out
.rv
= callback
.WaitForResult();
3958 EXPECT_EQ(out
.rv
, OK
);
3960 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3961 EXPECT_TRUE(response
->headers
.get() != NULL
);
3962 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3963 out
.status_line
= response
->headers
->GetStatusLine();
3964 out
.response_info
= *response
; // Make a copy so we can verify.
3967 TestCompletionCallback read_callback
;
3969 std::string content
;
3970 int reads_completed
= 0;
3972 // Read small chunks at a time.
3973 const int kSmallReadSize
= 14;
3974 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3975 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3976 if (rv
== net::ERR_IO_PENDING
) {
3977 data
.CompleteRead();
3978 rv
= read_callback
.WaitForResult();
3981 EXPECT_EQ(kSmallReadSize
, rv
);
3982 content
.append(buf
->data(), rv
);
3983 } else if (rv
< 0) {
3984 FAIL() << "Unexpected read error: " << rv
;
3989 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3991 out
.response_data
.swap(content
);
3993 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3994 // MockClientSocketFactory) are still alive.
3995 base::RunLoop().RunUntilIdle();
3997 // Verify that we consumed all test data.
3998 helper
.VerifyDataConsumed();
4000 EXPECT_EQ(OK
, out
.rv
);
4001 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4002 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4005 // Verify the case where we buffer data but read it after it has been buffered.
4006 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
4007 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4009 scoped_ptr
<SpdyFrame
> req(
4010 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4011 MockWrite writes
[] = { CreateMockWrite(*req
) };
4013 // 5 data frames in a single read.
4014 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4015 scoped_ptr
<SpdyFrame
> data_frame(
4016 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4017 scoped_ptr
<SpdyFrame
> data_frame_fin(
4018 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4019 const SpdyFrame
* frames
[5] = {reply
.get(), data_frame
.get(), data_frame
.get(),
4020 data_frame
.get(), data_frame_fin
.get()};
4021 char combined_frames
[200];
4022 int combined_frames_len
=
4023 CombineFrames(frames
, arraysize(frames
),
4024 combined_frames
, arraysize(combined_frames
));
4026 MockRead reads
[] = {
4027 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4028 MockRead(ASYNC
, 0, 0) // EOF
4031 DelayedSocketData
data(1, reads
, arraysize(reads
),
4032 writes
, arraysize(writes
));
4034 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4035 BoundNetLog(), GetParam(), NULL
);
4036 helper
.RunPreTestSetup();
4037 helper
.AddData(&data
);
4038 HttpNetworkTransaction
* trans
= helper
.trans();
4040 TestCompletionCallback callback
;
4041 int rv
= trans
->Start(
4042 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4045 TransactionHelperResult out
= helper
.output();
4046 out
.rv
= callback
.WaitForResult();
4047 EXPECT_EQ(out
.rv
, OK
);
4049 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4050 EXPECT_TRUE(response
->headers
.get() != NULL
);
4051 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4052 out
.status_line
= response
->headers
->GetStatusLine();
4053 out
.response_info
= *response
; // Make a copy so we can verify.
4056 TestCompletionCallback read_callback
;
4058 std::string content
;
4059 int reads_completed
= 0;
4061 // Read small chunks at a time.
4062 const int kSmallReadSize
= 14;
4063 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4064 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4066 EXPECT_EQ(kSmallReadSize
, rv
);
4067 content
.append(buf
->data(), rv
);
4068 } else if (rv
< 0) {
4069 FAIL() << "Unexpected read error: " << rv
;
4074 EXPECT_EQ(3, reads_completed
);
4076 out
.response_data
.swap(content
);
4078 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4079 // MockClientSocketFactory) are still alive.
4080 base::RunLoop().RunUntilIdle();
4082 // Verify that we consumed all test data.
4083 helper
.VerifyDataConsumed();
4085 EXPECT_EQ(OK
, out
.rv
);
4086 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4087 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4090 // Verify the case where we buffer data and close the connection.
4091 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4092 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4094 scoped_ptr
<SpdyFrame
> req(
4095 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4096 MockWrite writes
[] = { CreateMockWrite(*req
) };
4098 // All data frames in a single read.
4099 // NOTE: We don't FIN the stream.
4100 scoped_ptr
<SpdyFrame
> data_frame(
4101 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4102 const SpdyFrame
* data_frames
[4] = {
4108 char combined_data_frames
[100];
4109 int combined_data_frames_len
=
4110 CombineFrames(data_frames
, arraysize(data_frames
),
4111 combined_data_frames
, arraysize(combined_data_frames
));
4112 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4113 MockRead reads
[] = {
4114 CreateMockRead(*resp
),
4115 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4116 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4117 MockRead(ASYNC
, 0, 0) // EOF
4120 DelayedSocketData
data(1, reads
, arraysize(reads
),
4121 writes
, arraysize(writes
));
4123 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4124 BoundNetLog(), GetParam(), NULL
);
4125 helper
.RunPreTestSetup();
4126 helper
.AddData(&data
);
4127 HttpNetworkTransaction
* trans
= helper
.trans();
4129 TestCompletionCallback callback
;
4131 int rv
= trans
->Start(
4132 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4135 TransactionHelperResult out
= helper
.output();
4136 out
.rv
= callback
.WaitForResult();
4137 EXPECT_EQ(out
.rv
, OK
);
4139 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4140 EXPECT_TRUE(response
->headers
.get() != NULL
);
4141 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4142 out
.status_line
= response
->headers
->GetStatusLine();
4143 out
.response_info
= *response
; // Make a copy so we can verify.
4146 TestCompletionCallback read_callback
;
4148 std::string content
;
4149 int reads_completed
= 0;
4151 // Read small chunks at a time.
4152 const int kSmallReadSize
= 14;
4153 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4154 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4155 if (rv
== net::ERR_IO_PENDING
) {
4156 data
.CompleteRead();
4157 rv
= read_callback
.WaitForResult();
4160 content
.append(buf
->data(), rv
);
4161 } else if (rv
< 0) {
4162 // This test intentionally closes the connection, and will get an error.
4163 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4169 EXPECT_EQ(0, reads_completed
);
4171 out
.response_data
.swap(content
);
4173 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4174 // MockClientSocketFactory) are still alive.
4175 base::RunLoop().RunUntilIdle();
4177 // Verify that we consumed all test data.
4178 helper
.VerifyDataConsumed();
4181 // Verify the case where we buffer data and cancel the transaction.
4182 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4183 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4185 scoped_ptr
<SpdyFrame
> req(
4186 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4187 scoped_ptr
<SpdyFrame
> rst(
4188 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
4189 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*rst
)};
4191 // NOTE: We don't FIN the stream.
4192 scoped_ptr
<SpdyFrame
> data_frame(
4193 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4195 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4196 MockRead reads
[] = {
4197 CreateMockRead(*resp
),
4198 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4199 CreateMockRead(*data_frame
),
4200 MockRead(ASYNC
, 0, 0) // EOF
4203 DelayedSocketData
data(1, reads
, arraysize(reads
),
4204 writes
, arraysize(writes
));
4206 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4207 BoundNetLog(), GetParam(), NULL
);
4208 helper
.RunPreTestSetup();
4209 helper
.AddData(&data
);
4210 HttpNetworkTransaction
* trans
= helper
.trans();
4211 TestCompletionCallback callback
;
4213 int rv
= trans
->Start(
4214 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4215 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4217 TransactionHelperResult out
= helper
.output();
4218 out
.rv
= callback
.WaitForResult();
4219 EXPECT_EQ(out
.rv
, OK
);
4221 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4222 EXPECT_TRUE(response
->headers
.get() != NULL
);
4223 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4224 out
.status_line
= response
->headers
->GetStatusLine();
4225 out
.response_info
= *response
; // Make a copy so we can verify.
4228 TestCompletionCallback read_callback
;
4230 const int kReadSize
= 256;
4231 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4232 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4233 ASSERT_EQ(net::ERR_IO_PENDING
, rv
) << "Unexpected read: " << rv
;
4235 // Complete the read now, which causes buffering to start.
4236 data
.CompleteRead();
4237 // Destroy the transaction, causing the stream to get cancelled
4238 // and orphaning the buffered IO task.
4239 helper
.ResetTrans();
4241 // Flush the MessageLoop; this will cause the buffered IO task
4242 // to run for the final time.
4243 base::RunLoop().RunUntilIdle();
4245 // Verify that we consumed all test data.
4246 helper
.VerifyDataConsumed();
4249 // Test that if the server requests persistence of settings, that we save
4250 // the settings in the HttpServerProperties.
4251 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4252 if (spdy_util_
.spdy_version() >= SPDY4
) {
4253 // SPDY4 doesn't support settings persistence.
4256 static const SpdyHeaderInfo kSynReplyInfo
= {
4257 SYN_REPLY
, // Syn Reply
4259 0, // Associated Stream ID
4260 ConvertRequestPriorityToSpdyPriority(
4261 LOWEST
, spdy_util_
.spdy_version()),
4262 kSpdyCredentialSlotUnused
,
4263 CONTROL_FLAG_NONE
, // Control Flags
4264 false, // Compressed
4265 RST_STREAM_INVALID
, // Status
4268 DATA_FLAG_NONE
// Data Flags
4271 BoundNetLog net_log
;
4272 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4273 net_log
, GetParam(), NULL
);
4274 helper
.RunPreTestSetup();
4276 // Verify that no settings exist initially.
4277 HostPortPair
host_port_pair("www.google.com", helper
.port());
4278 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4279 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4280 host_port_pair
).empty());
4282 // Construct the request.
4283 scoped_ptr
<SpdyFrame
> req(
4284 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4285 MockWrite writes
[] = { CreateMockWrite(*req
) };
4287 // Construct the reply.
4288 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4289 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4290 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4291 scoped_ptr
<SpdyFrame
> reply(
4292 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4294 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4295 unsigned int kSampleValue1
= 0x0a0a0a0a;
4296 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4297 unsigned int kSampleValue2
= 0x0b0b0b0b;
4298 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4299 unsigned int kSampleValue3
= 0x0c0c0c0c;
4300 scoped_ptr
<SpdyFrame
> settings_frame
;
4302 // Construct the SETTINGS frame.
4303 SettingsMap settings
;
4304 // First add a persisted setting.
4305 settings
[kSampleId1
] =
4306 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4307 // Next add a non-persisted setting.
4308 settings
[kSampleId2
] =
4309 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4310 // Next add another persisted setting.
4311 settings
[kSampleId3
] =
4312 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4313 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4316 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4317 MockRead reads
[] = {
4318 CreateMockRead(*reply
),
4319 CreateMockRead(*body
),
4320 CreateMockRead(*settings_frame
),
4321 MockRead(ASYNC
, 0, 0) // EOF
4324 DelayedSocketData
data(1, reads
, arraysize(reads
),
4325 writes
, arraysize(writes
));
4326 helper
.AddData(&data
);
4327 helper
.RunDefaultTest();
4328 helper
.VerifyDataConsumed();
4329 TransactionHelperResult out
= helper
.output();
4330 EXPECT_EQ(OK
, out
.rv
);
4331 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4332 EXPECT_EQ("hello!", out
.response_data
);
4335 // Verify we had two persisted settings.
4336 const SettingsMap
& settings_map
=
4337 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4339 ASSERT_EQ(2u, settings_map
.size());
4341 // Verify the first persisted setting.
4342 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4343 EXPECT_TRUE(it1
!= settings_map
.end());
4344 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4345 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4346 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4348 // Verify the second persisted setting.
4349 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4350 EXPECT_TRUE(it3
!= settings_map
.end());
4351 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4352 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4353 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4357 // Test that when there are settings saved that they are sent back to the
4358 // server upon session establishment.
4359 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4360 if (spdy_util_
.spdy_version() >= SPDY4
) {
4361 // SPDY4 doesn't support settings persistence.
4364 static const SpdyHeaderInfo kSynReplyInfo
= {
4365 SYN_REPLY
, // Syn Reply
4367 0, // Associated Stream ID
4368 ConvertRequestPriorityToSpdyPriority(
4369 LOWEST
, spdy_util_
.spdy_version()),
4370 kSpdyCredentialSlotUnused
,
4371 CONTROL_FLAG_NONE
, // Control Flags
4372 false, // Compressed
4373 RST_STREAM_INVALID
, // Status
4376 DATA_FLAG_NONE
// Data Flags
4379 BoundNetLog net_log
;
4380 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4381 net_log
, GetParam(), NULL
);
4382 helper
.RunPreTestSetup();
4384 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4386 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4387 pool_peer
.SetEnableSendingInitialData(true);
4389 // Verify that no settings exist initially.
4390 HostPortPair
host_port_pair("www.google.com", helper
.port());
4391 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4392 host_port_pair
).empty());
4394 const SpdySettingsIds kSampleId1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
4395 unsigned int kSampleValue1
= 0x0a0a0a0a;
4396 const SpdySettingsIds kSampleId2
= SETTINGS_INITIAL_WINDOW_SIZE
;
4397 unsigned int kSampleValue2
= 0x0c0c0c0c;
4399 // First add a persisted setting.
4400 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4403 SETTINGS_FLAG_PLEASE_PERSIST
,
4406 // Next add another persisted setting.
4407 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4410 SETTINGS_FLAG_PLEASE_PERSIST
,
4413 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4414 host_port_pair
).size());
4416 // Construct the initial SETTINGS frame.
4417 SettingsMap initial_settings
;
4418 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4419 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4420 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4421 spdy_util_
.ConstructSpdySettings(initial_settings
));
4423 // Construct the initial window update.
4424 scoped_ptr
<SpdyFrame
> initial_window_update(
4425 spdy_util_
.ConstructSpdyWindowUpdate(
4426 kSessionFlowControlStreamId
,
4427 kDefaultInitialRecvWindowSize
-
4428 SpdySession::GetInitialWindowSize(GetParam().protocol
)));
4430 // Construct the persisted SETTINGS frame.
4431 const SettingsMap
& settings
=
4432 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4434 scoped_ptr
<SpdyFrame
> settings_frame(
4435 spdy_util_
.ConstructSpdySettings(settings
));
4437 // Construct the request.
4438 scoped_ptr
<SpdyFrame
> req(
4439 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4441 std::vector
<MockWrite
> writes
;
4442 if ((GetParam().protocol
>= kProtoSPDY4MinimumVersion
) &&
4443 (GetParam().protocol
<= kProtoSPDY4MaximumVersion
)) {
4446 kHttp2ConnectionHeaderPrefix
,
4447 kHttp2ConnectionHeaderPrefixSize
));
4449 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4450 if (GetParam().protocol
>= kProtoSPDY31
) {
4451 writes
.push_back(CreateMockWrite(*initial_window_update
));
4453 writes
.push_back(CreateMockWrite(*settings_frame
));
4454 writes
.push_back(CreateMockWrite(*req
));
4456 // Construct the reply.
4457 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4458 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4459 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4460 scoped_ptr
<SpdyFrame
> reply(
4461 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4463 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4464 MockRead reads
[] = {
4465 CreateMockRead(*reply
),
4466 CreateMockRead(*body
),
4467 MockRead(ASYNC
, 0, 0) // EOF
4470 DelayedSocketData
data(2, reads
, arraysize(reads
),
4471 vector_as_array(&writes
), writes
.size());
4472 helper
.AddData(&data
);
4473 helper
.RunDefaultTest();
4474 helper
.VerifyDataConsumed();
4475 TransactionHelperResult out
= helper
.output();
4476 EXPECT_EQ(OK
, out
.rv
);
4477 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4478 EXPECT_EQ("hello!", out
.response_data
);
4481 // Verify we had two persisted settings.
4482 const SettingsMap
& settings_map
=
4483 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4485 ASSERT_EQ(2u, settings_map
.size());
4487 // Verify the first persisted setting.
4488 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4489 EXPECT_TRUE(it1
!= settings_map
.end());
4490 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4491 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4492 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4494 // Verify the second persisted setting.
4495 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4496 EXPECT_TRUE(it2
!= settings_map
.end());
4497 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4498 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4499 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4503 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4504 scoped_ptr
<SpdyFrame
> req(
4505 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4506 MockWrite writes
[] = { CreateMockWrite(*req
) };
4508 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4509 MockRead reads
[] = {
4510 CreateMockRead(*go_away
),
4513 DelayedSocketData
data(1, reads
, arraysize(reads
),
4514 writes
, arraysize(writes
));
4515 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4516 BoundNetLog(), GetParam(), NULL
);
4517 helper
.AddData(&data
);
4518 helper
.RunToCompletion(&data
);
4519 TransactionHelperResult out
= helper
.output();
4520 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4523 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4524 scoped_ptr
<SpdyFrame
> req(
4525 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4526 MockWrite writes
[] = { CreateMockWrite(*req
) };
4528 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4529 MockRead reads
[] = {
4530 CreateMockRead(*resp
),
4531 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4534 DelayedSocketData
data(1, reads
, arraysize(reads
),
4535 writes
, arraysize(writes
));
4537 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4538 log
, GetParam(), NULL
);
4539 helper
.RunPreTestSetup();
4540 helper
.AddData(&data
);
4541 HttpNetworkTransaction
* trans
= helper
.trans();
4543 TestCompletionCallback callback
;
4544 TransactionHelperResult out
;
4545 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4547 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4548 out
.rv
= callback
.WaitForResult();
4549 EXPECT_EQ(out
.rv
, OK
);
4551 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4552 EXPECT_TRUE(response
->headers
.get() != NULL
);
4553 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4554 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4555 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4557 // Verify that we consumed all test data.
4558 helper
.VerifyDataConsumed();
4561 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4562 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredError
) {
4563 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4564 if (spdy_util_
.spdy_version() < SPDY4
)
4567 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4568 BoundNetLog(), GetParam(), nullptr);
4570 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4571 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4572 MockRead reads
[] = {
4573 CreateMockRead(*go_away
),
4575 DelayedSocketData
data(0, reads
, arraysize(reads
), nullptr, 0);
4577 helper
.RunToCompletion(&data
);
4578 TransactionHelperResult out
= helper
.output();
4579 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED
, out
.rv
);
4582 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4583 // protocol negotiation happens, instead this test forces protocols for both
4585 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredRetry
) {
4586 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4587 if (spdy_util_
.spdy_version() < SPDY4
)
4589 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4590 // only spoken over SSL.
4591 if (GetParam().ssl_type
!= SPDYSSL
)
4594 HttpRequestInfo request
;
4595 request
.method
= "GET";
4596 request
.url
= GURL("https://www.google.com/");
4597 scoped_ptr
<SpdySessionDependencies
> session_deps(
4598 CreateSpdySessionDependencies(GetParam()));
4599 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4600 session_deps
->force_spdy_over_ssl
= false;
4601 session_deps
->force_spdy_always
= false;
4602 session_deps
->next_protos
= SpdyNextProtos();
4603 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4604 GetParam(), session_deps
.release());
4606 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4607 const char* url
= "https://www.google.com/";
4608 scoped_ptr
<SpdyHeaderBlock
> headers(spdy_util_
.ConstructGetHeaderBlock(url
));
4609 scoped_ptr
<SpdyFrame
> req(
4610 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4611 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4612 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4613 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4614 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4615 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4616 arraysize(writes0
));
4618 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4619 new SSLSocketDataProvider(ASYNC
, OK
));
4620 // Expect HTTP/2 protocols too in SSLConfig.
4621 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4622 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4623 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4624 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_15
);
4626 ssl_provider0
->SetNextProto(GetParam().protocol
);
4627 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4629 // Second socket: falling back to HTTP/1.1.
4630 MockWrite writes1
[] = {MockWrite(
4631 "GET / HTTP/1.1\r\n"
4632 "Host: www.google.com\r\n"
4633 "Connection: keep-alive\r\n\r\n")};
4634 MockRead reads1
[] = {MockRead(
4635 "HTTP/1.1 200 OK\r\n"
4636 "Content-Length: 5\r\n\r\n"
4638 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4639 arraysize(writes1
));
4641 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4642 new SSLSocketDataProvider(ASYNC
, OK
));
4643 // Expect only HTTP/1.1 protocol in SSLConfig.
4644 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4646 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4647 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4649 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4650 helper
.session()->spdy_session_pool()->http_server_properties();
4651 const HostPortPair host_port_pair
= HostPortPair::FromURL(GURL(url
));
4652 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4654 helper
.RunPreTestSetup();
4655 helper
.StartDefaultTest();
4656 helper
.FinishDefaultTestWithoutVerification();
4657 helper
.VerifyDataConsumed();
4658 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4660 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4661 ASSERT_TRUE(response
!= nullptr);
4662 ASSERT_TRUE(response
->headers
.get() != nullptr);
4663 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4664 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4665 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4666 EXPECT_TRUE(response
->was_npn_negotiated
);
4667 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4668 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4669 EXPECT_EQ(443, response
->socket_address
.port());
4670 std::string response_data
;
4671 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4672 EXPECT_EQ("hello", response_data
);
4675 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4676 // proxy. Note that no actual protocol negotiation happens, instead this test
4677 // forces protocols for both sockets.
4678 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredProxyRetry
) {
4679 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4680 if (spdy_util_
.spdy_version() < SPDY4
)
4682 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4683 // only spoken over SSL.
4684 if (GetParam().ssl_type
!= SPDYSSL
)
4687 HttpRequestInfo request
;
4688 request
.method
= "GET";
4689 request
.url
= GURL("https://www.google.com/");
4690 scoped_ptr
<SpdySessionDependencies
> session_deps(
4691 CreateSpdySessionDependencies(
4693 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4694 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4695 session_deps
->force_spdy_over_ssl
= false;
4696 session_deps
->force_spdy_always
= false;
4697 session_deps
->next_protos
= SpdyNextProtos();
4698 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4699 GetParam(), session_deps
.release());
4701 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4702 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
4703 nullptr, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
4704 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4705 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4706 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4707 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4708 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4709 arraysize(writes0
));
4711 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4712 new SSLSocketDataProvider(ASYNC
, OK
));
4713 // Expect HTTP/2 protocols too in SSLConfig.
4714 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4715 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4716 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4717 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_15
);
4719 ssl_provider0
->SetNextProto(GetParam().protocol
);
4720 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4722 // Second socket: retry using HTTP/1.1.
4723 MockWrite writes1
[] = {
4725 "CONNECT www.google.com:443 HTTP/1.1\r\n"
4726 "Host: www.google.com\r\n"
4727 "Proxy-Connection: keep-alive\r\n\r\n"),
4729 "GET / HTTP/1.1\r\n"
4730 "Host: www.google.com\r\n"
4731 "Connection: keep-alive\r\n\r\n"),
4734 MockRead reads1
[] = {
4735 MockRead(ASYNC
, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4737 "HTTP/1.1 200 OK\r\n"
4738 "Content-Length: 5\r\n\r\n"
4741 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4742 arraysize(writes1
));
4744 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4745 new SSLSocketDataProvider(ASYNC
, OK
));
4746 // Expect only HTTP/1.1 protocol in SSLConfig.
4747 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4749 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4750 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4752 // A third socket is needed for the tunnelled connection.
4753 scoped_ptr
<SSLSocketDataProvider
> ssl_provider2(
4754 new SSLSocketDataProvider(ASYNC
, OK
));
4755 helper
.session_deps()->socket_factory
->AddSSLSocketDataProvider(
4756 ssl_provider2
.get());
4758 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4759 helper
.session()->spdy_session_pool()->http_server_properties();
4760 const HostPortPair proxy_host_port_pair
= HostPortPair("myproxy", 70);
4761 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4763 helper
.RunPreTestSetup();
4764 helper
.StartDefaultTest();
4765 helper
.FinishDefaultTestWithoutVerification();
4766 helper
.VerifyDataConsumed();
4767 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4769 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4770 ASSERT_TRUE(response
!= nullptr);
4771 ASSERT_TRUE(response
->headers
.get() != nullptr);
4772 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4773 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4774 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4775 EXPECT_FALSE(response
->was_npn_negotiated
);
4776 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4777 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4778 EXPECT_EQ(70, response
->socket_address
.port());
4779 std::string response_data
;
4780 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4781 EXPECT_EQ("hello", response_data
);
4784 // Test to make sure we can correctly connect through a proxy.
4785 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4786 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4787 BoundNetLog(), GetParam(), NULL
);
4788 helper
.session_deps().reset(CreateSpdySessionDependencies(
4790 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4791 helper
.SetSession(make_scoped_refptr(
4792 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4793 helper
.RunPreTestSetup();
4794 HttpNetworkTransaction
* trans
= helper
.trans();
4796 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4797 "Host: www.google.com\r\n"
4798 "Proxy-Connection: keep-alive\r\n\r\n"};
4799 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4800 "Host: www.google.com\r\n"
4801 "Proxy-Connection: keep-alive\r\n\r\n"};
4802 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4803 scoped_ptr
<SpdyFrame
> req(
4804 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4805 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4806 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4808 MockWrite writes_SPDYNPN
[] = {
4809 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4810 CreateMockWrite(*req
, 2),
4812 MockRead reads_SPDYNPN
[] = {
4813 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4814 CreateMockRead(*resp
, 3),
4815 CreateMockRead(*body
.get(), 4),
4816 MockRead(ASYNC
, 0, 0, 5),
4819 MockWrite writes_SPDYSSL
[] = {
4820 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4821 CreateMockWrite(*req
, 2),
4823 MockRead reads_SPDYSSL
[] = {
4824 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4825 CreateMockRead(*resp
, 3),
4826 CreateMockRead(*body
.get(), 4),
4827 MockRead(ASYNC
, 0, 0, 5),
4830 MockWrite writes_SPDYNOSSL
[] = {
4831 CreateMockWrite(*req
, 0),
4834 MockRead reads_SPDYNOSSL
[] = {
4835 CreateMockRead(*resp
, 1),
4836 CreateMockRead(*body
.get(), 2),
4837 MockRead(ASYNC
, 0, 0, 3),
4840 scoped_ptr
<OrderedSocketData
> data
;
4841 switch (GetParam().ssl_type
) {
4843 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4844 arraysize(reads_SPDYNOSSL
),
4846 arraysize(writes_SPDYNOSSL
)));
4849 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4850 arraysize(reads_SPDYSSL
),
4852 arraysize(writes_SPDYSSL
)));
4855 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4856 arraysize(reads_SPDYNPN
),
4858 arraysize(writes_SPDYNPN
)));
4864 helper
.AddData(data
.get());
4865 TestCompletionCallback callback
;
4867 int rv
= trans
->Start(
4868 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4869 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4871 rv
= callback
.WaitForResult();
4874 // Verify the SYN_REPLY.
4875 HttpResponseInfo response
= *trans
->GetResponseInfo();
4876 EXPECT_TRUE(response
.headers
.get() != NULL
);
4877 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4879 std::string response_data
;
4880 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4881 EXPECT_EQ("hello!", response_data
);
4882 helper
.VerifyDataConsumed();
4885 // Test to make sure we can correctly connect through a proxy to www.google.com,
4886 // if there already exists a direct spdy connection to www.google.com. See
4887 // http://crbug.com/49874
4888 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4889 // When setting up the first transaction, we store the SpdySessionPool so that
4890 // we can use the same pool in the second transaction.
4891 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4892 BoundNetLog(), GetParam(), NULL
);
4894 // Use a proxy service which returns a proxy fallback list from DIRECT to
4895 // myproxy:70. For this test there will be no fallback, so it is equivalent
4896 // to simply DIRECT. The reason for appending the second proxy is to verify
4897 // that the session pool key used does is just "DIRECT".
4898 helper
.session_deps().reset(CreateSpdySessionDependencies(
4900 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4901 helper
.SetSession(make_scoped_refptr(
4902 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4904 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4905 helper
.RunPreTestSetup();
4907 // Construct and send a simple GET request.
4908 scoped_ptr
<SpdyFrame
> req(
4909 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4910 MockWrite writes
[] = {
4911 CreateMockWrite(*req
, 1),
4914 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4915 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4916 MockRead reads
[] = {
4917 CreateMockRead(*resp
, 2),
4918 CreateMockRead(*body
, 3),
4919 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4920 MockRead(ASYNC
, 0, 5) // EOF
4922 OrderedSocketData
data(reads
, arraysize(reads
),
4923 writes
, arraysize(writes
));
4924 helper
.AddData(&data
);
4925 HttpNetworkTransaction
* trans
= helper
.trans();
4927 TestCompletionCallback callback
;
4928 TransactionHelperResult out
;
4929 out
.rv
= trans
->Start(
4930 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4932 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4933 out
.rv
= callback
.WaitForResult();
4934 EXPECT_EQ(out
.rv
, OK
);
4936 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4937 EXPECT_TRUE(response
->headers
.get() != NULL
);
4938 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4939 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4940 EXPECT_EQ(OK
, out
.rv
);
4941 out
.status_line
= response
->headers
->GetStatusLine();
4942 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4943 EXPECT_EQ("hello!", out
.response_data
);
4945 // Check that the SpdySession is still in the SpdySessionPool.
4946 HostPortPair
host_port_pair("www.google.com", helper
.port());
4947 SpdySessionKey
session_pool_key_direct(
4948 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4949 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4950 SpdySessionKey
session_pool_key_proxy(
4952 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4953 PRIVACY_MODE_DISABLED
);
4954 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4956 // Set up data for the proxy connection.
4957 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4958 "Host: www.google.com\r\n"
4959 "Proxy-Connection: keep-alive\r\n\r\n"};
4960 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4961 "Host: www.google.com\r\n"
4962 "Proxy-Connection: keep-alive\r\n\r\n"};
4963 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4964 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4965 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4966 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4967 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4969 MockWrite writes_SPDYNPN
[] = {
4970 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4971 CreateMockWrite(*req2
, 2),
4973 MockRead reads_SPDYNPN
[] = {
4974 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4975 CreateMockRead(*resp2
, 3),
4976 CreateMockRead(*body2
, 4),
4977 MockRead(ASYNC
, 0, 5) // EOF
4980 MockWrite writes_SPDYNOSSL
[] = {
4981 CreateMockWrite(*req2
, 0),
4983 MockRead reads_SPDYNOSSL
[] = {
4984 CreateMockRead(*resp2
, 1),
4985 CreateMockRead(*body2
, 2),
4986 MockRead(ASYNC
, 0, 3) // EOF
4989 MockWrite writes_SPDYSSL
[] = {
4990 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4991 CreateMockWrite(*req2
, 2),
4993 MockRead reads_SPDYSSL
[] = {
4994 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4995 CreateMockRead(*resp2
, 3),
4996 CreateMockRead(*body2
, 4),
4997 MockRead(ASYNC
, 0, 0, 5),
5000 scoped_ptr
<OrderedSocketData
> data_proxy
;
5001 switch (GetParam().ssl_type
) {
5003 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
5004 arraysize(reads_SPDYNPN
),
5006 arraysize(writes_SPDYNPN
)));
5009 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
5010 arraysize(reads_SPDYNOSSL
),
5012 arraysize(writes_SPDYNOSSL
)));
5015 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
5016 arraysize(reads_SPDYSSL
),
5018 arraysize(writes_SPDYSSL
)));
5024 // Create another request to www.google.com, but this time through a proxy.
5025 HttpRequestInfo request_proxy
;
5026 request_proxy
.method
= "GET";
5027 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
5028 request_proxy
.load_flags
= 0;
5029 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
5030 CreateSpdySessionDependencies(GetParam()));
5031 // Ensure that this transaction uses the same SpdySessionPool.
5032 scoped_refptr
<HttpNetworkSession
> session_proxy(
5033 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
5034 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
5035 BoundNetLog(), GetParam(), NULL
);
5036 HttpNetworkSessionPeer
session_peer(session_proxy
);
5037 scoped_ptr
<net::ProxyService
> proxy_service(
5038 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5039 session_peer
.SetProxyService(proxy_service
.get());
5040 helper_proxy
.session_deps().swap(ssd_proxy
);
5041 helper_proxy
.SetSession(session_proxy
);
5042 helper_proxy
.RunPreTestSetup();
5043 helper_proxy
.AddData(data_proxy
.get());
5045 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
5046 TestCompletionCallback callback_proxy
;
5047 int rv
= trans_proxy
->Start(
5048 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
5049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5050 rv
= callback_proxy
.WaitForResult();
5053 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
5054 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
5055 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
5057 std::string response_data
;
5058 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
5059 EXPECT_EQ("hello!", response_data
);
5061 data
.CompleteRead();
5062 helper_proxy
.VerifyDataConsumed();
5065 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5066 // on a new connection, if the connection was previously known to be good.
5067 // This can happen when a server reboots without saying goodbye, or when
5068 // we're behind a NAT that masked the RST.
5069 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
5070 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5071 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5072 MockRead reads
[] = {
5073 CreateMockRead(*resp
),
5074 CreateMockRead(*body
),
5075 MockRead(ASYNC
, ERR_IO_PENDING
),
5076 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
5079 MockRead reads2
[] = {
5080 CreateMockRead(*resp
),
5081 CreateMockRead(*body
),
5082 MockRead(ASYNC
, 0, 0) // EOF
5085 // This test has a couple of variants.
5087 // Induce the RST while waiting for our transaction to send.
5088 VARIANT_RST_DURING_SEND_COMPLETION
,
5089 // Induce the RST while waiting for our transaction to read.
5090 // In this case, the send completed - everything copied into the SNDBUF.
5091 VARIANT_RST_DURING_READ_COMPLETION
5094 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
5095 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
5097 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
5099 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
5101 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5102 BoundNetLog(), GetParam(), NULL
);
5103 helper
.AddData(&data1
);
5104 helper
.AddData(&data2
);
5105 helper
.RunPreTestSetup();
5107 for (int i
= 0; i
< 2; ++i
) {
5108 scoped_ptr
<HttpNetworkTransaction
> trans(
5109 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5111 TestCompletionCallback callback
;
5112 int rv
= trans
->Start(
5113 &helper
.request(), callback
.callback(), BoundNetLog());
5114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5115 // On the second transaction, we trigger the RST.
5117 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
5118 // Writes to the socket complete asynchronously on SPDY by running
5119 // through the message loop. Complete the write here.
5120 base::RunLoop().RunUntilIdle();
5123 // Now schedule the ERR_CONNECTION_RESET.
5124 EXPECT_EQ(3u, data1
.read_index());
5125 data1
.CompleteRead();
5126 EXPECT_EQ(4u, data1
.read_index());
5128 rv
= callback
.WaitForResult();
5131 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5132 ASSERT_TRUE(response
!= NULL
);
5133 EXPECT_TRUE(response
->headers
.get() != NULL
);
5134 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5135 std::string response_data
;
5136 rv
= ReadTransaction(trans
.get(), &response_data
);
5138 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5139 EXPECT_EQ("hello!", response_data
);
5142 helper
.VerifyDataConsumed();
5146 // Test that turning SPDY on and off works properly.
5147 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
5148 HttpStreamFactory::set_spdy_enabled(true);
5149 scoped_ptr
<SpdyFrame
> req(
5150 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5151 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
5153 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5154 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5155 MockRead spdy_reads
[] = {
5156 CreateMockRead(*resp
),
5157 CreateMockRead(*body
),
5158 MockRead(ASYNC
, 0, 0) // EOF
5161 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
5162 spdy_writes
, arraysize(spdy_writes
));
5163 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5164 BoundNetLog(), GetParam(), NULL
);
5165 helper
.RunToCompletion(&data
);
5166 TransactionHelperResult out
= helper
.output();
5167 EXPECT_EQ(OK
, out
.rv
);
5168 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5169 EXPECT_EQ("hello!", out
.response_data
);
5171 net::HttpStreamFactory::set_spdy_enabled(false);
5172 MockRead http_reads
[] = {
5173 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5174 MockRead("hello from http"),
5175 MockRead(SYNCHRONOUS
, OK
),
5177 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
5178 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
5179 BoundNetLog(), GetParam(), NULL
);
5180 helper2
.SetSpdyDisabled();
5181 helper2
.RunToCompletion(&data2
);
5182 TransactionHelperResult out2
= helper2
.output();
5183 EXPECT_EQ(OK
, out2
.rv
);
5184 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
5185 EXPECT_EQ("hello from http", out2
.response_data
);
5187 net::HttpStreamFactory::set_spdy_enabled(true);
5190 // Tests that Basic authentication works over SPDY
5191 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
5192 net::HttpStreamFactory::set_spdy_enabled(true);
5194 // The first request will be a bare GET, the second request will be a
5195 // GET with an Authorization header.
5196 scoped_ptr
<SpdyFrame
> req_get(
5197 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5198 const char* const kExtraAuthorizationHeaders
[] = {
5199 "authorization", "Basic Zm9vOmJhcg=="
5201 scoped_ptr
<SpdyFrame
> req_get_authorization(
5202 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
5203 arraysize(kExtraAuthorizationHeaders
) / 2,
5204 false, 3, LOWEST
, true));
5205 MockWrite spdy_writes
[] = {
5206 CreateMockWrite(*req_get
, 1),
5207 CreateMockWrite(*req_get_authorization
, 4),
5210 // The first response is a 401 authentication challenge, and the second
5211 // response will be a 200 response since the second request includes a valid
5212 // Authorization header.
5213 const char* const kExtraAuthenticationHeaders
[] = {
5215 "Basic realm=\"MyRealm\""
5217 scoped_ptr
<SpdyFrame
> resp_authentication(
5218 spdy_util_
.ConstructSpdySynReplyError(
5219 "401 Authentication Required",
5220 kExtraAuthenticationHeaders
,
5221 arraysize(kExtraAuthenticationHeaders
) / 2,
5223 scoped_ptr
<SpdyFrame
> body_authentication(
5224 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5225 scoped_ptr
<SpdyFrame
> resp_data(
5226 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5227 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5228 MockRead spdy_reads
[] = {
5229 CreateMockRead(*resp_authentication
, 2),
5230 CreateMockRead(*body_authentication
, 3),
5231 CreateMockRead(*resp_data
, 5),
5232 CreateMockRead(*body_data
, 6),
5233 MockRead(ASYNC
, 0, 7),
5236 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5237 spdy_writes
, arraysize(spdy_writes
));
5238 HttpRequestInfo
request(CreateGetRequest());
5239 BoundNetLog net_log
;
5240 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5241 net_log
, GetParam(), NULL
);
5243 helper
.RunPreTestSetup();
5244 helper
.AddData(&data
);
5245 HttpNetworkTransaction
* trans
= helper
.trans();
5246 TestCompletionCallback callback
;
5247 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5248 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5249 const int rv_start_complete
= callback
.WaitForResult();
5250 EXPECT_EQ(OK
, rv_start_complete
);
5252 // Make sure the response has an auth challenge.
5253 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5254 ASSERT_TRUE(response_start
!= NULL
);
5255 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5256 EXPECT_EQ(401, response_start
->headers
->response_code());
5257 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5258 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5259 ASSERT_TRUE(auth_challenge
!= NULL
);
5260 EXPECT_FALSE(auth_challenge
->is_proxy
);
5261 EXPECT_EQ("basic", auth_challenge
->scheme
);
5262 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5264 // Restart with a username/password.
5265 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5266 base::ASCIIToUTF16("bar"));
5267 TestCompletionCallback callback_restart
;
5268 const int rv_restart
= trans
->RestartWithAuth(
5269 credentials
, callback_restart
.callback());
5270 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5271 const int rv_restart_complete
= callback_restart
.WaitForResult();
5272 EXPECT_EQ(OK
, rv_restart_complete
);
5273 // TODO(cbentzel): This is actually the same response object as before, but
5274 // data has changed.
5275 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5276 ASSERT_TRUE(response_restart
!= NULL
);
5277 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5278 EXPECT_EQ(200, response_restart
->headers
->response_code());
5279 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5282 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5283 scoped_ptr
<SpdyFrame
> stream1_syn(
5284 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5285 scoped_ptr
<SpdyFrame
> stream1_body(
5286 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5287 MockWrite writes
[] = {
5288 CreateMockWrite(*stream1_syn
, 1),
5291 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5292 spdy_util_
.AddUrlToHeaderBlock(
5293 "http://www.google.com/foo.dat", initial_headers
.get());
5294 scoped_ptr
<SpdyFrame
> stream2_syn(
5295 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5297 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5298 (*late_headers
)["hello"] = "bye";
5299 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5300 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5301 scoped_ptr
<SpdyFrame
> stream2_headers(
5302 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5310 scoped_ptr
<SpdyFrame
>
5311 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5312 const char kPushedData
[] = "pushed";
5313 scoped_ptr
<SpdyFrame
> stream2_body(
5314 spdy_util_
.ConstructSpdyBodyFrame(
5315 2, kPushedData
, strlen(kPushedData
), true));
5316 MockRead reads
[] = {
5317 CreateMockRead(*stream1_reply
, 2),
5318 CreateMockRead(*stream2_syn
, 3),
5319 CreateMockRead(*stream2_headers
, 4),
5320 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5321 CreateMockRead(*stream2_body
, 5),
5322 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5325 HttpResponseInfo response
;
5326 HttpResponseInfo response2
;
5327 std::string
expected_push_result("pushed");
5328 OrderedSocketData
data(reads
, arraysize(reads
),
5329 writes
, arraysize(writes
));
5330 RunServerPushTest(&data
,
5333 expected_push_result
);
5335 // Verify the SYN_REPLY.
5336 EXPECT_TRUE(response
.headers
.get() != NULL
);
5337 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5339 // Verify the pushed stream.
5340 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5341 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5344 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5345 // We push a stream and attempt to claim it before the headers come down.
5346 scoped_ptr
<SpdyFrame
> stream1_syn(
5347 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5348 scoped_ptr
<SpdyFrame
> stream1_body(
5349 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5350 MockWrite writes
[] = {
5351 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5354 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5355 spdy_util_
.AddUrlToHeaderBlock(
5356 "http://www.google.com/foo.dat", initial_headers
.get());
5357 scoped_ptr
<SpdyFrame
> stream2_syn(
5358 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5360 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5361 (*late_headers
)["hello"] = "bye";
5362 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5363 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5364 scoped_ptr
<SpdyFrame
> stream2_headers(
5365 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5373 scoped_ptr
<SpdyFrame
>
5374 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5375 const char kPushedData
[] = "pushed";
5376 scoped_ptr
<SpdyFrame
> stream2_body(
5377 spdy_util_
.ConstructSpdyBodyFrame(
5378 2, kPushedData
, strlen(kPushedData
), true));
5379 MockRead reads
[] = {
5380 CreateMockRead(*stream1_reply
, 1),
5381 CreateMockRead(*stream2_syn
, 2),
5382 CreateMockRead(*stream1_body
, 3),
5383 CreateMockRead(*stream2_headers
, 4),
5384 CreateMockRead(*stream2_body
, 5),
5385 MockRead(ASYNC
, 0, 6), // EOF
5388 HttpResponseInfo response
;
5389 HttpResponseInfo response2
;
5390 std::string
expected_push_result("pushed");
5391 DeterministicSocketData
data(reads
, arraysize(reads
),
5392 writes
, arraysize(writes
));
5394 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5395 BoundNetLog(), GetParam(), NULL
);
5396 helper
.SetDeterministic();
5397 helper
.AddDeterministicData(&data
);
5398 helper
.RunPreTestSetup();
5400 HttpNetworkTransaction
* trans
= helper
.trans();
5402 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5403 // and the body of the primary stream, but before we've received the HEADERS
5404 // for the pushed stream.
5407 // Start the transaction.
5408 TestCompletionCallback callback
;
5409 int rv
= trans
->Start(
5410 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5411 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5413 rv
= callback
.WaitForResult();
5416 // Request the pushed path. At this point, we've received the push, but the
5417 // headers are not yet complete.
5418 scoped_ptr
<HttpNetworkTransaction
> trans2(
5419 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5421 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5424 base::RunLoop().RunUntilIdle();
5426 // Read the server push body.
5427 std::string result2
;
5428 ReadResult(trans2
.get(), &data
, &result2
);
5429 // Read the response body.
5431 ReadResult(trans
, &data
, &result
);
5433 // Verify that the received push data is same as the expected push data.
5434 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5435 << "Received data: "
5437 << "||||| Expected data: "
5438 << expected_push_result
;
5440 // Verify the SYN_REPLY.
5441 // Copy the response info, because trans goes away.
5442 response
= *trans
->GetResponseInfo();
5443 response2
= *trans2
->GetResponseInfo();
5445 VerifyStreamsClosed(helper
);
5447 // Verify the SYN_REPLY.
5448 EXPECT_TRUE(response
.headers
.get() != NULL
);
5449 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5451 // Verify the pushed stream.
5452 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5453 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5455 // Read the final EOF (which will close the session)
5458 // Verify that we consumed all test data.
5459 EXPECT_TRUE(data
.at_read_eof());
5460 EXPECT_TRUE(data
.at_write_eof());
5463 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5464 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5465 // We push a stream and attempt to claim it before the headers come down.
5466 scoped_ptr
<SpdyFrame
> stream1_syn(
5467 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5468 scoped_ptr
<SpdyFrame
> stream1_body(
5469 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5470 MockWrite writes
[] = {
5471 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5474 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5475 if (spdy_util_
.spdy_version() < SPDY4
) {
5476 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5477 (*initial_headers
)["alpha"] = "beta";
5479 spdy_util_
.AddUrlToHeaderBlock(
5480 "http://www.google.com/foo.dat", initial_headers
.get());
5481 scoped_ptr
<SpdyFrame
> stream2_syn(
5482 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5484 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5485 (*middle_headers
)["hello"] = "bye";
5486 scoped_ptr
<SpdyFrame
> stream2_headers1(
5487 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5495 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5496 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5497 if (spdy_util_
.spdy_version() < SPDY4
) {
5498 // SPDY4/HTTP2 eliminates use of the :version header.
5499 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5501 scoped_ptr
<SpdyFrame
> stream2_headers2(
5502 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5510 scoped_ptr
<SpdyFrame
>
5511 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5512 const char kPushedData
[] = "pushed";
5513 scoped_ptr
<SpdyFrame
> stream2_body(
5514 spdy_util_
.ConstructSpdyBodyFrame(
5515 2, kPushedData
, strlen(kPushedData
), true));
5516 MockRead reads
[] = {
5517 CreateMockRead(*stream1_reply
, 1),
5518 CreateMockRead(*stream2_syn
, 2),
5519 CreateMockRead(*stream1_body
, 3),
5520 CreateMockRead(*stream2_headers1
, 4),
5521 CreateMockRead(*stream2_headers2
, 5),
5522 CreateMockRead(*stream2_body
, 6),
5523 MockRead(ASYNC
, 0, 7), // EOF
5526 HttpResponseInfo response
;
5527 HttpResponseInfo response2
;
5528 std::string
expected_push_result("pushed");
5529 DeterministicSocketData
data(reads
, arraysize(reads
),
5530 writes
, arraysize(writes
));
5532 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5533 BoundNetLog(), GetParam(), NULL
);
5534 helper
.SetDeterministic();
5535 helper
.AddDeterministicData(&data
);
5536 helper
.RunPreTestSetup();
5538 HttpNetworkTransaction
* trans
= helper
.trans();
5540 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5541 // the first HEADERS frame, and the body of the primary stream, but before
5542 // we've received the final HEADERS for the pushed stream.
5545 // Start the transaction.
5546 TestCompletionCallback callback
;
5547 int rv
= trans
->Start(
5548 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5549 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5551 rv
= callback
.WaitForResult();
5554 // Request the pushed path. At this point, we've received the push, but the
5555 // headers are not yet complete.
5556 scoped_ptr
<HttpNetworkTransaction
> trans2(
5557 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5559 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5560 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5562 base::RunLoop().RunUntilIdle();
5564 // Read the server push body.
5565 std::string result2
;
5566 ReadResult(trans2
.get(), &data
, &result2
);
5567 // Read the response body.
5569 ReadResult(trans
, &data
, &result
);
5571 // Verify that the received push data is same as the expected push data.
5572 EXPECT_EQ(expected_push_result
, result2
);
5574 // Verify the SYN_REPLY.
5575 // Copy the response info, because trans goes away.
5576 response
= *trans
->GetResponseInfo();
5577 response2
= *trans2
->GetResponseInfo();
5579 VerifyStreamsClosed(helper
);
5581 // Verify the SYN_REPLY.
5582 EXPECT_TRUE(response
.headers
.get() != NULL
);
5583 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5585 // Verify the pushed stream.
5586 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5587 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5589 // Verify we got all the headers from all header blocks.
5590 if (spdy_util_
.spdy_version() < SPDY4
)
5591 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5592 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5593 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5595 // Read the final EOF (which will close the session)
5598 // Verify that we consumed all test data.
5599 EXPECT_TRUE(data
.at_read_eof());
5600 EXPECT_TRUE(data
.at_write_eof());
5603 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5604 // We push a stream and attempt to claim it before the headers come down.
5605 scoped_ptr
<SpdyFrame
> stream1_syn(
5606 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5607 scoped_ptr
<SpdyFrame
> stream1_body(
5608 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5609 MockWrite writes
[] = {
5610 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5613 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5614 spdy_util_
.AddUrlToHeaderBlock(
5615 "http://www.google.com/foo.dat", initial_headers
.get());
5616 scoped_ptr
<SpdyFrame
> stream2_syn(
5617 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5619 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5620 (*middle_headers
)["hello"] = "bye";
5621 scoped_ptr
<SpdyFrame
> stream2_headers1(
5622 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5630 scoped_ptr
<SpdyFrame
>
5631 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5632 const char kPushedData
[] = "pushed";
5633 scoped_ptr
<SpdyFrame
> stream2_body(
5634 spdy_util_
.ConstructSpdyBodyFrame(
5635 2, kPushedData
, strlen(kPushedData
), true));
5636 MockRead reads
[] = {
5637 CreateMockRead(*stream1_reply
, 1),
5638 CreateMockRead(*stream2_syn
, 2),
5639 CreateMockRead(*stream1_body
, 3),
5640 CreateMockRead(*stream2_headers1
, 4),
5641 CreateMockRead(*stream2_body
, 5),
5642 MockRead(ASYNC
, 0, 6), // EOF
5645 DeterministicSocketData
data(reads
, arraysize(reads
),
5646 writes
, arraysize(writes
));
5648 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5649 BoundNetLog(), GetParam(), NULL
);
5650 helper
.SetDeterministic();
5651 helper
.AddDeterministicData(&data
);
5652 helper
.RunPreTestSetup();
5654 HttpNetworkTransaction
* trans
= helper
.trans();
5656 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5657 // the first HEADERS frame, and the body of the primary stream, but before
5658 // we've received the final HEADERS for the pushed stream.
5661 // Start the transaction.
5662 TestCompletionCallback callback
;
5663 int rv
= trans
->Start(
5664 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5665 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5667 rv
= callback
.WaitForResult();
5670 // Request the pushed path. At this point, we've received the push, but the
5671 // headers are not yet complete.
5672 scoped_ptr
<HttpNetworkTransaction
> trans2(
5673 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5675 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5676 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5678 base::RunLoop().RunUntilIdle();
5680 // Read the server push body.
5681 std::string result2
;
5682 ReadResult(trans2
.get(), &data
, &result2
);
5683 // Read the response body.
5685 ReadResult(trans
, &data
, &result
);
5686 EXPECT_EQ("hello!", result
);
5688 // Verify that we haven't received any push data.
5689 EXPECT_EQ("", result2
);
5691 // Verify the SYN_REPLY.
5692 // Copy the response info, because trans goes away.
5693 HttpResponseInfo response
= *trans
->GetResponseInfo();
5694 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5696 VerifyStreamsClosed(helper
);
5698 // Verify the SYN_REPLY.
5699 EXPECT_TRUE(response
.headers
.get() != NULL
);
5700 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5702 // Read the final EOF (which will close the session).
5705 // Verify that we consumed all test data.
5706 EXPECT_TRUE(data
.at_read_eof());
5707 EXPECT_TRUE(data
.at_write_eof());
5710 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5711 scoped_ptr
<SpdyFrame
> req(
5712 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5713 scoped_ptr
<SpdyFrame
> rst(
5714 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5715 MockWrite writes
[] = {
5716 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5719 scoped_ptr
<SpdyFrame
> stream1_reply(
5720 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5722 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5723 (*late_headers
)["hello"] = "bye";
5724 scoped_ptr
<SpdyFrame
> stream1_headers(
5725 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5732 scoped_ptr
<SpdyFrame
> stream1_body(
5733 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5734 MockRead reads
[] = {
5735 CreateMockRead(*stream1_reply
),
5736 CreateMockRead(*stream1_headers
),
5737 CreateMockRead(*stream1_body
),
5738 MockRead(ASYNC
, 0, 0) // EOF
5741 DelayedSocketData
data(1, reads
, arraysize(reads
),
5742 writes
, arraysize(writes
));
5743 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5744 BoundNetLog(), GetParam(), NULL
);
5745 helper
.RunToCompletion(&data
);
5746 TransactionHelperResult out
= helper
.output();
5747 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5750 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5751 scoped_ptr
<SpdyFrame
> req(
5752 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5753 scoped_ptr
<SpdyFrame
> rst(
5754 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5755 MockWrite writes
[] = {
5756 CreateMockWrite(*req
),
5757 CreateMockWrite(*rst
),
5760 scoped_ptr
<SpdyFrame
> stream1_reply(
5761 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5763 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5764 (*late_headers
)["hello"] = "bye";
5765 scoped_ptr
<SpdyFrame
> stream1_headers(
5766 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5773 scoped_ptr
<SpdyFrame
> stream1_body(
5774 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5775 scoped_ptr
<SpdyFrame
> stream1_body2(
5776 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5777 MockRead reads
[] = {
5778 CreateMockRead(*stream1_reply
),
5779 CreateMockRead(*stream1_body
),
5780 CreateMockRead(*stream1_headers
),
5781 CreateMockRead(*stream1_body2
),
5782 MockRead(ASYNC
, 0, 0) // EOF
5785 DelayedSocketData
data(1, reads
, arraysize(reads
),
5786 writes
, arraysize(writes
));
5787 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5788 BoundNetLog(), GetParam(), NULL
);
5789 helper
.RunToCompletion(&data
);
5790 TransactionHelperResult out
= helper
.output();
5791 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5794 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5795 // In this test we want to verify that we can't accidentally push content
5796 // which can't be pushed by this content server.
5797 // This test assumes that:
5798 // - if we're requesting http://www.foo.com/barbaz
5799 // - the browser has made a connection to "www.foo.com".
5801 // A list of the URL to fetch, followed by the URL being pushed.
5802 static const char* const kTestCases
[] = {
5803 "http://www.google.com/foo.html",
5804 "http://www.google.com:81/foo.js", // Bad port
5806 "http://www.google.com/foo.html",
5807 "https://www.google.com/foo.js", // Bad protocol
5809 "http://www.google.com/foo.html",
5810 "ftp://www.google.com/foo.js", // Invalid Protocol
5812 "http://www.google.com/foo.html",
5813 "http://blat.www.google.com/foo.js", // Cross subdomain
5815 "http://www.google.com/foo.html",
5816 "http://www.foo.com/foo.js", // Cross domain
5819 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5820 const char* url_to_fetch
= kTestCases
[index
];
5821 const char* url_to_push
= kTestCases
[index
+ 1];
5823 scoped_ptr
<SpdyFrame
> stream1_syn(
5824 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5825 scoped_ptr
<SpdyFrame
> stream1_body(
5826 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5827 scoped_ptr
<SpdyFrame
> push_rst(
5828 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5829 MockWrite writes
[] = {
5830 CreateMockWrite(*stream1_syn
, 1),
5831 CreateMockWrite(*push_rst
, 4),
5834 scoped_ptr
<SpdyFrame
>
5835 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5836 scoped_ptr
<SpdyFrame
>
5837 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5842 const char kPushedData
[] = "pushed";
5843 scoped_ptr
<SpdyFrame
> stream2_body(
5844 spdy_util_
.ConstructSpdyBodyFrame(
5845 2, kPushedData
, strlen(kPushedData
), true));
5846 scoped_ptr
<SpdyFrame
> rst(
5847 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5849 MockRead reads
[] = {
5850 CreateMockRead(*stream1_reply
, 2),
5851 CreateMockRead(*stream2_syn
, 3),
5852 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5853 CreateMockRead(*stream2_body
, 6),
5854 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5857 HttpResponseInfo response
;
5858 OrderedSocketData
data(reads
, arraysize(reads
),
5859 writes
, arraysize(writes
));
5861 HttpRequestInfo request
;
5862 request
.method
= "GET";
5863 request
.url
= GURL(url_to_fetch
);
5864 request
.load_flags
= 0;
5866 // Enable cross-origin push. Since we are not using a proxy, this should
5867 // not actually enable cross-origin SPDY push.
5868 scoped_ptr
<SpdySessionDependencies
> session_deps(
5869 CreateSpdySessionDependencies(GetParam()));
5870 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5871 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5872 BoundNetLog(), GetParam(),
5873 session_deps
.release());
5874 helper
.RunPreTestSetup();
5875 helper
.AddData(&data
);
5877 HttpNetworkTransaction
* trans
= helper
.trans();
5879 // Start the transaction with basic parameters.
5880 TestCompletionCallback callback
;
5882 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5883 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5884 rv
= callback
.WaitForResult();
5886 // Read the response body.
5888 ReadResult(trans
, &data
, &result
);
5890 // Verify that we consumed all test data.
5891 EXPECT_TRUE(data
.at_read_eof());
5892 EXPECT_TRUE(data
.at_write_eof());
5894 // Verify the SYN_REPLY.
5895 // Copy the response info, because trans goes away.
5896 response
= *trans
->GetResponseInfo();
5898 VerifyStreamsClosed(helper
);
5900 // Verify the SYN_REPLY.
5901 EXPECT_TRUE(response
.headers
.get() != NULL
);
5902 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5906 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5907 // Construct the request.
5908 scoped_ptr
<SpdyFrame
> req(
5909 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5910 scoped_ptr
<SpdyFrame
> req2(
5911 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5912 MockWrite writes
[] = {
5913 CreateMockWrite(*req
, 1),
5914 CreateMockWrite(*req2
, 3),
5917 scoped_ptr
<SpdyFrame
> refused(
5918 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5919 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5920 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5921 MockRead reads
[] = {
5922 CreateMockRead(*refused
, 2),
5923 CreateMockRead(*resp
, 4),
5924 CreateMockRead(*body
, 5),
5925 MockRead(ASYNC
, 0, 6) // EOF
5928 OrderedSocketData
data(reads
, arraysize(reads
),
5929 writes
, arraysize(writes
));
5930 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5931 BoundNetLog(), GetParam(), NULL
);
5933 helper
.RunPreTestSetup();
5934 helper
.AddData(&data
);
5936 HttpNetworkTransaction
* trans
= helper
.trans();
5938 // Start the transaction with basic parameters.
5939 TestCompletionCallback callback
;
5940 int rv
= trans
->Start(
5941 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5943 rv
= callback
.WaitForResult();
5946 // Verify that we consumed all test data.
5947 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5948 << data
.read_count()
5950 << data
.read_index();
5951 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5952 << data
.write_count()
5954 << data
.write_index();
5956 // Verify the SYN_REPLY.
5957 HttpResponseInfo response
= *trans
->GetResponseInfo();
5958 EXPECT_TRUE(response
.headers
.get() != NULL
);
5959 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5962 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5963 // This first request will start to establish the SpdySession.
5964 // Then we will start the second (MEDIUM priority) and then third
5965 // (HIGHEST priority) request in such a way that the third will actually
5966 // start before the second, causing the second to be numbered differently
5967 // than the order they were created.
5968 scoped_ptr
<SpdyFrame
> req1(
5969 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5970 scoped_ptr
<SpdyFrame
> req2(
5971 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5972 scoped_ptr
<SpdyFrame
> req3(
5973 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5974 MockWrite writes
[] = {
5975 CreateMockWrite(*req1
, 0),
5976 CreateMockWrite(*req2
, 3),
5977 CreateMockWrite(*req3
, 4),
5980 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5981 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5982 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5983 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5984 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5985 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5986 MockRead reads
[] = {
5987 CreateMockRead(*resp1
, 1),
5988 CreateMockRead(*body1
, 2),
5989 CreateMockRead(*resp2
, 5),
5990 CreateMockRead(*body2
, 6),
5991 CreateMockRead(*resp3
, 7),
5992 CreateMockRead(*body3
, 8),
5993 MockRead(ASYNC
, 0, 9) // EOF
5996 DeterministicSocketData
data(reads
, arraysize(reads
),
5997 writes
, arraysize(writes
));
5998 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5999 BoundNetLog(), GetParam(), NULL
);
6000 helper
.SetDeterministic();
6001 helper
.RunPreTestSetup();
6002 helper
.AddDeterministicData(&data
);
6004 // Start the first transaction to set up the SpdySession
6005 HttpNetworkTransaction
* trans
= helper
.trans();
6006 TestCompletionCallback callback
;
6007 HttpRequestInfo info1
= CreateGetRequest();
6008 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
6009 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6011 // Run the message loop, but do not allow the write to complete.
6012 // This leaves the SpdySession with a write pending, which prevents
6013 // SpdySession from attempting subsequent writes until this write completes.
6014 base::RunLoop().RunUntilIdle();
6016 // Now, start both new transactions
6017 HttpRequestInfo info2
= CreateGetRequest();
6018 TestCompletionCallback callback2
;
6019 scoped_ptr
<HttpNetworkTransaction
> trans2(
6020 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
6021 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
6022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6023 base::RunLoop().RunUntilIdle();
6025 HttpRequestInfo info3
= CreateGetRequest();
6026 TestCompletionCallback callback3
;
6027 scoped_ptr
<HttpNetworkTransaction
> trans3(
6028 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
6029 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
6030 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6031 base::RunLoop().RunUntilIdle();
6033 // We now have two SYN_STREAM frames queued up which will be
6034 // dequeued only once the first write completes, which we
6035 // now allow to happen.
6037 EXPECT_EQ(OK
, callback
.WaitForResult());
6039 // And now we can allow everything else to run to completion.
6042 EXPECT_EQ(OK
, callback2
.WaitForResult());
6043 EXPECT_EQ(OK
, callback3
.WaitForResult());
6045 helper
.VerifyDataConsumed();
6048 // The tests below are only for SPDY/3 and above.
6050 // Test that sent data frames and received WINDOW_UPDATE frames change
6051 // the send_window_size_ correctly.
6053 // WINDOW_UPDATE is different than most other frames in that it can arrive
6054 // while the client is still sending the request body. In order to enforce
6055 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
6056 // socket data provider, so that initial read that is done as soon as the
6057 // stream is created, succeeds and schedules another read. This way reads
6058 // and writes are interleaved; after doing a full frame write, SpdyStream
6059 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
6060 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
6061 // since request has not been completely written, therefore we feed
6062 // enough number of WINDOW_UPDATEs to finish the first read and cause a
6063 // write, leading to a complete write of request body; after that we send
6064 // a reply with a body, to cause a graceful shutdown.
6066 // TODO(agayev): develop a socket data provider where both, reads and
6067 // writes are ordered so that writing tests like these are easy and rewrite
6068 // all these tests using it. Right now we are working around the
6069 // limitations as described above and it's not deterministic, tests may
6070 // fail under specific circumstances.
6071 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
6072 static int kFrameCount
= 2;
6073 scoped_ptr
<std::string
> content(
6074 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6075 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6076 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6077 scoped_ptr
<SpdyFrame
> body(
6078 spdy_util_
.ConstructSpdyBodyFrame(
6079 1, content
->c_str(), content
->size(), false));
6080 scoped_ptr
<SpdyFrame
> body_end(
6081 spdy_util_
.ConstructSpdyBodyFrame(
6082 1, content
->c_str(), content
->size(), true));
6084 MockWrite writes
[] = {
6085 CreateMockWrite(*req
, 0),
6086 CreateMockWrite(*body
, 1),
6087 CreateMockWrite(*body_end
, 2),
6090 static const int32 kDeltaWindowSize
= 0xff;
6091 static const int kDeltaCount
= 4;
6092 scoped_ptr
<SpdyFrame
> window_update(
6093 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6094 scoped_ptr
<SpdyFrame
> window_update_dummy(
6095 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
6096 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6097 MockRead reads
[] = {
6098 CreateMockRead(*window_update_dummy
, 3),
6099 CreateMockRead(*window_update_dummy
, 4),
6100 CreateMockRead(*window_update_dummy
, 5),
6101 CreateMockRead(*window_update
, 6), // Four updates, therefore window
6102 CreateMockRead(*window_update
, 7), // size should increase by
6103 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
6104 CreateMockRead(*window_update
, 9),
6105 CreateMockRead(*resp
, 10),
6106 CreateMockRead(*body_end
, 11),
6107 MockRead(ASYNC
, 0, 0, 12) // EOF
6110 DeterministicSocketData
data(reads
, arraysize(reads
),
6111 writes
, arraysize(writes
));
6113 ScopedVector
<UploadElementReader
> element_readers
;
6114 for (int i
= 0; i
< kFrameCount
; ++i
) {
6115 element_readers
.push_back(
6116 new UploadBytesElementReader(content
->c_str(), content
->size()));
6118 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6120 // Setup the request
6121 HttpRequestInfo request
;
6122 request
.method
= "POST";
6123 request
.url
= GURL(kDefaultURL
);
6124 request
.upload_data_stream
= &upload_data_stream
;
6126 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6127 BoundNetLog(), GetParam(), NULL
);
6128 helper
.SetDeterministic();
6129 helper
.AddDeterministicData(&data
);
6130 helper
.RunPreTestSetup();
6132 HttpNetworkTransaction
* trans
= helper
.trans();
6134 TestCompletionCallback callback
;
6135 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6137 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6141 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6142 ASSERT_TRUE(stream
!= NULL
);
6143 ASSERT_TRUE(stream
->stream() != NULL
);
6145 static_cast<int>(SpdySession::GetInitialWindowSize(GetParam().protocol
)) +
6146 kDeltaWindowSize
* kDeltaCount
- kMaxSpdyFrameChunkSize
* kFrameCount
,
6147 stream
->stream()->send_window_size());
6151 rv
= callback
.WaitForResult();
6154 helper
.VerifyDataConsumed();
6157 // Test that received data frames and sent WINDOW_UPDATE frames change
6158 // the recv_window_size_ correctly.
6159 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
6160 const int32 initial_window_size
=
6161 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6162 // Amount of body required to trigger a sent window update.
6163 const size_t kTargetSize
= initial_window_size
/ 2 + 1;
6165 scoped_ptr
<SpdyFrame
> req(
6166 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6167 scoped_ptr
<SpdyFrame
> session_window_update(
6168 spdy_util_
.ConstructSpdyWindowUpdate(0, kTargetSize
));
6169 scoped_ptr
<SpdyFrame
> window_update(
6170 spdy_util_
.ConstructSpdyWindowUpdate(1, kTargetSize
));
6172 std::vector
<MockWrite
> writes
;
6173 writes
.push_back(CreateMockWrite(*req
));
6174 if (GetParam().protocol
>= kProtoSPDY31
)
6175 writes
.push_back(CreateMockWrite(*session_window_update
));
6176 writes
.push_back(CreateMockWrite(*window_update
));
6178 std::vector
<MockRead
> reads
;
6179 scoped_ptr
<SpdyFrame
> resp(
6180 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6181 reads
.push_back(CreateMockRead(*resp
));
6183 ScopedVector
<SpdyFrame
> body_frames
;
6184 const std::string
body_data(4096, 'x');
6185 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
6186 size_t frame_size
= std::min(remaining
, body_data
.size());
6187 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
6188 1, body_data
.data(), frame_size
, false));
6189 reads
.push_back(CreateMockRead(*body_frames
.back()));
6190 remaining
-= frame_size
;
6192 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
6194 DelayedSocketData
data(1, vector_as_array(&reads
), reads
.size(),
6195 vector_as_array(&writes
), writes
.size());
6197 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
6198 BoundNetLog(), GetParam(), NULL
);
6199 helper
.AddData(&data
);
6200 helper
.RunPreTestSetup();
6201 HttpNetworkTransaction
* trans
= helper
.trans();
6203 TestCompletionCallback callback
;
6204 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6206 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6207 rv
= callback
.WaitForResult();
6210 SpdyHttpStream
* stream
=
6211 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6212 ASSERT_TRUE(stream
!= NULL
);
6213 ASSERT_TRUE(stream
->stream() != NULL
);
6215 // All data has been read, but not consumed. The window reflects this.
6216 EXPECT_EQ(static_cast<int>(initial_window_size
- kTargetSize
),
6217 stream
->stream()->recv_window_size());
6219 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6220 ASSERT_TRUE(response
!= NULL
);
6221 ASSERT_TRUE(response
->headers
.get() != NULL
);
6222 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
6223 EXPECT_TRUE(response
->was_fetched_via_spdy
);
6225 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6226 // size increased to default.
6227 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kTargetSize
));
6228 EXPECT_EQ(static_cast<int>(kTargetSize
),
6229 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
6230 EXPECT_EQ(static_cast<int>(initial_window_size
),
6231 stream
->stream()->recv_window_size());
6232 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6234 // Allow scheduled WINDOW_UPDATE frames to write.
6235 base::RunLoop().RunUntilIdle();
6236 helper
.VerifyDataConsumed();
6239 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6240 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6241 // Number of full frames we hope to write (but will not, used to
6242 // set content-length header correctly)
6243 static int kFrameCount
= 3;
6245 scoped_ptr
<std::string
> content(
6246 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6247 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6248 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6249 scoped_ptr
<SpdyFrame
> body(
6250 spdy_util_
.ConstructSpdyBodyFrame(
6251 1, content
->c_str(), content
->size(), false));
6252 scoped_ptr
<SpdyFrame
> rst(
6253 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6255 // We're not going to write a data frame with FIN, we'll receive a bad
6256 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6257 MockWrite writes
[] = {
6258 CreateMockWrite(*req
, 0),
6259 CreateMockWrite(*body
, 2),
6260 CreateMockWrite(*rst
, 3),
6263 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6264 scoped_ptr
<SpdyFrame
> window_update(
6265 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6266 MockRead reads
[] = {
6267 CreateMockRead(*window_update
, 1),
6268 MockRead(ASYNC
, 0, 4) // EOF
6271 DeterministicSocketData
data(reads
, arraysize(reads
),
6272 writes
, arraysize(writes
));
6274 ScopedVector
<UploadElementReader
> element_readers
;
6275 for (int i
= 0; i
< kFrameCount
; ++i
) {
6276 element_readers
.push_back(
6277 new UploadBytesElementReader(content
->c_str(), content
->size()));
6279 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6281 // Setup the request
6282 HttpRequestInfo request
;
6283 request
.method
= "POST";
6284 request
.url
= GURL("http://www.google.com/");
6285 request
.upload_data_stream
= &upload_data_stream
;
6287 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6288 BoundNetLog(), GetParam(), NULL
);
6289 helper
.SetDeterministic();
6290 helper
.RunPreTestSetup();
6291 helper
.AddDeterministicData(&data
);
6292 HttpNetworkTransaction
* trans
= helper
.trans();
6294 TestCompletionCallback callback
;
6295 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6296 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6299 ASSERT_TRUE(callback
.have_result());
6300 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6301 helper
.VerifyDataConsumed();
6304 // Test that after hitting a send window size of 0, the write process
6305 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6307 // This test constructs a POST request followed by enough data frames
6308 // containing 'a' that would make the window size 0, followed by another
6309 // data frame containing default content (which is "hello!") and this frame
6310 // also contains a FIN flag. DelayedSocketData is used to enforce all
6311 // writes go through before a read could happen. However, the last frame
6312 // ("hello!") is not supposed to go through since by the time its turn
6313 // arrives, window size is 0. At this point MessageLoop::Run() called via
6314 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6315 // which returns after performing all possible writes. We use DCHECKS to
6316 // ensure that last data frame is still there and stream has stalled.
6317 // After that, next read is artifically enforced, which causes a
6318 // WINDOW_UPDATE to be read and I/O process resumes.
6319 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6320 const int32 initial_window_size
=
6321 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6322 // Number of frames we need to send to zero out the window size: data
6323 // frames plus SYN_STREAM plus the last data frame; also we need another
6324 // data frame that we will send once the WINDOW_UPDATE is received,
6326 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6328 // Calculate last frame's size; 0 size data frame is legal.
6329 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6331 // Construct content for a data frame of maximum size.
6332 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6334 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6335 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6338 scoped_ptr
<SpdyFrame
> body1(
6339 spdy_util_
.ConstructSpdyBodyFrame(
6340 1, content
.c_str(), content
.size(), false));
6342 // Last frame to zero out the window size.
6343 scoped_ptr
<SpdyFrame
> body2(
6344 spdy_util_
.ConstructSpdyBodyFrame(
6345 1, content
.c_str(), last_frame_size
, false));
6347 // Data frame to be sent once WINDOW_UPDATE frame is received.
6348 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6350 // Fill in mock writes.
6351 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6353 writes
[i
] = CreateMockWrite(*req
);
6354 for (i
= 1; i
< num_writes
- 2; i
++)
6355 writes
[i
] = CreateMockWrite(*body1
);
6356 writes
[i
++] = CreateMockWrite(*body2
);
6357 writes
[i
] = CreateMockWrite(*body3
);
6359 // Construct read frame, give enough space to upload the rest of the
6361 scoped_ptr
<SpdyFrame
> session_window_update(
6362 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6363 scoped_ptr
<SpdyFrame
> window_update(
6364 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6365 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6366 MockRead reads
[] = {
6367 CreateMockRead(*session_window_update
),
6368 CreateMockRead(*session_window_update
),
6369 CreateMockRead(*window_update
),
6370 CreateMockRead(*window_update
),
6371 CreateMockRead(*reply
),
6372 CreateMockRead(*body2
),
6373 CreateMockRead(*body3
),
6374 MockRead(ASYNC
, 0, 0) // EOF
6377 // Skip the session window updates unless we're using SPDY/3.1 and
6379 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6380 size_t num_reads
= arraysize(reads
) - read_offset
;
6382 // Force all writes to happen before any read, last write will not
6383 // actually queue a frame, due to window size being 0.
6384 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6385 writes
.get(), num_writes
);
6387 ScopedVector
<UploadElementReader
> element_readers
;
6388 std::string
upload_data_string(initial_window_size
, 'a');
6389 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6390 element_readers
.push_back(new UploadBytesElementReader(
6391 upload_data_string
.c_str(), upload_data_string
.size()));
6392 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6394 HttpRequestInfo request
;
6395 request
.method
= "POST";
6396 request
.url
= GURL("http://www.google.com/");
6397 request
.upload_data_stream
= &upload_data_stream
;
6398 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6399 BoundNetLog(), GetParam(), NULL
);
6400 helper
.AddData(&data
);
6401 helper
.RunPreTestSetup();
6403 HttpNetworkTransaction
* trans
= helper
.trans();
6405 TestCompletionCallback callback
;
6406 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6407 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6409 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6411 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6412 ASSERT_TRUE(stream
!= NULL
);
6413 ASSERT_TRUE(stream
->stream() != NULL
);
6414 EXPECT_EQ(0, stream
->stream()->send_window_size());
6415 // All the body data should have been read.
6416 // TODO(satorux): This is because of the weirdness in reading the request
6417 // body in OnSendBodyComplete(). See crbug.com/113107.
6418 EXPECT_TRUE(upload_data_stream
.IsEOF());
6419 // But the body is not yet fully sent (kUploadData is not yet sent)
6420 // since we're send-stalled.
6421 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6423 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6424 rv
= callback
.WaitForResult();
6425 helper
.VerifyDataConsumed();
6428 // Test we correctly handle the case where the SETTINGS frame results in
6429 // unstalling the send window.
6430 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6431 const int32 initial_window_size
=
6432 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6434 // Number of frames we need to send to zero out the window size: data
6435 // frames plus SYN_STREAM plus the last data frame; also we need another
6436 // data frame that we will send once the SETTING is received, therefore +3.
6437 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6439 // Calculate last frame's size; 0 size data frame is legal.
6440 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6442 // Construct content for a data frame of maximum size.
6443 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6445 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6446 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6449 scoped_ptr
<SpdyFrame
> body1(
6450 spdy_util_
.ConstructSpdyBodyFrame(
6451 1, content
.c_str(), content
.size(), false));
6453 // Last frame to zero out the window size.
6454 scoped_ptr
<SpdyFrame
> body2(
6455 spdy_util_
.ConstructSpdyBodyFrame(
6456 1, content
.c_str(), last_frame_size
, false));
6458 // Data frame to be sent once SETTINGS frame is received.
6459 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6461 // Fill in mock reads/writes.
6462 std::vector
<MockRead
> reads
;
6463 std::vector
<MockWrite
> writes
;
6465 writes
.push_back(CreateMockWrite(*req
, i
++));
6466 while (i
< num_writes
- 2)
6467 writes
.push_back(CreateMockWrite(*body1
, i
++));
6468 writes
.push_back(CreateMockWrite(*body2
, i
++));
6470 // Construct read frame for SETTINGS that gives enough space to upload the
6471 // rest of the data.
6472 SettingsMap settings
;
6473 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6474 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
* 2);
6475 scoped_ptr
<SpdyFrame
> settings_frame_large(
6476 spdy_util_
.ConstructSpdySettings(settings
));
6478 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6480 scoped_ptr
<SpdyFrame
> session_window_update(
6481 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6482 if (GetParam().protocol
>= kProtoSPDY31
)
6483 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6485 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6486 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6488 writes
.push_back(CreateMockWrite(*body3
, i
++));
6490 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6491 reads
.push_back(CreateMockRead(*reply
, i
++));
6492 reads
.push_back(CreateMockRead(*body2
, i
++));
6493 reads
.push_back(CreateMockRead(*body3
, i
++));
6494 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6496 // Force all writes to happen before any read, last write will not
6497 // actually queue a frame, due to window size being 0.
6498 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6499 vector_as_array(&writes
), writes
.size());
6501 ScopedVector
<UploadElementReader
> element_readers
;
6502 std::string
upload_data_string(initial_window_size
, 'a');
6503 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6504 element_readers
.push_back(new UploadBytesElementReader(
6505 upload_data_string
.c_str(), upload_data_string
.size()));
6506 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6508 HttpRequestInfo request
;
6509 request
.method
= "POST";
6510 request
.url
= GURL("http://www.google.com/");
6511 request
.upload_data_stream
= &upload_data_stream
;
6512 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6513 BoundNetLog(), GetParam(), NULL
);
6514 helper
.SetDeterministic();
6515 helper
.RunPreTestSetup();
6516 helper
.AddDeterministicData(&data
);
6518 HttpNetworkTransaction
* trans
= helper
.trans();
6520 TestCompletionCallback callback
;
6521 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6522 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6524 data
.RunFor(num_writes
- 1); // Write as much as we can.
6526 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6527 ASSERT_TRUE(stream
!= NULL
);
6528 ASSERT_TRUE(stream
->stream() != NULL
);
6529 EXPECT_EQ(0, stream
->stream()->send_window_size());
6531 // All the body data should have been read.
6532 // TODO(satorux): This is because of the weirdness in reading the request
6533 // body in OnSendBodyComplete(). See crbug.com/113107.
6534 EXPECT_TRUE(upload_data_stream
.IsEOF());
6535 // But the body is not yet fully sent (kUploadData is not yet sent)
6536 // since we're send-stalled.
6537 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6539 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6540 rv
= callback
.WaitForResult();
6541 helper
.VerifyDataConsumed();
6542 // If stream is NULL, that means it was unstalled and closed.
6543 EXPECT_TRUE(stream
->stream() == NULL
);
6546 // Test we correctly handle the case where the SETTINGS frame results in a
6547 // negative send window size.
6548 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6549 const int32 initial_window_size
=
6550 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6551 // Number of frames we need to send to zero out the window size: data
6552 // frames plus SYN_STREAM plus the last data frame; also we need another
6553 // data frame that we will send once the SETTING is received, therefore +3.
6554 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6556 // Calculate last frame's size; 0 size data frame is legal.
6557 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6559 // Construct content for a data frame of maximum size.
6560 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6562 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6563 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6566 scoped_ptr
<SpdyFrame
> body1(
6567 spdy_util_
.ConstructSpdyBodyFrame(
6568 1, content
.c_str(), content
.size(), false));
6570 // Last frame to zero out the window size.
6571 scoped_ptr
<SpdyFrame
> body2(
6572 spdy_util_
.ConstructSpdyBodyFrame(
6573 1, content
.c_str(), last_frame_size
, false));
6575 // Data frame to be sent once SETTINGS frame is received.
6576 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6578 // Fill in mock reads/writes.
6579 std::vector
<MockRead
> reads
;
6580 std::vector
<MockWrite
> writes
;
6582 writes
.push_back(CreateMockWrite(*req
, i
++));
6583 while (i
< num_writes
- 2)
6584 writes
.push_back(CreateMockWrite(*body1
, i
++));
6585 writes
.push_back(CreateMockWrite(*body2
, i
++));
6587 // Construct read frame for SETTINGS that makes the send_window_size
6589 SettingsMap new_settings
;
6590 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6591 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
/ 2);
6592 scoped_ptr
<SpdyFrame
> settings_frame_small(
6593 spdy_util_
.ConstructSpdySettings(new_settings
));
6594 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6596 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6597 spdy_util_
.ConstructSpdyWindowUpdate(0, initial_window_size
));
6598 scoped_ptr
<SpdyFrame
> window_update_init_size(
6599 spdy_util_
.ConstructSpdyWindowUpdate(1, initial_window_size
));
6601 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6602 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6603 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6605 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6606 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6608 writes
.push_back(CreateMockWrite(*body3
, i
++));
6610 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6611 reads
.push_back(CreateMockRead(*reply
, i
++));
6612 reads
.push_back(CreateMockRead(*body2
, i
++));
6613 reads
.push_back(CreateMockRead(*body3
, i
++));
6614 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6616 // Force all writes to happen before any read, last write will not
6617 // actually queue a frame, due to window size being 0.
6618 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6619 vector_as_array(&writes
), writes
.size());
6621 ScopedVector
<UploadElementReader
> element_readers
;
6622 std::string
upload_data_string(initial_window_size
, 'a');
6623 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6624 element_readers
.push_back(new UploadBytesElementReader(
6625 upload_data_string
.c_str(), upload_data_string
.size()));
6626 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6628 HttpRequestInfo request
;
6629 request
.method
= "POST";
6630 request
.url
= GURL("http://www.google.com/");
6631 request
.upload_data_stream
= &upload_data_stream
;
6632 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6633 BoundNetLog(), GetParam(), NULL
);
6634 helper
.SetDeterministic();
6635 helper
.RunPreTestSetup();
6636 helper
.AddDeterministicData(&data
);
6638 HttpNetworkTransaction
* trans
= helper
.trans();
6640 TestCompletionCallback callback
;
6641 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6642 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6644 data
.RunFor(num_writes
- 1); // Write as much as we can.
6646 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6647 ASSERT_TRUE(stream
!= NULL
);
6648 ASSERT_TRUE(stream
->stream() != NULL
);
6649 EXPECT_EQ(0, stream
->stream()->send_window_size());
6651 // All the body data should have been read.
6652 // TODO(satorux): This is because of the weirdness in reading the request
6653 // body in OnSendBodyComplete(). See crbug.com/113107.
6654 EXPECT_TRUE(upload_data_stream
.IsEOF());
6655 // But the body is not yet fully sent (kUploadData is not yet sent)
6656 // since we're send-stalled.
6657 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6659 // Read in WINDOW_UPDATE or SETTINGS frame.
6660 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6661 rv
= callback
.WaitForResult();
6662 helper
.VerifyDataConsumed();
6665 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnOddPushStreamId
) {
6666 if (spdy_util_
.spdy_version() < SPDY3
)
6669 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
6670 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6671 push_headers
.get());
6672 scoped_ptr
<SpdyFrame
> push(
6673 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 3, 1));
6674 MockRead reads
[] = {CreateMockRead(*push
, 1)};
6676 scoped_ptr
<SpdyFrame
> req(
6677 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6678 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6679 0, GOAWAY_PROTOCOL_ERROR
, "Odd push stream id."));
6680 MockWrite writes
[] = {
6681 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 2),
6684 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6685 NormalSpdyTransactionHelper
helper(
6686 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6687 helper
.RunToCompletion(&data
);
6688 TransactionHelperResult out
= helper
.output();
6689 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6692 TEST_P(SpdyNetworkTransactionTest
,
6693 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted
) {
6694 if (spdy_util_
.spdy_version() < SPDY3
)
6697 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
6698 NULL
, 0, 4, 1, "http://www.google.com/a.dat"));
6699 scoped_ptr
<SpdyHeaderBlock
> push_b_headers(new SpdyHeaderBlock
);
6700 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6701 push_b_headers
.get());
6702 scoped_ptr
<SpdyFrame
> push_b(
6703 spdy_util_
.ConstructInitialSpdyPushFrame(push_b_headers
.Pass(), 2, 1));
6704 MockRead reads
[] = {
6705 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
6708 scoped_ptr
<SpdyFrame
> req(
6709 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6710 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6712 GOAWAY_PROTOCOL_ERROR
,
6713 "New push stream id must be greater than the last accepted."));
6714 MockWrite writes
[] = {
6715 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
6718 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6719 NormalSpdyTransactionHelper
helper(
6720 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6721 helper
.RunToCompletion(&data
);
6722 TransactionHelperResult out
= helper
.output();
6723 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6726 class SpdyNetworkTransactionNoTLSUsageCheckTest
6727 : public SpdyNetworkTransactionTest
{
6729 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6730 // Construct the request.
6731 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyGet(
6732 "https://www.google.com/", false, 1, LOWEST
));
6733 MockWrite writes
[] = {CreateMockWrite(*req
)};
6735 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6736 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6737 MockRead reads
[] = {
6738 CreateMockRead(*resp
), CreateMockRead(*body
),
6739 MockRead(ASYNC
, 0, 0) // EOF
6742 DelayedSocketData
data(
6743 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6744 HttpRequestInfo request
;
6745 request
.method
= "GET";
6746 request
.url
= GURL("https://www.google.com/");
6747 NormalSpdyTransactionHelper
helper(
6748 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6749 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6750 TransactionHelperResult out
= helper
.output();
6751 EXPECT_EQ(OK
, out
.rv
);
6752 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6753 EXPECT_EQ("hello!", out
.response_data
);
6757 //-----------------------------------------------------------------------------
6758 // All tests are run with three different connection types: SPDY after NPN
6759 // negotiation, SPDY without SSL, and SPDY with SSL.
6761 // TODO(akalin): Use ::testing::Combine() when we are able to use
6763 INSTANTIATE_TEST_CASE_P(
6765 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6766 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
)));
6768 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6769 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6770 new SSLSocketDataProvider(ASYNC
, OK
));
6771 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6772 &ssl_provider
->connection_status
);
6774 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6777 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6778 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6779 new SSLSocketDataProvider(ASYNC
, OK
));
6780 // Set to TLS_RSA_WITH_NULL_MD5
6781 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6783 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6786 class SpdyNetworkTransactionTLSUsageCheckTest
6787 : public SpdyNetworkTransactionTest
{
6789 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6790 scoped_ptr
<SpdyFrame
> goaway(
6791 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6792 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6794 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6795 HttpRequestInfo request
;
6796 request
.method
= "GET";
6797 request
.url
= GURL("https://www.google.com/");
6798 NormalSpdyTransactionHelper
helper(
6799 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6800 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6801 TransactionHelperResult out
= helper
.output();
6802 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6806 INSTANTIATE_TEST_CASE_P(
6808 SpdyNetworkTransactionTLSUsageCheckTest
,
6810 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
6811 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNPN
)));
6813 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6814 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6815 new SSLSocketDataProvider(ASYNC
, OK
));
6816 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6817 &ssl_provider
->connection_status
);
6819 RunTLSUsageCheckTest(ssl_provider
.Pass());
6822 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6823 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6824 new SSLSocketDataProvider(ASYNC
, OK
));
6825 // Set to TLS_RSA_WITH_NULL_MD5
6826 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6828 RunTLSUsageCheckTest(ssl_provider
.Pass());