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 pos
= net::ExpectLogContainsSomewhere(
3784 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3785 net::NetLog::PHASE_NONE
);
3787 base::ListValue
* header_list
;
3788 ASSERT_TRUE(entries
[pos
].params
.get());
3789 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3791 std::vector
<std::string
> expected
;
3792 expected
.push_back(std::string(spdy_util_
.GetHostKey()) + ": www.google.com");
3793 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3794 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": http");
3795 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3796 expected
.push_back("user-agent: Chrome");
3797 if (spdy_util_
.spdy_version() < SPDY4
) {
3798 // SPDY4/HTTP2 eliminates use of the :version header.
3799 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3801 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3802 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3803 it
!= expected
.end();
3805 base::StringValue
header(*it
);
3806 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3807 "Header not found: " << *it
;
3811 // Since we buffer the IO from the stream to the renderer, this test verifies
3812 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3813 // on the network, but issued a Read for only 5 of those bytes) that the data
3814 // flow still works correctly.
3815 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3816 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3818 scoped_ptr
<SpdyFrame
> req(
3819 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3820 MockWrite writes
[] = { CreateMockWrite(*req
) };
3822 // 2 data frames in a single read.
3823 scoped_ptr
<SpdyFrame
> data_frame_1(
3824 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3825 scoped_ptr
<SpdyFrame
> data_frame_2(
3826 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3827 const SpdyFrame
* data_frames
[2] = {
3831 char combined_data_frames
[100];
3832 int combined_data_frames_len
=
3833 CombineFrames(data_frames
, arraysize(data_frames
),
3834 combined_data_frames
, arraysize(combined_data_frames
));
3835 scoped_ptr
<SpdyFrame
> last_frame(
3836 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3838 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3839 MockRead reads
[] = {
3840 CreateMockRead(*resp
),
3841 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3842 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3843 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3844 CreateMockRead(*last_frame
),
3845 MockRead(ASYNC
, 0, 0) // EOF
3848 DelayedSocketData
data(1, reads
, arraysize(reads
),
3849 writes
, arraysize(writes
));
3851 TestCompletionCallback callback
;
3853 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3854 BoundNetLog(), GetParam(), NULL
);
3855 helper
.RunPreTestSetup();
3856 helper
.AddData(&data
);
3857 HttpNetworkTransaction
* trans
= helper
.trans();
3858 int rv
= trans
->Start(
3859 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3860 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3862 TransactionHelperResult out
= helper
.output();
3863 out
.rv
= callback
.WaitForResult();
3864 EXPECT_EQ(out
.rv
, OK
);
3866 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3867 EXPECT_TRUE(response
->headers
.get() != NULL
);
3868 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3869 out
.status_line
= response
->headers
->GetStatusLine();
3870 out
.response_info
= *response
; // Make a copy so we can verify.
3873 TestCompletionCallback read_callback
;
3875 std::string content
;
3877 // Read small chunks at a time.
3878 const int kSmallReadSize
= 3;
3879 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3880 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3881 if (rv
== net::ERR_IO_PENDING
) {
3882 data
.CompleteRead();
3883 rv
= read_callback
.WaitForResult();
3886 content
.append(buf
->data(), rv
);
3887 } else if (rv
< 0) {
3892 out
.response_data
.swap(content
);
3894 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3895 // MockClientSocketFactory) are still alive.
3896 base::RunLoop().RunUntilIdle();
3898 // Verify that we consumed all test data.
3899 helper
.VerifyDataConsumed();
3901 EXPECT_EQ(OK
, out
.rv
);
3902 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3903 EXPECT_EQ("goodbye world", out
.response_data
);
3906 // Verify that basic buffering works; when multiple data frames arrive
3907 // at the same time, ensure that we don't notify a read completion for
3908 // each data frame individually.
3909 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3910 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3912 scoped_ptr
<SpdyFrame
> req(
3913 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3914 MockWrite writes
[] = { CreateMockWrite(*req
) };
3916 // 4 data frames in a single read.
3917 scoped_ptr
<SpdyFrame
> data_frame(
3918 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3919 scoped_ptr
<SpdyFrame
> data_frame_fin(
3920 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3921 const SpdyFrame
* data_frames
[4] = {
3925 data_frame_fin
.get()
3927 char combined_data_frames
[100];
3928 int combined_data_frames_len
=
3929 CombineFrames(data_frames
, arraysize(data_frames
),
3930 combined_data_frames
, arraysize(combined_data_frames
));
3932 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3933 MockRead reads
[] = {
3934 CreateMockRead(*resp
),
3935 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3936 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3937 MockRead(ASYNC
, 0, 0) // EOF
3940 DelayedSocketData
data(1, reads
, arraysize(reads
),
3941 writes
, arraysize(writes
));
3943 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3944 BoundNetLog(), GetParam(), NULL
);
3945 helper
.RunPreTestSetup();
3946 helper
.AddData(&data
);
3947 HttpNetworkTransaction
* trans
= helper
.trans();
3949 TestCompletionCallback callback
;
3950 int rv
= trans
->Start(
3951 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3952 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3954 TransactionHelperResult out
= helper
.output();
3955 out
.rv
= callback
.WaitForResult();
3956 EXPECT_EQ(out
.rv
, OK
);
3958 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3959 EXPECT_TRUE(response
->headers
.get() != NULL
);
3960 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3961 out
.status_line
= response
->headers
->GetStatusLine();
3962 out
.response_info
= *response
; // Make a copy so we can verify.
3965 TestCompletionCallback read_callback
;
3967 std::string content
;
3968 int reads_completed
= 0;
3970 // Read small chunks at a time.
3971 const int kSmallReadSize
= 14;
3972 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3973 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3974 if (rv
== net::ERR_IO_PENDING
) {
3975 data
.CompleteRead();
3976 rv
= read_callback
.WaitForResult();
3979 EXPECT_EQ(kSmallReadSize
, rv
);
3980 content
.append(buf
->data(), rv
);
3981 } else if (rv
< 0) {
3982 FAIL() << "Unexpected read error: " << rv
;
3987 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3989 out
.response_data
.swap(content
);
3991 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3992 // MockClientSocketFactory) are still alive.
3993 base::RunLoop().RunUntilIdle();
3995 // Verify that we consumed all test data.
3996 helper
.VerifyDataConsumed();
3998 EXPECT_EQ(OK
, out
.rv
);
3999 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4000 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4003 // Verify the case where we buffer data but read it after it has been buffered.
4004 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
4005 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4007 scoped_ptr
<SpdyFrame
> req(
4008 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4009 MockWrite writes
[] = { CreateMockWrite(*req
) };
4011 // 5 data frames in a single read.
4012 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4013 scoped_ptr
<SpdyFrame
> data_frame(
4014 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4015 scoped_ptr
<SpdyFrame
> data_frame_fin(
4016 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4017 const SpdyFrame
* frames
[5] = {reply
.get(), data_frame
.get(), data_frame
.get(),
4018 data_frame
.get(), data_frame_fin
.get()};
4019 char combined_frames
[200];
4020 int combined_frames_len
=
4021 CombineFrames(frames
, arraysize(frames
),
4022 combined_frames
, arraysize(combined_frames
));
4024 MockRead reads
[] = {
4025 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4026 MockRead(ASYNC
, 0, 0) // EOF
4029 DelayedSocketData
data(1, reads
, arraysize(reads
),
4030 writes
, arraysize(writes
));
4032 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4033 BoundNetLog(), GetParam(), NULL
);
4034 helper
.RunPreTestSetup();
4035 helper
.AddData(&data
);
4036 HttpNetworkTransaction
* trans
= helper
.trans();
4038 TestCompletionCallback callback
;
4039 int rv
= trans
->Start(
4040 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4041 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4043 TransactionHelperResult out
= helper
.output();
4044 out
.rv
= callback
.WaitForResult();
4045 EXPECT_EQ(out
.rv
, OK
);
4047 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4048 EXPECT_TRUE(response
->headers
.get() != NULL
);
4049 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4050 out
.status_line
= response
->headers
->GetStatusLine();
4051 out
.response_info
= *response
; // Make a copy so we can verify.
4054 TestCompletionCallback read_callback
;
4056 std::string content
;
4057 int reads_completed
= 0;
4059 // Read small chunks at a time.
4060 const int kSmallReadSize
= 14;
4061 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4062 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4064 EXPECT_EQ(kSmallReadSize
, rv
);
4065 content
.append(buf
->data(), rv
);
4066 } else if (rv
< 0) {
4067 FAIL() << "Unexpected read error: " << rv
;
4072 EXPECT_EQ(3, reads_completed
);
4074 out
.response_data
.swap(content
);
4076 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4077 // MockClientSocketFactory) are still alive.
4078 base::RunLoop().RunUntilIdle();
4080 // Verify that we consumed all test data.
4081 helper
.VerifyDataConsumed();
4083 EXPECT_EQ(OK
, out
.rv
);
4084 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4085 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4088 // Verify the case where we buffer data and close the connection.
4089 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4090 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4092 scoped_ptr
<SpdyFrame
> req(
4093 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4094 MockWrite writes
[] = { CreateMockWrite(*req
) };
4096 // All data frames in a single read.
4097 // NOTE: We don't FIN the stream.
4098 scoped_ptr
<SpdyFrame
> data_frame(
4099 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4100 const SpdyFrame
* data_frames
[4] = {
4106 char combined_data_frames
[100];
4107 int combined_data_frames_len
=
4108 CombineFrames(data_frames
, arraysize(data_frames
),
4109 combined_data_frames
, arraysize(combined_data_frames
));
4110 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4111 MockRead reads
[] = {
4112 CreateMockRead(*resp
),
4113 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4114 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4115 MockRead(ASYNC
, 0, 0) // EOF
4118 DelayedSocketData
data(1, reads
, arraysize(reads
),
4119 writes
, arraysize(writes
));
4121 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4122 BoundNetLog(), GetParam(), NULL
);
4123 helper
.RunPreTestSetup();
4124 helper
.AddData(&data
);
4125 HttpNetworkTransaction
* trans
= helper
.trans();
4127 TestCompletionCallback callback
;
4129 int rv
= trans
->Start(
4130 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4131 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4133 TransactionHelperResult out
= helper
.output();
4134 out
.rv
= callback
.WaitForResult();
4135 EXPECT_EQ(out
.rv
, OK
);
4137 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4138 EXPECT_TRUE(response
->headers
.get() != NULL
);
4139 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4140 out
.status_line
= response
->headers
->GetStatusLine();
4141 out
.response_info
= *response
; // Make a copy so we can verify.
4144 TestCompletionCallback read_callback
;
4146 std::string content
;
4147 int reads_completed
= 0;
4149 // Read small chunks at a time.
4150 const int kSmallReadSize
= 14;
4151 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4152 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4153 if (rv
== net::ERR_IO_PENDING
) {
4154 data
.CompleteRead();
4155 rv
= read_callback
.WaitForResult();
4158 content
.append(buf
->data(), rv
);
4159 } else if (rv
< 0) {
4160 // This test intentionally closes the connection, and will get an error.
4161 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4167 EXPECT_EQ(0, reads_completed
);
4169 out
.response_data
.swap(content
);
4171 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4172 // MockClientSocketFactory) are still alive.
4173 base::RunLoop().RunUntilIdle();
4175 // Verify that we consumed all test data.
4176 helper
.VerifyDataConsumed();
4179 // Verify the case where we buffer data and cancel the transaction.
4180 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4181 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4183 scoped_ptr
<SpdyFrame
> req(
4184 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4185 scoped_ptr
<SpdyFrame
> rst(
4186 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
4187 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*rst
)};
4189 // NOTE: We don't FIN the stream.
4190 scoped_ptr
<SpdyFrame
> data_frame(
4191 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4193 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4194 MockRead reads
[] = {
4195 CreateMockRead(*resp
),
4196 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4197 CreateMockRead(*data_frame
),
4198 MockRead(ASYNC
, 0, 0) // EOF
4201 DelayedSocketData
data(1, reads
, arraysize(reads
),
4202 writes
, arraysize(writes
));
4204 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4205 BoundNetLog(), GetParam(), NULL
);
4206 helper
.RunPreTestSetup();
4207 helper
.AddData(&data
);
4208 HttpNetworkTransaction
* trans
= helper
.trans();
4209 TestCompletionCallback callback
;
4211 int rv
= trans
->Start(
4212 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4215 TransactionHelperResult out
= helper
.output();
4216 out
.rv
= callback
.WaitForResult();
4217 EXPECT_EQ(out
.rv
, OK
);
4219 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4220 EXPECT_TRUE(response
->headers
.get() != NULL
);
4221 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4222 out
.status_line
= response
->headers
->GetStatusLine();
4223 out
.response_info
= *response
; // Make a copy so we can verify.
4226 TestCompletionCallback read_callback
;
4228 const int kReadSize
= 256;
4229 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4230 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4231 ASSERT_EQ(net::ERR_IO_PENDING
, rv
) << "Unexpected read: " << rv
;
4233 // Complete the read now, which causes buffering to start.
4234 data
.CompleteRead();
4235 // Destroy the transaction, causing the stream to get cancelled
4236 // and orphaning the buffered IO task.
4237 helper
.ResetTrans();
4239 // Flush the MessageLoop; this will cause the buffered IO task
4240 // to run for the final time.
4241 base::RunLoop().RunUntilIdle();
4243 // Verify that we consumed all test data.
4244 helper
.VerifyDataConsumed();
4247 // Test that if the server requests persistence of settings, that we save
4248 // the settings in the HttpServerProperties.
4249 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4250 if (spdy_util_
.spdy_version() >= SPDY4
) {
4251 // SPDY4 doesn't support settings persistence.
4254 static const SpdyHeaderInfo kSynReplyInfo
= {
4255 SYN_REPLY
, // Syn Reply
4257 0, // Associated Stream ID
4258 ConvertRequestPriorityToSpdyPriority(
4259 LOWEST
, spdy_util_
.spdy_version()),
4260 kSpdyCredentialSlotUnused
,
4261 CONTROL_FLAG_NONE
, // Control Flags
4262 false, // Compressed
4263 RST_STREAM_INVALID
, // Status
4266 DATA_FLAG_NONE
// Data Flags
4269 BoundNetLog net_log
;
4270 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4271 net_log
, GetParam(), NULL
);
4272 helper
.RunPreTestSetup();
4274 // Verify that no settings exist initially.
4275 HostPortPair
host_port_pair("www.google.com", helper
.port());
4276 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4277 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4278 host_port_pair
).empty());
4280 // Construct the request.
4281 scoped_ptr
<SpdyFrame
> req(
4282 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4283 MockWrite writes
[] = { CreateMockWrite(*req
) };
4285 // Construct the reply.
4286 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4287 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4288 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4289 scoped_ptr
<SpdyFrame
> reply(
4290 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4292 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4293 unsigned int kSampleValue1
= 0x0a0a0a0a;
4294 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4295 unsigned int kSampleValue2
= 0x0b0b0b0b;
4296 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4297 unsigned int kSampleValue3
= 0x0c0c0c0c;
4298 scoped_ptr
<SpdyFrame
> settings_frame
;
4300 // Construct the SETTINGS frame.
4301 SettingsMap settings
;
4302 // First add a persisted setting.
4303 settings
[kSampleId1
] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4305 // Next add a non-persisted setting.
4306 settings
[kSampleId2
] =
4307 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4308 // Next add another persisted setting.
4309 settings
[kSampleId3
] =
4310 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4311 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4314 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4315 MockRead reads
[] = {
4316 CreateMockRead(*reply
),
4317 CreateMockRead(*body
),
4318 CreateMockRead(*settings_frame
),
4319 MockRead(ASYNC
, 0, 0) // EOF
4322 DelayedSocketData
data(1, reads
, arraysize(reads
),
4323 writes
, arraysize(writes
));
4324 helper
.AddData(&data
);
4325 helper
.RunDefaultTest();
4326 helper
.VerifyDataConsumed();
4327 TransactionHelperResult out
= helper
.output();
4328 EXPECT_EQ(OK
, out
.rv
);
4329 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4330 EXPECT_EQ("hello!", out
.response_data
);
4333 // Verify we had two persisted settings.
4334 const SettingsMap
& settings_map
=
4335 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4337 ASSERT_EQ(2u, settings_map
.size());
4339 // Verify the first persisted setting.
4340 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4341 EXPECT_TRUE(it1
!= settings_map
.end());
4342 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4343 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4344 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4346 // Verify the second persisted setting.
4347 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4348 EXPECT_TRUE(it3
!= settings_map
.end());
4349 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4350 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4351 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4355 // Test that when there are settings saved that they are sent back to the
4356 // server upon session establishment.
4357 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4358 if (spdy_util_
.spdy_version() >= SPDY4
) {
4359 // SPDY4 doesn't support settings persistence.
4362 static const SpdyHeaderInfo kSynReplyInfo
= {
4363 SYN_REPLY
, // Syn Reply
4365 0, // Associated Stream ID
4366 ConvertRequestPriorityToSpdyPriority(
4367 LOWEST
, spdy_util_
.spdy_version()),
4368 kSpdyCredentialSlotUnused
,
4369 CONTROL_FLAG_NONE
, // Control Flags
4370 false, // Compressed
4371 RST_STREAM_INVALID
, // Status
4374 DATA_FLAG_NONE
// Data Flags
4377 BoundNetLog net_log
;
4378 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4379 net_log
, GetParam(), NULL
);
4380 helper
.RunPreTestSetup();
4382 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4384 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4385 pool_peer
.SetEnableSendingInitialData(true);
4387 // Verify that no settings exist initially.
4388 HostPortPair
host_port_pair("www.google.com", helper
.port());
4389 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4390 host_port_pair
).empty());
4392 const SpdySettingsIds kSampleId1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
4393 unsigned int kSampleValue1
= 0x0a0a0a0a;
4394 const SpdySettingsIds kSampleId2
= SETTINGS_INITIAL_WINDOW_SIZE
;
4395 unsigned int kSampleValue2
= 0x0c0c0c0c;
4397 // First add a persisted setting.
4398 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4401 SETTINGS_FLAG_PLEASE_PERSIST
,
4404 // Next add another persisted setting.
4405 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4408 SETTINGS_FLAG_PLEASE_PERSIST
,
4411 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4412 host_port_pair
).size());
4414 // Construct the initial SETTINGS frame.
4415 SettingsMap initial_settings
;
4416 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4417 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4418 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4419 spdy_util_
.ConstructSpdySettings(initial_settings
));
4421 // Construct the initial window update.
4422 scoped_ptr
<SpdyFrame
> initial_window_update(
4423 spdy_util_
.ConstructSpdyWindowUpdate(
4424 kSessionFlowControlStreamId
,
4425 kDefaultInitialRecvWindowSize
-
4426 SpdySession::GetInitialWindowSize(GetParam().protocol
)));
4428 // Construct the persisted SETTINGS frame.
4429 const SettingsMap
& settings
=
4430 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4432 scoped_ptr
<SpdyFrame
> settings_frame(
4433 spdy_util_
.ConstructSpdySettings(settings
));
4435 // Construct the request.
4436 scoped_ptr
<SpdyFrame
> req(
4437 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4439 std::vector
<MockWrite
> writes
;
4440 if ((GetParam().protocol
>= kProtoSPDY4MinimumVersion
) &&
4441 (GetParam().protocol
<= kProtoSPDY4MaximumVersion
)) {
4444 kHttp2ConnectionHeaderPrefix
,
4445 kHttp2ConnectionHeaderPrefixSize
));
4447 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4448 if (GetParam().protocol
>= kProtoSPDY31
) {
4449 writes
.push_back(CreateMockWrite(*initial_window_update
));
4451 writes
.push_back(CreateMockWrite(*settings_frame
));
4452 writes
.push_back(CreateMockWrite(*req
));
4454 // Construct the reply.
4455 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4456 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4457 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4458 scoped_ptr
<SpdyFrame
> reply(
4459 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4461 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4462 MockRead reads
[] = {
4463 CreateMockRead(*reply
),
4464 CreateMockRead(*body
),
4465 MockRead(ASYNC
, 0, 0) // EOF
4468 DelayedSocketData
data(2, reads
, arraysize(reads
),
4469 vector_as_array(&writes
), writes
.size());
4470 helper
.AddData(&data
);
4471 helper
.RunDefaultTest();
4472 helper
.VerifyDataConsumed();
4473 TransactionHelperResult out
= helper
.output();
4474 EXPECT_EQ(OK
, out
.rv
);
4475 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4476 EXPECT_EQ("hello!", out
.response_data
);
4479 // Verify we had two persisted settings.
4480 const SettingsMap
& settings_map
=
4481 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4483 ASSERT_EQ(2u, settings_map
.size());
4485 // Verify the first persisted setting.
4486 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4487 EXPECT_TRUE(it1
!= settings_map
.end());
4488 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4489 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4490 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4492 // Verify the second persisted setting.
4493 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4494 EXPECT_TRUE(it2
!= settings_map
.end());
4495 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4496 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4497 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4501 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4502 scoped_ptr
<SpdyFrame
> req(
4503 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4504 MockWrite writes
[] = { CreateMockWrite(*req
) };
4506 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4507 MockRead reads
[] = {
4508 CreateMockRead(*go_away
),
4511 DelayedSocketData
data(1, reads
, arraysize(reads
),
4512 writes
, arraysize(writes
));
4513 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4514 BoundNetLog(), GetParam(), NULL
);
4515 helper
.AddData(&data
);
4516 helper
.RunToCompletion(&data
);
4517 TransactionHelperResult out
= helper
.output();
4518 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4521 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4522 scoped_ptr
<SpdyFrame
> req(
4523 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4524 MockWrite writes
[] = { CreateMockWrite(*req
) };
4526 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4527 MockRead reads
[] = {
4528 CreateMockRead(*resp
),
4529 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4532 DelayedSocketData
data(1, reads
, arraysize(reads
),
4533 writes
, arraysize(writes
));
4535 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4536 log
, GetParam(), NULL
);
4537 helper
.RunPreTestSetup();
4538 helper
.AddData(&data
);
4539 HttpNetworkTransaction
* trans
= helper
.trans();
4541 TestCompletionCallback callback
;
4542 TransactionHelperResult out
;
4543 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4545 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4546 out
.rv
= callback
.WaitForResult();
4547 EXPECT_EQ(out
.rv
, OK
);
4549 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4550 EXPECT_TRUE(response
->headers
.get() != NULL
);
4551 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4552 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4553 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4555 // Verify that we consumed all test data.
4556 helper
.VerifyDataConsumed();
4559 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4560 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredError
) {
4561 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4562 if (spdy_util_
.spdy_version() < SPDY4
)
4565 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4566 BoundNetLog(), GetParam(), nullptr);
4568 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4569 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4570 MockRead reads
[] = {
4571 CreateMockRead(*go_away
),
4573 DelayedSocketData
data(0, reads
, arraysize(reads
), nullptr, 0);
4575 helper
.RunToCompletion(&data
);
4576 TransactionHelperResult out
= helper
.output();
4577 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED
, out
.rv
);
4580 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4581 // protocol negotiation happens, instead this test forces protocols for both
4583 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredRetry
) {
4584 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4585 if (spdy_util_
.spdy_version() < SPDY4
)
4587 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4588 // only spoken over SSL.
4589 if (GetParam().ssl_type
!= SPDYSSL
)
4592 HttpRequestInfo request
;
4593 request
.method
= "GET";
4594 request
.url
= GURL("https://www.google.com/");
4595 scoped_ptr
<SpdySessionDependencies
> session_deps(
4596 CreateSpdySessionDependencies(GetParam()));
4597 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4598 session_deps
->force_spdy_over_ssl
= false;
4599 session_deps
->force_spdy_always
= false;
4600 session_deps
->next_protos
= SpdyNextProtos();
4601 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4602 GetParam(), session_deps
.release());
4604 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4605 const char* url
= "https://www.google.com/";
4606 scoped_ptr
<SpdyHeaderBlock
> headers(spdy_util_
.ConstructGetHeaderBlock(url
));
4607 scoped_ptr
<SpdyFrame
> req(
4608 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4609 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4610 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4611 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4612 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4613 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4614 arraysize(writes0
));
4616 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4617 new SSLSocketDataProvider(ASYNC
, OK
));
4618 // Expect HTTP/2 protocols too in SSLConfig.
4619 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4620 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4621 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4622 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_15
);
4624 ssl_provider0
->SetNextProto(GetParam().protocol
);
4625 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4627 // Second socket: falling back to HTTP/1.1.
4628 MockWrite writes1
[] = {MockWrite(
4629 "GET / HTTP/1.1\r\n"
4630 "Host: www.google.com\r\n"
4631 "Connection: keep-alive\r\n\r\n")};
4632 MockRead reads1
[] = {MockRead(
4633 "HTTP/1.1 200 OK\r\n"
4634 "Content-Length: 5\r\n\r\n"
4636 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4637 arraysize(writes1
));
4639 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4640 new SSLSocketDataProvider(ASYNC
, OK
));
4641 // Expect only HTTP/1.1 protocol in SSLConfig.
4642 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4644 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4645 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4647 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4648 helper
.session()->spdy_session_pool()->http_server_properties();
4649 const HostPortPair host_port_pair
= HostPortPair::FromURL(GURL(url
));
4650 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4652 helper
.RunPreTestSetup();
4653 helper
.StartDefaultTest();
4654 helper
.FinishDefaultTestWithoutVerification();
4655 helper
.VerifyDataConsumed();
4656 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4658 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4659 ASSERT_TRUE(response
!= nullptr);
4660 ASSERT_TRUE(response
->headers
.get() != nullptr);
4661 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4662 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4663 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4664 EXPECT_TRUE(response
->was_npn_negotiated
);
4665 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4666 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4667 EXPECT_EQ(443, response
->socket_address
.port());
4668 std::string response_data
;
4669 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4670 EXPECT_EQ("hello", response_data
);
4673 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4674 // proxy. Note that no actual protocol negotiation happens, instead this test
4675 // forces protocols for both sockets.
4676 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredProxyRetry
) {
4677 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4678 if (spdy_util_
.spdy_version() < SPDY4
)
4680 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4681 // only spoken over SSL.
4682 if (GetParam().ssl_type
!= SPDYSSL
)
4685 HttpRequestInfo request
;
4686 request
.method
= "GET";
4687 request
.url
= GURL("https://www.google.com/");
4688 scoped_ptr
<SpdySessionDependencies
> session_deps(
4689 CreateSpdySessionDependencies(
4691 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4692 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4693 session_deps
->force_spdy_over_ssl
= false;
4694 session_deps
->force_spdy_always
= false;
4695 session_deps
->next_protos
= SpdyNextProtos();
4696 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4697 GetParam(), session_deps
.release());
4699 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4700 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
4701 nullptr, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
4702 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4703 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4704 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4705 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4706 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4707 arraysize(writes0
));
4709 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4710 new SSLSocketDataProvider(ASYNC
, OK
));
4711 // Expect HTTP/2 protocols too in SSLConfig.
4712 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4713 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4714 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4715 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_15
);
4717 ssl_provider0
->SetNextProto(GetParam().protocol
);
4718 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4720 // Second socket: retry using HTTP/1.1.
4721 MockWrite writes1
[] = {
4723 "CONNECT www.google.com:443 HTTP/1.1\r\n"
4724 "Host: www.google.com\r\n"
4725 "Proxy-Connection: keep-alive\r\n\r\n"),
4727 "GET / HTTP/1.1\r\n"
4728 "Host: www.google.com\r\n"
4729 "Connection: keep-alive\r\n\r\n"),
4732 MockRead reads1
[] = {
4733 MockRead(ASYNC
, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4735 "HTTP/1.1 200 OK\r\n"
4736 "Content-Length: 5\r\n\r\n"
4739 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4740 arraysize(writes1
));
4742 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4743 new SSLSocketDataProvider(ASYNC
, OK
));
4744 // Expect only HTTP/1.1 protocol in SSLConfig.
4745 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4747 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4748 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4750 // A third socket is needed for the tunnelled connection.
4751 scoped_ptr
<SSLSocketDataProvider
> ssl_provider2(
4752 new SSLSocketDataProvider(ASYNC
, OK
));
4753 helper
.session_deps()->socket_factory
->AddSSLSocketDataProvider(
4754 ssl_provider2
.get());
4756 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4757 helper
.session()->spdy_session_pool()->http_server_properties();
4758 const HostPortPair proxy_host_port_pair
= HostPortPair("myproxy", 70);
4759 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4761 helper
.RunPreTestSetup();
4762 helper
.StartDefaultTest();
4763 helper
.FinishDefaultTestWithoutVerification();
4764 helper
.VerifyDataConsumed();
4765 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4767 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4768 ASSERT_TRUE(response
!= nullptr);
4769 ASSERT_TRUE(response
->headers
.get() != nullptr);
4770 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4771 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4772 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4773 EXPECT_FALSE(response
->was_npn_negotiated
);
4774 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4775 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4776 EXPECT_EQ(70, response
->socket_address
.port());
4777 std::string response_data
;
4778 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4779 EXPECT_EQ("hello", response_data
);
4782 // Test to make sure we can correctly connect through a proxy.
4783 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4784 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4785 BoundNetLog(), GetParam(), NULL
);
4786 helper
.session_deps().reset(CreateSpdySessionDependencies(
4788 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4789 helper
.SetSession(make_scoped_refptr(
4790 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4791 helper
.RunPreTestSetup();
4792 HttpNetworkTransaction
* trans
= helper
.trans();
4794 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4795 "Host: www.google.com\r\n"
4796 "Proxy-Connection: keep-alive\r\n\r\n"};
4797 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4798 "Host: www.google.com\r\n"
4799 "Proxy-Connection: keep-alive\r\n\r\n"};
4800 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4801 scoped_ptr
<SpdyFrame
> req(
4802 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4803 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4804 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4806 MockWrite writes_SPDYNPN
[] = {
4807 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4808 CreateMockWrite(*req
, 2),
4810 MockRead reads_SPDYNPN
[] = {
4811 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4812 CreateMockRead(*resp
, 3),
4813 CreateMockRead(*body
.get(), 4),
4814 MockRead(ASYNC
, 0, 0, 5),
4817 MockWrite writes_SPDYSSL
[] = {
4818 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4819 CreateMockWrite(*req
, 2),
4821 MockRead reads_SPDYSSL
[] = {
4822 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4823 CreateMockRead(*resp
, 3),
4824 CreateMockRead(*body
.get(), 4),
4825 MockRead(ASYNC
, 0, 0, 5),
4828 MockWrite writes_SPDYNOSSL
[] = {
4829 CreateMockWrite(*req
, 0),
4832 MockRead reads_SPDYNOSSL
[] = {
4833 CreateMockRead(*resp
, 1),
4834 CreateMockRead(*body
.get(), 2),
4835 MockRead(ASYNC
, 0, 0, 3),
4838 scoped_ptr
<OrderedSocketData
> data
;
4839 switch (GetParam().ssl_type
) {
4841 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4842 arraysize(reads_SPDYNOSSL
),
4844 arraysize(writes_SPDYNOSSL
)));
4847 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4848 arraysize(reads_SPDYSSL
),
4850 arraysize(writes_SPDYSSL
)));
4853 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4854 arraysize(reads_SPDYNPN
),
4856 arraysize(writes_SPDYNPN
)));
4862 helper
.AddData(data
.get());
4863 TestCompletionCallback callback
;
4865 int rv
= trans
->Start(
4866 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4867 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4869 rv
= callback
.WaitForResult();
4872 // Verify the SYN_REPLY.
4873 HttpResponseInfo response
= *trans
->GetResponseInfo();
4874 EXPECT_TRUE(response
.headers
.get() != NULL
);
4875 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4877 std::string response_data
;
4878 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4879 EXPECT_EQ("hello!", response_data
);
4880 helper
.VerifyDataConsumed();
4883 // Test to make sure we can correctly connect through a proxy to www.google.com,
4884 // if there already exists a direct spdy connection to www.google.com. See
4885 // http://crbug.com/49874
4886 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4887 // When setting up the first transaction, we store the SpdySessionPool so that
4888 // we can use the same pool in the second transaction.
4889 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4890 BoundNetLog(), GetParam(), NULL
);
4892 // Use a proxy service which returns a proxy fallback list from DIRECT to
4893 // myproxy:70. For this test there will be no fallback, so it is equivalent
4894 // to simply DIRECT. The reason for appending the second proxy is to verify
4895 // that the session pool key used does is just "DIRECT".
4896 helper
.session_deps().reset(CreateSpdySessionDependencies(
4898 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4899 helper
.SetSession(make_scoped_refptr(
4900 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4902 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4903 helper
.RunPreTestSetup();
4905 // Construct and send a simple GET request.
4906 scoped_ptr
<SpdyFrame
> req(
4907 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4908 MockWrite writes
[] = {
4909 CreateMockWrite(*req
, 1),
4912 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4913 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4914 MockRead reads
[] = {
4915 CreateMockRead(*resp
, 2),
4916 CreateMockRead(*body
, 3),
4917 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4918 MockRead(ASYNC
, 0, 5) // EOF
4920 OrderedSocketData
data(reads
, arraysize(reads
),
4921 writes
, arraysize(writes
));
4922 helper
.AddData(&data
);
4923 HttpNetworkTransaction
* trans
= helper
.trans();
4925 TestCompletionCallback callback
;
4926 TransactionHelperResult out
;
4927 out
.rv
= trans
->Start(
4928 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4930 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4931 out
.rv
= callback
.WaitForResult();
4932 EXPECT_EQ(out
.rv
, OK
);
4934 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4935 EXPECT_TRUE(response
->headers
.get() != NULL
);
4936 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4937 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4938 EXPECT_EQ(OK
, out
.rv
);
4939 out
.status_line
= response
->headers
->GetStatusLine();
4940 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4941 EXPECT_EQ("hello!", out
.response_data
);
4943 // Check that the SpdySession is still in the SpdySessionPool.
4944 HostPortPair
host_port_pair("www.google.com", helper
.port());
4945 SpdySessionKey
session_pool_key_direct(
4946 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4947 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4948 SpdySessionKey
session_pool_key_proxy(
4950 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4951 PRIVACY_MODE_DISABLED
);
4952 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4954 // Set up data for the proxy connection.
4955 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4956 "Host: www.google.com\r\n"
4957 "Proxy-Connection: keep-alive\r\n\r\n"};
4958 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4959 "Host: www.google.com\r\n"
4960 "Proxy-Connection: keep-alive\r\n\r\n"};
4961 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4962 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4963 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4964 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4965 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4967 MockWrite writes_SPDYNPN
[] = {
4968 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4969 CreateMockWrite(*req2
, 2),
4971 MockRead reads_SPDYNPN
[] = {
4972 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4973 CreateMockRead(*resp2
, 3),
4974 CreateMockRead(*body2
, 4),
4975 MockRead(ASYNC
, 0, 5) // EOF
4978 MockWrite writes_SPDYNOSSL
[] = {
4979 CreateMockWrite(*req2
, 0),
4981 MockRead reads_SPDYNOSSL
[] = {
4982 CreateMockRead(*resp2
, 1),
4983 CreateMockRead(*body2
, 2),
4984 MockRead(ASYNC
, 0, 3) // EOF
4987 MockWrite writes_SPDYSSL
[] = {
4988 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4989 CreateMockWrite(*req2
, 2),
4991 MockRead reads_SPDYSSL
[] = {
4992 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4993 CreateMockRead(*resp2
, 3),
4994 CreateMockRead(*body2
, 4),
4995 MockRead(ASYNC
, 0, 0, 5),
4998 scoped_ptr
<OrderedSocketData
> data_proxy
;
4999 switch (GetParam().ssl_type
) {
5001 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
5002 arraysize(reads_SPDYNPN
),
5004 arraysize(writes_SPDYNPN
)));
5007 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
5008 arraysize(reads_SPDYNOSSL
),
5010 arraysize(writes_SPDYNOSSL
)));
5013 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
5014 arraysize(reads_SPDYSSL
),
5016 arraysize(writes_SPDYSSL
)));
5022 // Create another request to www.google.com, but this time through a proxy.
5023 HttpRequestInfo request_proxy
;
5024 request_proxy
.method
= "GET";
5025 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
5026 request_proxy
.load_flags
= 0;
5027 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
5028 CreateSpdySessionDependencies(GetParam()));
5029 // Ensure that this transaction uses the same SpdySessionPool.
5030 scoped_refptr
<HttpNetworkSession
> session_proxy(
5031 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
5032 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
5033 BoundNetLog(), GetParam(), NULL
);
5034 HttpNetworkSessionPeer
session_peer(session_proxy
);
5035 scoped_ptr
<net::ProxyService
> proxy_service(
5036 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5037 session_peer
.SetProxyService(proxy_service
.get());
5038 helper_proxy
.session_deps().swap(ssd_proxy
);
5039 helper_proxy
.SetSession(session_proxy
);
5040 helper_proxy
.RunPreTestSetup();
5041 helper_proxy
.AddData(data_proxy
.get());
5043 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
5044 TestCompletionCallback callback_proxy
;
5045 int rv
= trans_proxy
->Start(
5046 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
5047 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5048 rv
= callback_proxy
.WaitForResult();
5051 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
5052 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
5053 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
5055 std::string response_data
;
5056 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
5057 EXPECT_EQ("hello!", response_data
);
5059 data
.CompleteRead();
5060 helper_proxy
.VerifyDataConsumed();
5063 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5064 // on a new connection, if the connection was previously known to be good.
5065 // This can happen when a server reboots without saying goodbye, or when
5066 // we're behind a NAT that masked the RST.
5067 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
5068 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5069 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5070 MockRead reads
[] = {
5071 CreateMockRead(*resp
),
5072 CreateMockRead(*body
),
5073 MockRead(ASYNC
, ERR_IO_PENDING
),
5074 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
5077 MockRead reads2
[] = {
5078 CreateMockRead(*resp
),
5079 CreateMockRead(*body
),
5080 MockRead(ASYNC
, 0, 0) // EOF
5083 // This test has a couple of variants.
5085 // Induce the RST while waiting for our transaction to send.
5086 VARIANT_RST_DURING_SEND_COMPLETION
,
5087 // Induce the RST while waiting for our transaction to read.
5088 // In this case, the send completed - everything copied into the SNDBUF.
5089 VARIANT_RST_DURING_READ_COMPLETION
5092 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
5093 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
5095 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
5097 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
5099 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5100 BoundNetLog(), GetParam(), NULL
);
5101 helper
.AddData(&data1
);
5102 helper
.AddData(&data2
);
5103 helper
.RunPreTestSetup();
5105 for (int i
= 0; i
< 2; ++i
) {
5106 scoped_ptr
<HttpNetworkTransaction
> trans(
5107 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5109 TestCompletionCallback callback
;
5110 int rv
= trans
->Start(
5111 &helper
.request(), callback
.callback(), BoundNetLog());
5112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5113 // On the second transaction, we trigger the RST.
5115 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
5116 // Writes to the socket complete asynchronously on SPDY by running
5117 // through the message loop. Complete the write here.
5118 base::RunLoop().RunUntilIdle();
5121 // Now schedule the ERR_CONNECTION_RESET.
5122 EXPECT_EQ(3u, data1
.read_index());
5123 data1
.CompleteRead();
5124 EXPECT_EQ(4u, data1
.read_index());
5126 rv
= callback
.WaitForResult();
5129 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5130 ASSERT_TRUE(response
!= NULL
);
5131 EXPECT_TRUE(response
->headers
.get() != NULL
);
5132 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5133 std::string response_data
;
5134 rv
= ReadTransaction(trans
.get(), &response_data
);
5136 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5137 EXPECT_EQ("hello!", response_data
);
5140 helper
.VerifyDataConsumed();
5144 // Test that turning SPDY on and off works properly.
5145 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
5146 HttpStreamFactory::set_spdy_enabled(true);
5147 scoped_ptr
<SpdyFrame
> req(
5148 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5149 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
5151 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5152 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5153 MockRead spdy_reads
[] = {
5154 CreateMockRead(*resp
),
5155 CreateMockRead(*body
),
5156 MockRead(ASYNC
, 0, 0) // EOF
5159 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
5160 spdy_writes
, arraysize(spdy_writes
));
5161 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5162 BoundNetLog(), GetParam(), NULL
);
5163 helper
.RunToCompletion(&data
);
5164 TransactionHelperResult out
= helper
.output();
5165 EXPECT_EQ(OK
, out
.rv
);
5166 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5167 EXPECT_EQ("hello!", out
.response_data
);
5169 net::HttpStreamFactory::set_spdy_enabled(false);
5170 MockRead http_reads
[] = {
5171 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5172 MockRead("hello from http"),
5173 MockRead(SYNCHRONOUS
, OK
),
5175 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
5176 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
5177 BoundNetLog(), GetParam(), NULL
);
5178 helper2
.SetSpdyDisabled();
5179 helper2
.RunToCompletion(&data2
);
5180 TransactionHelperResult out2
= helper2
.output();
5181 EXPECT_EQ(OK
, out2
.rv
);
5182 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
5183 EXPECT_EQ("hello from http", out2
.response_data
);
5185 net::HttpStreamFactory::set_spdy_enabled(true);
5188 // Tests that Basic authentication works over SPDY
5189 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
5190 net::HttpStreamFactory::set_spdy_enabled(true);
5192 // The first request will be a bare GET, the second request will be a
5193 // GET with an Authorization header.
5194 scoped_ptr
<SpdyFrame
> req_get(
5195 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5196 const char* const kExtraAuthorizationHeaders
[] = {
5197 "authorization", "Basic Zm9vOmJhcg=="
5199 scoped_ptr
<SpdyFrame
> req_get_authorization(
5200 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
5201 arraysize(kExtraAuthorizationHeaders
) / 2,
5202 false, 3, LOWEST
, true));
5203 MockWrite spdy_writes
[] = {
5204 CreateMockWrite(*req_get
, 1),
5205 CreateMockWrite(*req_get_authorization
, 4),
5208 // The first response is a 401 authentication challenge, and the second
5209 // response will be a 200 response since the second request includes a valid
5210 // Authorization header.
5211 const char* const kExtraAuthenticationHeaders
[] = {
5213 "Basic realm=\"MyRealm\""
5215 scoped_ptr
<SpdyFrame
> resp_authentication(
5216 spdy_util_
.ConstructSpdySynReplyError(
5217 "401 Authentication Required",
5218 kExtraAuthenticationHeaders
,
5219 arraysize(kExtraAuthenticationHeaders
) / 2,
5221 scoped_ptr
<SpdyFrame
> body_authentication(
5222 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5223 scoped_ptr
<SpdyFrame
> resp_data(
5224 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5225 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5226 MockRead spdy_reads
[] = {
5227 CreateMockRead(*resp_authentication
, 2),
5228 CreateMockRead(*body_authentication
, 3),
5229 CreateMockRead(*resp_data
, 5),
5230 CreateMockRead(*body_data
, 6),
5231 MockRead(ASYNC
, 0, 7),
5234 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5235 spdy_writes
, arraysize(spdy_writes
));
5236 HttpRequestInfo
request(CreateGetRequest());
5237 BoundNetLog net_log
;
5238 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5239 net_log
, GetParam(), NULL
);
5241 helper
.RunPreTestSetup();
5242 helper
.AddData(&data
);
5243 HttpNetworkTransaction
* trans
= helper
.trans();
5244 TestCompletionCallback callback
;
5245 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5246 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5247 const int rv_start_complete
= callback
.WaitForResult();
5248 EXPECT_EQ(OK
, rv_start_complete
);
5250 // Make sure the response has an auth challenge.
5251 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5252 ASSERT_TRUE(response_start
!= NULL
);
5253 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5254 EXPECT_EQ(401, response_start
->headers
->response_code());
5255 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5256 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5257 ASSERT_TRUE(auth_challenge
!= NULL
);
5258 EXPECT_FALSE(auth_challenge
->is_proxy
);
5259 EXPECT_EQ("basic", auth_challenge
->scheme
);
5260 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5262 // Restart with a username/password.
5263 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5264 base::ASCIIToUTF16("bar"));
5265 TestCompletionCallback callback_restart
;
5266 const int rv_restart
= trans
->RestartWithAuth(
5267 credentials
, callback_restart
.callback());
5268 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5269 const int rv_restart_complete
= callback_restart
.WaitForResult();
5270 EXPECT_EQ(OK
, rv_restart_complete
);
5271 // TODO(cbentzel): This is actually the same response object as before, but
5272 // data has changed.
5273 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5274 ASSERT_TRUE(response_restart
!= NULL
);
5275 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5276 EXPECT_EQ(200, response_restart
->headers
->response_code());
5277 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5280 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5281 scoped_ptr
<SpdyFrame
> stream1_syn(
5282 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5283 scoped_ptr
<SpdyFrame
> stream1_body(
5284 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5285 MockWrite writes
[] = {
5286 CreateMockWrite(*stream1_syn
, 1),
5289 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5290 spdy_util_
.AddUrlToHeaderBlock(
5291 "http://www.google.com/foo.dat", initial_headers
.get());
5292 scoped_ptr
<SpdyFrame
> stream2_syn(
5293 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5295 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5296 (*late_headers
)["hello"] = "bye";
5297 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5298 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5299 scoped_ptr
<SpdyFrame
> stream2_headers(
5300 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5308 scoped_ptr
<SpdyFrame
>
5309 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5310 const char kPushedData
[] = "pushed";
5311 scoped_ptr
<SpdyFrame
> stream2_body(
5312 spdy_util_
.ConstructSpdyBodyFrame(
5313 2, kPushedData
, strlen(kPushedData
), true));
5314 MockRead reads
[] = {
5315 CreateMockRead(*stream1_reply
, 2),
5316 CreateMockRead(*stream2_syn
, 3),
5317 CreateMockRead(*stream2_headers
, 4),
5318 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5319 CreateMockRead(*stream2_body
, 5),
5320 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5323 HttpResponseInfo response
;
5324 HttpResponseInfo response2
;
5325 std::string
expected_push_result("pushed");
5326 OrderedSocketData
data(reads
, arraysize(reads
),
5327 writes
, arraysize(writes
));
5328 RunServerPushTest(&data
,
5331 expected_push_result
);
5333 // Verify the SYN_REPLY.
5334 EXPECT_TRUE(response
.headers
.get() != NULL
);
5335 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5337 // Verify the pushed stream.
5338 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5339 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5342 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5343 // We push a stream and attempt to claim it before the headers come down.
5344 scoped_ptr
<SpdyFrame
> stream1_syn(
5345 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5346 scoped_ptr
<SpdyFrame
> stream1_body(
5347 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5348 MockWrite writes
[] = {
5349 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5352 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5353 spdy_util_
.AddUrlToHeaderBlock(
5354 "http://www.google.com/foo.dat", initial_headers
.get());
5355 scoped_ptr
<SpdyFrame
> stream2_syn(
5356 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5358 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5359 (*late_headers
)["hello"] = "bye";
5360 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5361 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5362 scoped_ptr
<SpdyFrame
> stream2_headers(
5363 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5371 scoped_ptr
<SpdyFrame
>
5372 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5373 const char kPushedData
[] = "pushed";
5374 scoped_ptr
<SpdyFrame
> stream2_body(
5375 spdy_util_
.ConstructSpdyBodyFrame(
5376 2, kPushedData
, strlen(kPushedData
), true));
5377 MockRead reads
[] = {
5378 CreateMockRead(*stream1_reply
, 1),
5379 CreateMockRead(*stream2_syn
, 2),
5380 CreateMockRead(*stream1_body
, 3),
5381 CreateMockRead(*stream2_headers
, 4),
5382 CreateMockRead(*stream2_body
, 5),
5383 MockRead(ASYNC
, 0, 6), // EOF
5386 HttpResponseInfo response
;
5387 HttpResponseInfo response2
;
5388 std::string
expected_push_result("pushed");
5389 DeterministicSocketData
data(reads
, arraysize(reads
),
5390 writes
, arraysize(writes
));
5392 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5393 BoundNetLog(), GetParam(), NULL
);
5394 helper
.SetDeterministic();
5395 helper
.AddDeterministicData(&data
);
5396 helper
.RunPreTestSetup();
5398 HttpNetworkTransaction
* trans
= helper
.trans();
5400 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5401 // and the body of the primary stream, but before we've received the HEADERS
5402 // for the pushed stream.
5405 // Start the transaction.
5406 TestCompletionCallback callback
;
5407 int rv
= trans
->Start(
5408 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5409 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5411 rv
= callback
.WaitForResult();
5414 // Request the pushed path. At this point, we've received the push, but the
5415 // headers are not yet complete.
5416 scoped_ptr
<HttpNetworkTransaction
> trans2(
5417 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5419 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5420 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5422 base::RunLoop().RunUntilIdle();
5424 // Read the server push body.
5425 std::string result2
;
5426 ReadResult(trans2
.get(), &data
, &result2
);
5427 // Read the response body.
5429 ReadResult(trans
, &data
, &result
);
5431 // Verify that the received push data is same as the expected push data.
5432 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5433 << "Received data: "
5435 << "||||| Expected data: "
5436 << expected_push_result
;
5438 // Verify the SYN_REPLY.
5439 // Copy the response info, because trans goes away.
5440 response
= *trans
->GetResponseInfo();
5441 response2
= *trans2
->GetResponseInfo();
5443 VerifyStreamsClosed(helper
);
5445 // Verify the SYN_REPLY.
5446 EXPECT_TRUE(response
.headers
.get() != NULL
);
5447 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5449 // Verify the pushed stream.
5450 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5451 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5453 // Read the final EOF (which will close the session)
5456 // Verify that we consumed all test data.
5457 EXPECT_TRUE(data
.at_read_eof());
5458 EXPECT_TRUE(data
.at_write_eof());
5461 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5462 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5463 // We push a stream and attempt to claim it before the headers come down.
5464 scoped_ptr
<SpdyFrame
> stream1_syn(
5465 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5466 scoped_ptr
<SpdyFrame
> stream1_body(
5467 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5468 MockWrite writes
[] = {
5469 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5472 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5473 if (spdy_util_
.spdy_version() < SPDY4
) {
5474 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5475 (*initial_headers
)["alpha"] = "beta";
5477 spdy_util_
.AddUrlToHeaderBlock(
5478 "http://www.google.com/foo.dat", initial_headers
.get());
5479 scoped_ptr
<SpdyFrame
> stream2_syn(
5480 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5482 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5483 (*middle_headers
)["hello"] = "bye";
5484 scoped_ptr
<SpdyFrame
> stream2_headers1(
5485 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5493 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5494 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5495 if (spdy_util_
.spdy_version() < SPDY4
) {
5496 // SPDY4/HTTP2 eliminates use of the :version header.
5497 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5499 scoped_ptr
<SpdyFrame
> stream2_headers2(
5500 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5508 scoped_ptr
<SpdyFrame
>
5509 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5510 const char kPushedData
[] = "pushed";
5511 scoped_ptr
<SpdyFrame
> stream2_body(
5512 spdy_util_
.ConstructSpdyBodyFrame(
5513 2, kPushedData
, strlen(kPushedData
), true));
5514 MockRead reads
[] = {
5515 CreateMockRead(*stream1_reply
, 1),
5516 CreateMockRead(*stream2_syn
, 2),
5517 CreateMockRead(*stream1_body
, 3),
5518 CreateMockRead(*stream2_headers1
, 4),
5519 CreateMockRead(*stream2_headers2
, 5),
5520 CreateMockRead(*stream2_body
, 6),
5521 MockRead(ASYNC
, 0, 7), // EOF
5524 HttpResponseInfo response
;
5525 HttpResponseInfo response2
;
5526 std::string
expected_push_result("pushed");
5527 DeterministicSocketData
data(reads
, arraysize(reads
),
5528 writes
, arraysize(writes
));
5530 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5531 BoundNetLog(), GetParam(), NULL
);
5532 helper
.SetDeterministic();
5533 helper
.AddDeterministicData(&data
);
5534 helper
.RunPreTestSetup();
5536 HttpNetworkTransaction
* trans
= helper
.trans();
5538 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5539 // the first HEADERS frame, and the body of the primary stream, but before
5540 // we've received the final HEADERS for the pushed stream.
5543 // Start the transaction.
5544 TestCompletionCallback callback
;
5545 int rv
= trans
->Start(
5546 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5547 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5549 rv
= callback
.WaitForResult();
5552 // Request the pushed path. At this point, we've received the push, but the
5553 // headers are not yet complete.
5554 scoped_ptr
<HttpNetworkTransaction
> trans2(
5555 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5557 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5560 base::RunLoop().RunUntilIdle();
5562 // Read the server push body.
5563 std::string result2
;
5564 ReadResult(trans2
.get(), &data
, &result2
);
5565 // Read the response body.
5567 ReadResult(trans
, &data
, &result
);
5569 // Verify that the received push data is same as the expected push data.
5570 EXPECT_EQ(expected_push_result
, result2
);
5572 // Verify the SYN_REPLY.
5573 // Copy the response info, because trans goes away.
5574 response
= *trans
->GetResponseInfo();
5575 response2
= *trans2
->GetResponseInfo();
5577 VerifyStreamsClosed(helper
);
5579 // Verify the SYN_REPLY.
5580 EXPECT_TRUE(response
.headers
.get() != NULL
);
5581 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5583 // Verify the pushed stream.
5584 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5585 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5587 // Verify we got all the headers from all header blocks.
5588 if (spdy_util_
.spdy_version() < SPDY4
)
5589 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5590 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5591 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5593 // Read the final EOF (which will close the session)
5596 // Verify that we consumed all test data.
5597 EXPECT_TRUE(data
.at_read_eof());
5598 EXPECT_TRUE(data
.at_write_eof());
5601 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5602 // We push a stream and attempt to claim it before the headers come down.
5603 scoped_ptr
<SpdyFrame
> stream1_syn(
5604 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5605 scoped_ptr
<SpdyFrame
> stream1_body(
5606 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5607 MockWrite writes
[] = {
5608 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5611 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5612 spdy_util_
.AddUrlToHeaderBlock(
5613 "http://www.google.com/foo.dat", initial_headers
.get());
5614 scoped_ptr
<SpdyFrame
> stream2_syn(
5615 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5617 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5618 (*middle_headers
)["hello"] = "bye";
5619 scoped_ptr
<SpdyFrame
> stream2_headers1(
5620 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5628 scoped_ptr
<SpdyFrame
>
5629 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5630 const char kPushedData
[] = "pushed";
5631 scoped_ptr
<SpdyFrame
> stream2_body(
5632 spdy_util_
.ConstructSpdyBodyFrame(
5633 2, kPushedData
, strlen(kPushedData
), true));
5634 MockRead reads
[] = {
5635 CreateMockRead(*stream1_reply
, 1),
5636 CreateMockRead(*stream2_syn
, 2),
5637 CreateMockRead(*stream1_body
, 3),
5638 CreateMockRead(*stream2_headers1
, 4),
5639 CreateMockRead(*stream2_body
, 5),
5640 MockRead(ASYNC
, 0, 6), // EOF
5643 DeterministicSocketData
data(reads
, arraysize(reads
),
5644 writes
, arraysize(writes
));
5646 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5647 BoundNetLog(), GetParam(), NULL
);
5648 helper
.SetDeterministic();
5649 helper
.AddDeterministicData(&data
);
5650 helper
.RunPreTestSetup();
5652 HttpNetworkTransaction
* trans
= helper
.trans();
5654 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5655 // the first HEADERS frame, and the body of the primary stream, but before
5656 // we've received the final HEADERS for the pushed stream.
5659 // Start the transaction.
5660 TestCompletionCallback callback
;
5661 int rv
= trans
->Start(
5662 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5663 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5665 rv
= callback
.WaitForResult();
5668 // Request the pushed path. At this point, we've received the push, but the
5669 // headers are not yet complete.
5670 scoped_ptr
<HttpNetworkTransaction
> trans2(
5671 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5673 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5674 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5676 base::RunLoop().RunUntilIdle();
5678 // Read the server push body.
5679 std::string result2
;
5680 ReadResult(trans2
.get(), &data
, &result2
);
5681 // Read the response body.
5683 ReadResult(trans
, &data
, &result
);
5684 EXPECT_EQ("hello!", result
);
5686 // Verify that we haven't received any push data.
5687 EXPECT_EQ("", result2
);
5689 // Verify the SYN_REPLY.
5690 // Copy the response info, because trans goes away.
5691 HttpResponseInfo response
= *trans
->GetResponseInfo();
5692 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5694 VerifyStreamsClosed(helper
);
5696 // Verify the SYN_REPLY.
5697 EXPECT_TRUE(response
.headers
.get() != NULL
);
5698 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5700 // Read the final EOF (which will close the session).
5703 // Verify that we consumed all test data.
5704 EXPECT_TRUE(data
.at_read_eof());
5705 EXPECT_TRUE(data
.at_write_eof());
5708 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5709 scoped_ptr
<SpdyFrame
> req(
5710 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5711 scoped_ptr
<SpdyFrame
> rst(
5712 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5713 MockWrite writes
[] = {
5714 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5717 scoped_ptr
<SpdyFrame
> stream1_reply(
5718 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5720 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5721 (*late_headers
)["hello"] = "bye";
5722 scoped_ptr
<SpdyFrame
> stream1_headers(
5723 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5730 scoped_ptr
<SpdyFrame
> stream1_body(
5731 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5732 MockRead reads
[] = {
5733 CreateMockRead(*stream1_reply
),
5734 CreateMockRead(*stream1_headers
),
5735 CreateMockRead(*stream1_body
),
5736 MockRead(ASYNC
, 0, 0) // EOF
5739 DelayedSocketData
data(1, reads
, arraysize(reads
),
5740 writes
, arraysize(writes
));
5741 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5742 BoundNetLog(), GetParam(), NULL
);
5743 helper
.RunToCompletion(&data
);
5744 TransactionHelperResult out
= helper
.output();
5745 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5748 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5749 scoped_ptr
<SpdyFrame
> req(
5750 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5751 scoped_ptr
<SpdyFrame
> rst(
5752 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5753 MockWrite writes
[] = {
5754 CreateMockWrite(*req
),
5755 CreateMockWrite(*rst
),
5758 scoped_ptr
<SpdyFrame
> stream1_reply(
5759 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5761 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5762 (*late_headers
)["hello"] = "bye";
5763 scoped_ptr
<SpdyFrame
> stream1_headers(
5764 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5771 scoped_ptr
<SpdyFrame
> stream1_body(
5772 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5773 scoped_ptr
<SpdyFrame
> stream1_body2(
5774 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5775 MockRead reads
[] = {
5776 CreateMockRead(*stream1_reply
),
5777 CreateMockRead(*stream1_body
),
5778 CreateMockRead(*stream1_headers
),
5779 CreateMockRead(*stream1_body2
),
5780 MockRead(ASYNC
, 0, 0) // EOF
5783 DelayedSocketData
data(1, reads
, arraysize(reads
),
5784 writes
, arraysize(writes
));
5785 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5786 BoundNetLog(), GetParam(), NULL
);
5787 helper
.RunToCompletion(&data
);
5788 TransactionHelperResult out
= helper
.output();
5789 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5792 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5793 // In this test we want to verify that we can't accidentally push content
5794 // which can't be pushed by this content server.
5795 // This test assumes that:
5796 // - if we're requesting http://www.foo.com/barbaz
5797 // - the browser has made a connection to "www.foo.com".
5799 // A list of the URL to fetch, followed by the URL being pushed.
5800 static const char* const kTestCases
[] = {
5801 "http://www.google.com/foo.html",
5802 "http://www.google.com:81/foo.js", // Bad port
5804 "http://www.google.com/foo.html",
5805 "https://www.google.com/foo.js", // Bad protocol
5807 "http://www.google.com/foo.html",
5808 "ftp://www.google.com/foo.js", // Invalid Protocol
5810 "http://www.google.com/foo.html",
5811 "http://blat.www.google.com/foo.js", // Cross subdomain
5813 "http://www.google.com/foo.html",
5814 "http://www.foo.com/foo.js", // Cross domain
5817 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5818 const char* url_to_fetch
= kTestCases
[index
];
5819 const char* url_to_push
= kTestCases
[index
+ 1];
5821 scoped_ptr
<SpdyFrame
> stream1_syn(
5822 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5823 scoped_ptr
<SpdyFrame
> stream1_body(
5824 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5825 scoped_ptr
<SpdyFrame
> push_rst(
5826 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5827 MockWrite writes
[] = {
5828 CreateMockWrite(*stream1_syn
, 1),
5829 CreateMockWrite(*push_rst
, 4),
5832 scoped_ptr
<SpdyFrame
>
5833 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5834 scoped_ptr
<SpdyFrame
>
5835 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5840 const char kPushedData
[] = "pushed";
5841 scoped_ptr
<SpdyFrame
> stream2_body(
5842 spdy_util_
.ConstructSpdyBodyFrame(
5843 2, kPushedData
, strlen(kPushedData
), true));
5844 scoped_ptr
<SpdyFrame
> rst(
5845 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5847 MockRead reads
[] = {
5848 CreateMockRead(*stream1_reply
, 2),
5849 CreateMockRead(*stream2_syn
, 3),
5850 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5851 CreateMockRead(*stream2_body
, 6),
5852 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5855 HttpResponseInfo response
;
5856 OrderedSocketData
data(reads
, arraysize(reads
),
5857 writes
, arraysize(writes
));
5859 HttpRequestInfo request
;
5860 request
.method
= "GET";
5861 request
.url
= GURL(url_to_fetch
);
5862 request
.load_flags
= 0;
5864 // Enable cross-origin push. Since we are not using a proxy, this should
5865 // not actually enable cross-origin SPDY push.
5866 scoped_ptr
<SpdySessionDependencies
> session_deps(
5867 CreateSpdySessionDependencies(GetParam()));
5868 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5869 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5870 BoundNetLog(), GetParam(),
5871 session_deps
.release());
5872 helper
.RunPreTestSetup();
5873 helper
.AddData(&data
);
5875 HttpNetworkTransaction
* trans
= helper
.trans();
5877 // Start the transaction with basic parameters.
5878 TestCompletionCallback callback
;
5880 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5882 rv
= callback
.WaitForResult();
5884 // Read the response body.
5886 ReadResult(trans
, &data
, &result
);
5888 // Verify that we consumed all test data.
5889 EXPECT_TRUE(data
.at_read_eof());
5890 EXPECT_TRUE(data
.at_write_eof());
5892 // Verify the SYN_REPLY.
5893 // Copy the response info, because trans goes away.
5894 response
= *trans
->GetResponseInfo();
5896 VerifyStreamsClosed(helper
);
5898 // Verify the SYN_REPLY.
5899 EXPECT_TRUE(response
.headers
.get() != NULL
);
5900 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5904 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5905 // Construct the request.
5906 scoped_ptr
<SpdyFrame
> req(
5907 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5908 scoped_ptr
<SpdyFrame
> req2(
5909 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5910 MockWrite writes
[] = {
5911 CreateMockWrite(*req
, 1),
5912 CreateMockWrite(*req2
, 3),
5915 scoped_ptr
<SpdyFrame
> refused(
5916 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5917 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5918 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5919 MockRead reads
[] = {
5920 CreateMockRead(*refused
, 2),
5921 CreateMockRead(*resp
, 4),
5922 CreateMockRead(*body
, 5),
5923 MockRead(ASYNC
, 0, 6) // EOF
5926 OrderedSocketData
data(reads
, arraysize(reads
),
5927 writes
, arraysize(writes
));
5928 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5929 BoundNetLog(), GetParam(), NULL
);
5931 helper
.RunPreTestSetup();
5932 helper
.AddData(&data
);
5934 HttpNetworkTransaction
* trans
= helper
.trans();
5936 // Start the transaction with basic parameters.
5937 TestCompletionCallback callback
;
5938 int rv
= trans
->Start(
5939 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5940 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5941 rv
= callback
.WaitForResult();
5944 // Verify that we consumed all test data.
5945 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5946 << data
.read_count()
5948 << data
.read_index();
5949 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5950 << data
.write_count()
5952 << data
.write_index();
5954 // Verify the SYN_REPLY.
5955 HttpResponseInfo response
= *trans
->GetResponseInfo();
5956 EXPECT_TRUE(response
.headers
.get() != NULL
);
5957 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5960 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5961 // This first request will start to establish the SpdySession.
5962 // Then we will start the second (MEDIUM priority) and then third
5963 // (HIGHEST priority) request in such a way that the third will actually
5964 // start before the second, causing the second to be numbered differently
5965 // than the order they were created.
5966 scoped_ptr
<SpdyFrame
> req1(
5967 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5968 scoped_ptr
<SpdyFrame
> req2(
5969 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5970 scoped_ptr
<SpdyFrame
> req3(
5971 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5972 MockWrite writes
[] = {
5973 CreateMockWrite(*req1
, 0),
5974 CreateMockWrite(*req2
, 3),
5975 CreateMockWrite(*req3
, 4),
5978 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5979 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5980 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5981 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5982 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5983 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5984 MockRead reads
[] = {
5985 CreateMockRead(*resp1
, 1),
5986 CreateMockRead(*body1
, 2),
5987 CreateMockRead(*resp2
, 5),
5988 CreateMockRead(*body2
, 6),
5989 CreateMockRead(*resp3
, 7),
5990 CreateMockRead(*body3
, 8),
5991 MockRead(ASYNC
, 0, 9) // EOF
5994 DeterministicSocketData
data(reads
, arraysize(reads
),
5995 writes
, arraysize(writes
));
5996 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5997 BoundNetLog(), GetParam(), NULL
);
5998 helper
.SetDeterministic();
5999 helper
.RunPreTestSetup();
6000 helper
.AddDeterministicData(&data
);
6002 // Start the first transaction to set up the SpdySession
6003 HttpNetworkTransaction
* trans
= helper
.trans();
6004 TestCompletionCallback callback
;
6005 HttpRequestInfo info1
= CreateGetRequest();
6006 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
6007 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6009 // Run the message loop, but do not allow the write to complete.
6010 // This leaves the SpdySession with a write pending, which prevents
6011 // SpdySession from attempting subsequent writes until this write completes.
6012 base::RunLoop().RunUntilIdle();
6014 // Now, start both new transactions
6015 HttpRequestInfo info2
= CreateGetRequest();
6016 TestCompletionCallback callback2
;
6017 scoped_ptr
<HttpNetworkTransaction
> trans2(
6018 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
6019 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
6020 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6021 base::RunLoop().RunUntilIdle();
6023 HttpRequestInfo info3
= CreateGetRequest();
6024 TestCompletionCallback callback3
;
6025 scoped_ptr
<HttpNetworkTransaction
> trans3(
6026 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
6027 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
6028 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6029 base::RunLoop().RunUntilIdle();
6031 // We now have two SYN_STREAM frames queued up which will be
6032 // dequeued only once the first write completes, which we
6033 // now allow to happen.
6035 EXPECT_EQ(OK
, callback
.WaitForResult());
6037 // And now we can allow everything else to run to completion.
6040 EXPECT_EQ(OK
, callback2
.WaitForResult());
6041 EXPECT_EQ(OK
, callback3
.WaitForResult());
6043 helper
.VerifyDataConsumed();
6046 // The tests below are only for SPDY/3 and above.
6048 // Test that sent data frames and received WINDOW_UPDATE frames change
6049 // the send_window_size_ correctly.
6051 // WINDOW_UPDATE is different than most other frames in that it can arrive
6052 // while the client is still sending the request body. In order to enforce
6053 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
6054 // socket data provider, so that initial read that is done as soon as the
6055 // stream is created, succeeds and schedules another read. This way reads
6056 // and writes are interleaved; after doing a full frame write, SpdyStream
6057 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
6058 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
6059 // since request has not been completely written, therefore we feed
6060 // enough number of WINDOW_UPDATEs to finish the first read and cause a
6061 // write, leading to a complete write of request body; after that we send
6062 // a reply with a body, to cause a graceful shutdown.
6064 // TODO(agayev): develop a socket data provider where both, reads and
6065 // writes are ordered so that writing tests like these are easy and rewrite
6066 // all these tests using it. Right now we are working around the
6067 // limitations as described above and it's not deterministic, tests may
6068 // fail under specific circumstances.
6069 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
6070 static int kFrameCount
= 2;
6071 scoped_ptr
<std::string
> content(
6072 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6073 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6074 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6075 scoped_ptr
<SpdyFrame
> body(
6076 spdy_util_
.ConstructSpdyBodyFrame(
6077 1, content
->c_str(), content
->size(), false));
6078 scoped_ptr
<SpdyFrame
> body_end(
6079 spdy_util_
.ConstructSpdyBodyFrame(
6080 1, content
->c_str(), content
->size(), true));
6082 MockWrite writes
[] = {
6083 CreateMockWrite(*req
, 0),
6084 CreateMockWrite(*body
, 1),
6085 CreateMockWrite(*body_end
, 2),
6088 static const int32 kDeltaWindowSize
= 0xff;
6089 static const int kDeltaCount
= 4;
6090 scoped_ptr
<SpdyFrame
> window_update(
6091 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6092 scoped_ptr
<SpdyFrame
> window_update_dummy(
6093 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
6094 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6095 MockRead reads
[] = {
6096 CreateMockRead(*window_update_dummy
, 3),
6097 CreateMockRead(*window_update_dummy
, 4),
6098 CreateMockRead(*window_update_dummy
, 5),
6099 CreateMockRead(*window_update
, 6), // Four updates, therefore window
6100 CreateMockRead(*window_update
, 7), // size should increase by
6101 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
6102 CreateMockRead(*window_update
, 9),
6103 CreateMockRead(*resp
, 10),
6104 CreateMockRead(*body_end
, 11),
6105 MockRead(ASYNC
, 0, 0, 12) // EOF
6108 DeterministicSocketData
data(reads
, arraysize(reads
),
6109 writes
, arraysize(writes
));
6111 ScopedVector
<UploadElementReader
> element_readers
;
6112 for (int i
= 0; i
< kFrameCount
; ++i
) {
6113 element_readers
.push_back(
6114 new UploadBytesElementReader(content
->c_str(), content
->size()));
6116 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6118 // Setup the request
6119 HttpRequestInfo request
;
6120 request
.method
= "POST";
6121 request
.url
= GURL(kDefaultURL
);
6122 request
.upload_data_stream
= &upload_data_stream
;
6124 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6125 BoundNetLog(), GetParam(), NULL
);
6126 helper
.SetDeterministic();
6127 helper
.AddDeterministicData(&data
);
6128 helper
.RunPreTestSetup();
6130 HttpNetworkTransaction
* trans
= helper
.trans();
6132 TestCompletionCallback callback
;
6133 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6139 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6140 ASSERT_TRUE(stream
!= NULL
);
6141 ASSERT_TRUE(stream
->stream() != NULL
);
6143 static_cast<int>(SpdySession::GetInitialWindowSize(GetParam().protocol
)) +
6144 kDeltaWindowSize
* kDeltaCount
- kMaxSpdyFrameChunkSize
* kFrameCount
,
6145 stream
->stream()->send_window_size());
6149 rv
= callback
.WaitForResult();
6152 helper
.VerifyDataConsumed();
6155 // Test that received data frames and sent WINDOW_UPDATE frames change
6156 // the recv_window_size_ correctly.
6157 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
6158 const int32 initial_window_size
=
6159 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6160 // Amount of body required to trigger a sent window update.
6161 const size_t kTargetSize
= initial_window_size
/ 2 + 1;
6163 scoped_ptr
<SpdyFrame
> req(
6164 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6165 scoped_ptr
<SpdyFrame
> session_window_update(
6166 spdy_util_
.ConstructSpdyWindowUpdate(0, kTargetSize
));
6167 scoped_ptr
<SpdyFrame
> window_update(
6168 spdy_util_
.ConstructSpdyWindowUpdate(1, kTargetSize
));
6170 std::vector
<MockWrite
> writes
;
6171 writes
.push_back(CreateMockWrite(*req
));
6172 if (GetParam().protocol
>= kProtoSPDY31
)
6173 writes
.push_back(CreateMockWrite(*session_window_update
));
6174 writes
.push_back(CreateMockWrite(*window_update
));
6176 std::vector
<MockRead
> reads
;
6177 scoped_ptr
<SpdyFrame
> resp(
6178 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6179 reads
.push_back(CreateMockRead(*resp
));
6181 ScopedVector
<SpdyFrame
> body_frames
;
6182 const std::string
body_data(4096, 'x');
6183 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
6184 size_t frame_size
= std::min(remaining
, body_data
.size());
6185 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
6186 1, body_data
.data(), frame_size
, false));
6187 reads
.push_back(CreateMockRead(*body_frames
.back()));
6188 remaining
-= frame_size
;
6190 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
6192 DelayedSocketData
data(1, vector_as_array(&reads
), reads
.size(),
6193 vector_as_array(&writes
), writes
.size());
6195 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
6196 BoundNetLog(), GetParam(), NULL
);
6197 helper
.AddData(&data
);
6198 helper
.RunPreTestSetup();
6199 HttpNetworkTransaction
* trans
= helper
.trans();
6201 TestCompletionCallback callback
;
6202 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6204 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6205 rv
= callback
.WaitForResult();
6208 SpdyHttpStream
* stream
=
6209 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6210 ASSERT_TRUE(stream
!= NULL
);
6211 ASSERT_TRUE(stream
->stream() != NULL
);
6213 // All data has been read, but not consumed. The window reflects this.
6214 EXPECT_EQ(static_cast<int>(initial_window_size
- kTargetSize
),
6215 stream
->stream()->recv_window_size());
6217 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6218 ASSERT_TRUE(response
!= NULL
);
6219 ASSERT_TRUE(response
->headers
.get() != NULL
);
6220 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
6221 EXPECT_TRUE(response
->was_fetched_via_spdy
);
6223 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6224 // size increased to default.
6225 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kTargetSize
));
6226 EXPECT_EQ(static_cast<int>(kTargetSize
),
6227 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
6228 EXPECT_EQ(static_cast<int>(initial_window_size
),
6229 stream
->stream()->recv_window_size());
6230 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6232 // Allow scheduled WINDOW_UPDATE frames to write.
6233 base::RunLoop().RunUntilIdle();
6234 helper
.VerifyDataConsumed();
6237 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6238 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6239 // Number of full frames we hope to write (but will not, used to
6240 // set content-length header correctly)
6241 static int kFrameCount
= 3;
6243 scoped_ptr
<std::string
> content(
6244 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6245 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6246 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6247 scoped_ptr
<SpdyFrame
> body(
6248 spdy_util_
.ConstructSpdyBodyFrame(
6249 1, content
->c_str(), content
->size(), false));
6250 scoped_ptr
<SpdyFrame
> rst(
6251 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6253 // We're not going to write a data frame with FIN, we'll receive a bad
6254 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6255 MockWrite writes
[] = {
6256 CreateMockWrite(*req
, 0),
6257 CreateMockWrite(*body
, 2),
6258 CreateMockWrite(*rst
, 3),
6261 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6262 scoped_ptr
<SpdyFrame
> window_update(
6263 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6264 MockRead reads
[] = {
6265 CreateMockRead(*window_update
, 1),
6266 MockRead(ASYNC
, 0, 4) // EOF
6269 DeterministicSocketData
data(reads
, arraysize(reads
),
6270 writes
, arraysize(writes
));
6272 ScopedVector
<UploadElementReader
> element_readers
;
6273 for (int i
= 0; i
< kFrameCount
; ++i
) {
6274 element_readers
.push_back(
6275 new UploadBytesElementReader(content
->c_str(), content
->size()));
6277 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6279 // Setup the request
6280 HttpRequestInfo request
;
6281 request
.method
= "POST";
6282 request
.url
= GURL("http://www.google.com/");
6283 request
.upload_data_stream
= &upload_data_stream
;
6285 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6286 BoundNetLog(), GetParam(), NULL
);
6287 helper
.SetDeterministic();
6288 helper
.RunPreTestSetup();
6289 helper
.AddDeterministicData(&data
);
6290 HttpNetworkTransaction
* trans
= helper
.trans();
6292 TestCompletionCallback callback
;
6293 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6294 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6297 ASSERT_TRUE(callback
.have_result());
6298 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6299 helper
.VerifyDataConsumed();
6302 // Test that after hitting a send window size of 0, the write process
6303 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6305 // This test constructs a POST request followed by enough data frames
6306 // containing 'a' that would make the window size 0, followed by another
6307 // data frame containing default content (which is "hello!") and this frame
6308 // also contains a FIN flag. DelayedSocketData is used to enforce all
6309 // writes go through before a read could happen. However, the last frame
6310 // ("hello!") is not supposed to go through since by the time its turn
6311 // arrives, window size is 0. At this point MessageLoop::Run() called via
6312 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6313 // which returns after performing all possible writes. We use DCHECKS to
6314 // ensure that last data frame is still there and stream has stalled.
6315 // After that, next read is artifically enforced, which causes a
6316 // WINDOW_UPDATE to be read and I/O process resumes.
6317 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6318 const int32 initial_window_size
=
6319 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6320 // Number of frames we need to send to zero out the window size: data
6321 // frames plus SYN_STREAM plus the last data frame; also we need another
6322 // data frame that we will send once the WINDOW_UPDATE is received,
6324 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6326 // Calculate last frame's size; 0 size data frame is legal.
6327 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6329 // Construct content for a data frame of maximum size.
6330 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6332 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6333 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6336 scoped_ptr
<SpdyFrame
> body1(
6337 spdy_util_
.ConstructSpdyBodyFrame(
6338 1, content
.c_str(), content
.size(), false));
6340 // Last frame to zero out the window size.
6341 scoped_ptr
<SpdyFrame
> body2(
6342 spdy_util_
.ConstructSpdyBodyFrame(
6343 1, content
.c_str(), last_frame_size
, false));
6345 // Data frame to be sent once WINDOW_UPDATE frame is received.
6346 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6348 // Fill in mock writes.
6349 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6351 writes
[i
] = CreateMockWrite(*req
);
6352 for (i
= 1; i
< num_writes
- 2; i
++)
6353 writes
[i
] = CreateMockWrite(*body1
);
6354 writes
[i
++] = CreateMockWrite(*body2
);
6355 writes
[i
] = CreateMockWrite(*body3
);
6357 // Construct read frame, give enough space to upload the rest of the
6359 scoped_ptr
<SpdyFrame
> session_window_update(
6360 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6361 scoped_ptr
<SpdyFrame
> window_update(
6362 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6363 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6364 MockRead reads
[] = {
6365 CreateMockRead(*session_window_update
),
6366 CreateMockRead(*session_window_update
),
6367 CreateMockRead(*window_update
),
6368 CreateMockRead(*window_update
),
6369 CreateMockRead(*reply
),
6370 CreateMockRead(*body2
),
6371 CreateMockRead(*body3
),
6372 MockRead(ASYNC
, 0, 0) // EOF
6375 // Skip the session window updates unless we're using SPDY/3.1 and
6377 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6378 size_t num_reads
= arraysize(reads
) - read_offset
;
6380 // Force all writes to happen before any read, last write will not
6381 // actually queue a frame, due to window size being 0.
6382 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6383 writes
.get(), num_writes
);
6385 ScopedVector
<UploadElementReader
> element_readers
;
6386 std::string
upload_data_string(initial_window_size
, 'a');
6387 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6388 element_readers
.push_back(new UploadBytesElementReader(
6389 upload_data_string
.c_str(), upload_data_string
.size()));
6390 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6392 HttpRequestInfo request
;
6393 request
.method
= "POST";
6394 request
.url
= GURL("http://www.google.com/");
6395 request
.upload_data_stream
= &upload_data_stream
;
6396 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6397 BoundNetLog(), GetParam(), NULL
);
6398 helper
.AddData(&data
);
6399 helper
.RunPreTestSetup();
6401 HttpNetworkTransaction
* trans
= helper
.trans();
6403 TestCompletionCallback callback
;
6404 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6405 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6407 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6409 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6410 ASSERT_TRUE(stream
!= NULL
);
6411 ASSERT_TRUE(stream
->stream() != NULL
);
6412 EXPECT_EQ(0, stream
->stream()->send_window_size());
6413 // All the body data should have been read.
6414 // TODO(satorux): This is because of the weirdness in reading the request
6415 // body in OnSendBodyComplete(). See crbug.com/113107.
6416 EXPECT_TRUE(upload_data_stream
.IsEOF());
6417 // But the body is not yet fully sent (kUploadData is not yet sent)
6418 // since we're send-stalled.
6419 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6421 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6422 rv
= callback
.WaitForResult();
6423 helper
.VerifyDataConsumed();
6426 // Test we correctly handle the case where the SETTINGS frame results in
6427 // unstalling the send window.
6428 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6429 const int32 initial_window_size
=
6430 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6432 // Number of frames we need to send to zero out the window size: data
6433 // frames plus SYN_STREAM plus the last data frame; also we need another
6434 // data frame that we will send once the SETTING is received, therefore +3.
6435 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6437 // Calculate last frame's size; 0 size data frame is legal.
6438 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6440 // Construct content for a data frame of maximum size.
6441 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6443 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6444 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6447 scoped_ptr
<SpdyFrame
> body1(
6448 spdy_util_
.ConstructSpdyBodyFrame(
6449 1, content
.c_str(), content
.size(), false));
6451 // Last frame to zero out the window size.
6452 scoped_ptr
<SpdyFrame
> body2(
6453 spdy_util_
.ConstructSpdyBodyFrame(
6454 1, content
.c_str(), last_frame_size
, false));
6456 // Data frame to be sent once SETTINGS frame is received.
6457 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6459 // Fill in mock reads/writes.
6460 std::vector
<MockRead
> reads
;
6461 std::vector
<MockWrite
> writes
;
6463 writes
.push_back(CreateMockWrite(*req
, i
++));
6464 while (i
< num_writes
- 2)
6465 writes
.push_back(CreateMockWrite(*body1
, i
++));
6466 writes
.push_back(CreateMockWrite(*body2
, i
++));
6468 // Construct read frame for SETTINGS that gives enough space to upload the
6469 // rest of the data.
6470 SettingsMap settings
;
6471 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6472 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
* 2);
6473 scoped_ptr
<SpdyFrame
> settings_frame_large(
6474 spdy_util_
.ConstructSpdySettings(settings
));
6476 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6478 scoped_ptr
<SpdyFrame
> session_window_update(
6479 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6480 if (GetParam().protocol
>= kProtoSPDY31
)
6481 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6483 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6484 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6486 writes
.push_back(CreateMockWrite(*body3
, i
++));
6488 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6489 reads
.push_back(CreateMockRead(*reply
, i
++));
6490 reads
.push_back(CreateMockRead(*body2
, i
++));
6491 reads
.push_back(CreateMockRead(*body3
, i
++));
6492 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6494 // Force all writes to happen before any read, last write will not
6495 // actually queue a frame, due to window size being 0.
6496 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6497 vector_as_array(&writes
), writes
.size());
6499 ScopedVector
<UploadElementReader
> element_readers
;
6500 std::string
upload_data_string(initial_window_size
, 'a');
6501 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6502 element_readers
.push_back(new UploadBytesElementReader(
6503 upload_data_string
.c_str(), upload_data_string
.size()));
6504 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6506 HttpRequestInfo request
;
6507 request
.method
= "POST";
6508 request
.url
= GURL("http://www.google.com/");
6509 request
.upload_data_stream
= &upload_data_stream
;
6510 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6511 BoundNetLog(), GetParam(), NULL
);
6512 helper
.SetDeterministic();
6513 helper
.RunPreTestSetup();
6514 helper
.AddDeterministicData(&data
);
6516 HttpNetworkTransaction
* trans
= helper
.trans();
6518 TestCompletionCallback callback
;
6519 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6520 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6522 data
.RunFor(num_writes
- 1); // Write as much as we can.
6524 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6525 ASSERT_TRUE(stream
!= NULL
);
6526 ASSERT_TRUE(stream
->stream() != NULL
);
6527 EXPECT_EQ(0, stream
->stream()->send_window_size());
6529 // All the body data should have been read.
6530 // TODO(satorux): This is because of the weirdness in reading the request
6531 // body in OnSendBodyComplete(). See crbug.com/113107.
6532 EXPECT_TRUE(upload_data_stream
.IsEOF());
6533 // But the body is not yet fully sent (kUploadData is not yet sent)
6534 // since we're send-stalled.
6535 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6537 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6538 rv
= callback
.WaitForResult();
6539 helper
.VerifyDataConsumed();
6540 // If stream is NULL, that means it was unstalled and closed.
6541 EXPECT_TRUE(stream
->stream() == NULL
);
6544 // Test we correctly handle the case where the SETTINGS frame results in a
6545 // negative send window size.
6546 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6547 const int32 initial_window_size
=
6548 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6549 // Number of frames we need to send to zero out the window size: data
6550 // frames plus SYN_STREAM plus the last data frame; also we need another
6551 // data frame that we will send once the SETTING is received, therefore +3.
6552 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6554 // Calculate last frame's size; 0 size data frame is legal.
6555 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6557 // Construct content for a data frame of maximum size.
6558 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6560 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6561 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6564 scoped_ptr
<SpdyFrame
> body1(
6565 spdy_util_
.ConstructSpdyBodyFrame(
6566 1, content
.c_str(), content
.size(), false));
6568 // Last frame to zero out the window size.
6569 scoped_ptr
<SpdyFrame
> body2(
6570 spdy_util_
.ConstructSpdyBodyFrame(
6571 1, content
.c_str(), last_frame_size
, false));
6573 // Data frame to be sent once SETTINGS frame is received.
6574 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6576 // Fill in mock reads/writes.
6577 std::vector
<MockRead
> reads
;
6578 std::vector
<MockWrite
> writes
;
6580 writes
.push_back(CreateMockWrite(*req
, i
++));
6581 while (i
< num_writes
- 2)
6582 writes
.push_back(CreateMockWrite(*body1
, i
++));
6583 writes
.push_back(CreateMockWrite(*body2
, i
++));
6585 // Construct read frame for SETTINGS that makes the send_window_size
6587 SettingsMap new_settings
;
6588 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6589 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
/ 2);
6590 scoped_ptr
<SpdyFrame
> settings_frame_small(
6591 spdy_util_
.ConstructSpdySettings(new_settings
));
6592 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6594 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6595 spdy_util_
.ConstructSpdyWindowUpdate(0, initial_window_size
));
6596 scoped_ptr
<SpdyFrame
> window_update_init_size(
6597 spdy_util_
.ConstructSpdyWindowUpdate(1, initial_window_size
));
6599 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6600 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6601 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6603 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6604 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6606 writes
.push_back(CreateMockWrite(*body3
, i
++));
6608 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6609 reads
.push_back(CreateMockRead(*reply
, i
++));
6610 reads
.push_back(CreateMockRead(*body2
, i
++));
6611 reads
.push_back(CreateMockRead(*body3
, i
++));
6612 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6614 // Force all writes to happen before any read, last write will not
6615 // actually queue a frame, due to window size being 0.
6616 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6617 vector_as_array(&writes
), writes
.size());
6619 ScopedVector
<UploadElementReader
> element_readers
;
6620 std::string
upload_data_string(initial_window_size
, 'a');
6621 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6622 element_readers
.push_back(new UploadBytesElementReader(
6623 upload_data_string
.c_str(), upload_data_string
.size()));
6624 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6626 HttpRequestInfo request
;
6627 request
.method
= "POST";
6628 request
.url
= GURL("http://www.google.com/");
6629 request
.upload_data_stream
= &upload_data_stream
;
6630 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6631 BoundNetLog(), GetParam(), NULL
);
6632 helper
.SetDeterministic();
6633 helper
.RunPreTestSetup();
6634 helper
.AddDeterministicData(&data
);
6636 HttpNetworkTransaction
* trans
= helper
.trans();
6638 TestCompletionCallback callback
;
6639 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6642 data
.RunFor(num_writes
- 1); // Write as much as we can.
6644 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6645 ASSERT_TRUE(stream
!= NULL
);
6646 ASSERT_TRUE(stream
->stream() != NULL
);
6647 EXPECT_EQ(0, stream
->stream()->send_window_size());
6649 // All the body data should have been read.
6650 // TODO(satorux): This is because of the weirdness in reading the request
6651 // body in OnSendBodyComplete(). See crbug.com/113107.
6652 EXPECT_TRUE(upload_data_stream
.IsEOF());
6653 // But the body is not yet fully sent (kUploadData is not yet sent)
6654 // since we're send-stalled.
6655 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6657 // Read in WINDOW_UPDATE or SETTINGS frame.
6658 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6659 rv
= callback
.WaitForResult();
6660 helper
.VerifyDataConsumed();
6663 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnOddPushStreamId
) {
6664 if (spdy_util_
.spdy_version() < SPDY3
)
6667 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
6668 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6669 push_headers
.get());
6670 scoped_ptr
<SpdyFrame
> push(
6671 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 3, 1));
6672 MockRead reads
[] = {CreateMockRead(*push
, 1)};
6674 scoped_ptr
<SpdyFrame
> req(
6675 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6676 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6677 0, GOAWAY_PROTOCOL_ERROR
, "Odd push stream id."));
6678 MockWrite writes
[] = {
6679 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 2),
6682 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6683 NormalSpdyTransactionHelper
helper(
6684 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6685 helper
.RunToCompletion(&data
);
6686 TransactionHelperResult out
= helper
.output();
6687 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6690 TEST_P(SpdyNetworkTransactionTest
,
6691 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted
) {
6692 if (spdy_util_
.spdy_version() < SPDY3
)
6695 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
6696 NULL
, 0, 4, 1, "http://www.google.com/a.dat"));
6697 scoped_ptr
<SpdyHeaderBlock
> push_b_headers(new SpdyHeaderBlock
);
6698 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6699 push_b_headers
.get());
6700 scoped_ptr
<SpdyFrame
> push_b(
6701 spdy_util_
.ConstructInitialSpdyPushFrame(push_b_headers
.Pass(), 2, 1));
6702 MockRead reads
[] = {
6703 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
6706 scoped_ptr
<SpdyFrame
> req(
6707 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6708 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6710 GOAWAY_PROTOCOL_ERROR
,
6711 "New push stream id must be greater than the last accepted."));
6712 MockWrite writes
[] = {
6713 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
6716 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6717 NormalSpdyTransactionHelper
helper(
6718 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6719 helper
.RunToCompletion(&data
);
6720 TransactionHelperResult out
= helper
.output();
6721 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6724 class SpdyNetworkTransactionNoTLSUsageCheckTest
6725 : public SpdyNetworkTransactionTest
{
6727 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6728 // Construct the request.
6729 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyGet(
6730 "https://www.google.com/", false, 1, LOWEST
));
6731 MockWrite writes
[] = {CreateMockWrite(*req
)};
6733 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6734 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6735 MockRead reads
[] = {
6736 CreateMockRead(*resp
), CreateMockRead(*body
),
6737 MockRead(ASYNC
, 0, 0) // EOF
6740 DelayedSocketData
data(
6741 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6742 HttpRequestInfo request
;
6743 request
.method
= "GET";
6744 request
.url
= GURL("https://www.google.com/");
6745 NormalSpdyTransactionHelper
helper(
6746 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6747 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6748 TransactionHelperResult out
= helper
.output();
6749 EXPECT_EQ(OK
, out
.rv
);
6750 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6751 EXPECT_EQ("hello!", out
.response_data
);
6755 //-----------------------------------------------------------------------------
6756 // All tests are run with three different connection types: SPDY after NPN
6757 // negotiation, SPDY without SSL, and SPDY with SSL.
6759 // TODO(akalin): Use ::testing::Combine() when we are able to use
6761 INSTANTIATE_TEST_CASE_P(
6763 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6764 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
)));
6766 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6767 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6768 new SSLSocketDataProvider(ASYNC
, OK
));
6769 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6770 &ssl_provider
->connection_status
);
6772 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6775 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6776 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6777 new SSLSocketDataProvider(ASYNC
, OK
));
6778 // Set to TLS_RSA_WITH_NULL_MD5
6779 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6781 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6784 class SpdyNetworkTransactionTLSUsageCheckTest
6785 : public SpdyNetworkTransactionTest
{
6787 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6788 scoped_ptr
<SpdyFrame
> goaway(
6789 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6790 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6792 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6793 HttpRequestInfo request
;
6794 request
.method
= "GET";
6795 request
.url
= GURL("https://www.google.com/");
6796 NormalSpdyTransactionHelper
helper(
6797 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6798 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6799 TransactionHelperResult out
= helper
.output();
6800 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6804 INSTANTIATE_TEST_CASE_P(
6806 SpdyNetworkTransactionTLSUsageCheckTest
,
6808 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
6809 SpdyNetworkTransactionTestParams(kProtoSPDY4_15
, SPDYNPN
)));
6811 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6812 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6813 new SSLSocketDataProvider(ASYNC
, OK
));
6814 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6815 &ssl_provider
->connection_status
);
6817 RunTLSUsageCheckTest(ssl_provider
.Pass());
6820 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6821 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6822 new SSLSocketDataProvider(ASYNC
, OK
));
6823 // Set to TLS_RSA_WITH_NULL_MD5
6824 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6826 RunTLSUsageCheckTest(ssl_provider
.Pass());