1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/bind_helpers.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_piece.h"
16 #include "base/test/test_file_util.h"
17 #include "net/base/auth.h"
18 #include "net/base/chunked_upload_data_stream.h"
19 #include "net/base/elements_upload_data_stream.h"
20 #include "net/base/request_priority.h"
21 #include "net/base/upload_bytes_element_reader.h"
22 #include "net/base/upload_file_element_reader.h"
23 #include "net/http/http_network_session_peer.h"
24 #include "net/http/http_network_transaction.h"
25 #include "net/http/http_server_properties.h"
26 #include "net/http/http_transaction_test_util.h"
27 #include "net/log/net_log_unittest.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
.SetAlternativeService(
80 HostPortPair("www.google.com", 80),
82 AlternateProtocolFromNextProto(test_params
.protocol
),
83 "www.google.com", 443),
85 session_deps
->use_alternate_protocols
= true;
86 session_deps
->next_protos
= SpdyNextProtos();
89 session_deps
->force_spdy_over_ssl
= false;
90 session_deps
->force_spdy_always
= true;
93 session_deps
->force_spdy_over_ssl
= true;
94 session_deps
->force_spdy_always
= true;
101 SpdySessionDependencies
* CreateSpdySessionDependencies(
102 SpdyNetworkTransactionTestParams test_params
) {
103 SpdySessionDependencies
* session_deps
=
104 new SpdySessionDependencies(test_params
.protocol
);
105 UpdateSpdySessionDependencies(test_params
, session_deps
);
109 SpdySessionDependencies
* CreateSpdySessionDependencies(
110 SpdyNetworkTransactionTestParams test_params
,
111 ProxyService
* proxy_service
) {
112 SpdySessionDependencies
* session_deps
=
113 new SpdySessionDependencies(test_params
.protocol
, proxy_service
);
114 UpdateSpdySessionDependencies(test_params
, session_deps
);
120 class SpdyNetworkTransactionTest
121 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestParams
> {
123 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol
) {
126 virtual ~SpdyNetworkTransactionTest() {
127 // UploadDataStream may post a deletion tasks back to the message loop on
129 upload_data_stream_
.reset();
130 base::RunLoop().RunUntilIdle();
133 void SetUp() override
{
134 google_get_request_initialized_
= false;
135 google_post_request_initialized_
= false;
136 google_chunked_post_request_initialized_
= false;
137 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
140 struct TransactionHelperResult
{
142 std::string status_line
;
143 std::string response_data
;
144 HttpResponseInfo response_info
;
147 // A helper class that handles all the initial npn/ssl setup.
148 class NormalSpdyTransactionHelper
{
150 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
151 RequestPriority priority
,
152 const BoundNetLog
& log
,
153 SpdyNetworkTransactionTestParams test_params
,
154 SpdySessionDependencies
* session_deps
)
157 session_deps_(session_deps
== NULL
?
158 CreateSpdySessionDependencies(test_params
) :
160 session_(SpdySessionDependencies::SpdyCreateSession(
161 session_deps_
.get())),
163 test_params_(test_params
),
164 deterministic_(false),
165 spdy_enabled_(true) {
166 switch (test_params_
.ssl_type
) {
179 ~NormalSpdyTransactionHelper() {
180 // Any test which doesn't close the socket by sending it an EOF will
181 // have a valid session left open, which leaks the entire session pool.
182 // This is just fine - in fact, some of our tests intentionally do this
183 // so that we can check consistency of the SpdySessionPool as the test
184 // finishes. If we had put an EOF on the socket, the SpdySession would
185 // have closed and we wouldn't be able to check the consistency.
187 // Forcefully close existing sessions here.
188 session()->spdy_session_pool()->CloseAllSessions();
191 void SetDeterministic() {
192 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
193 session_deps_
.get());
194 deterministic_
= true;
197 void SetSpdyDisabled() {
198 spdy_enabled_
= false;
202 void RunPreTestSetup() {
203 if (!session_deps_
.get())
204 session_deps_
.reset(CreateSpdySessionDependencies(test_params_
));
205 if (!session_
.get()) {
206 session_
= SpdySessionDependencies::SpdyCreateSession(
207 session_deps_
.get());
210 // We're now ready to use SSL-npn SPDY.
211 trans_
.reset(new HttpNetworkTransaction(priority_
, session_
.get()));
214 // Start the transaction, read some data, finish.
215 void RunDefaultTest() {
216 if (!StartDefaultTest())
221 bool StartDefaultTest() {
222 output_
.rv
= trans_
->Start(&request_
, callback_
.callback(), log_
);
224 // We expect an IO Pending or some sort of error.
225 EXPECT_LT(output_
.rv
, 0);
226 return output_
.rv
== ERR_IO_PENDING
;
229 void FinishDefaultTest() {
230 output_
.rv
= callback_
.WaitForResult();
231 if (output_
.rv
!= OK
) {
232 session_
->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED
);
237 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
238 ASSERT_TRUE(response
!= NULL
);
239 ASSERT_TRUE(response
->headers
.get() != NULL
);
240 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
241 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
242 if (HttpStreamFactory::spdy_enabled()) {
244 HttpResponseInfo::ConnectionInfoFromNextProto(
245 test_params_
.protocol
),
246 response
->connection_info
);
248 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
,
249 response
->connection_info
);
251 if (test_params_
.ssl_type
== SPDYNPN
&& spdy_enabled_
) {
252 EXPECT_TRUE(response
->was_npn_negotiated
);
254 EXPECT_TRUE(!response
->was_npn_negotiated
);
256 // If SPDY is not enabled, a HTTP request should not be diverted
257 // over a SSL session.
258 if (!spdy_enabled_
) {
259 EXPECT_EQ(request_
.url
.SchemeIs("https"),
260 response
->was_npn_negotiated
);
262 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
263 EXPECT_EQ(port_
, response
->socket_address
.port());
264 output_
.status_line
= response
->headers
->GetStatusLine();
265 output_
.response_info
= *response
; // Make a copy so we can verify.
266 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
269 void FinishDefaultTestWithoutVerification() {
270 output_
.rv
= callback_
.WaitForResult();
271 if (output_
.rv
!= OK
)
272 session_
->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED
);
275 // Most tests will want to call this function. In particular, the MockReads
276 // should end with an empty read, and that read needs to be processed to
277 // ensure proper deletion of the spdy_session_pool.
278 void VerifyDataConsumed() {
279 for (DataVector::iterator it
= data_vector_
.begin();
280 it
!= data_vector_
.end(); ++it
) {
281 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
282 << (*it
)->read_count()
284 << (*it
)->read_index();
285 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
286 << (*it
)->write_count()
288 << (*it
)->write_index();
292 // Occasionally a test will expect to error out before certain reads are
293 // processed. In that case we want to explicitly ensure that the reads were
295 void VerifyDataNotConsumed() {
296 for (DataVector::iterator it
= data_vector_
.begin();
297 it
!= data_vector_
.end(); ++it
) {
298 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
299 << (*it
)->read_count()
301 << (*it
)->read_index();
302 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
303 << (*it
)->write_count()
305 << (*it
)->write_index();
309 void RunToCompletion(StaticSocketDataProvider
* data
) {
313 VerifyDataConsumed();
316 void RunToCompletionWithSSLData(
317 StaticSocketDataProvider
* data
,
318 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
320 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
322 VerifyDataConsumed();
325 void AddData(StaticSocketDataProvider
* data
) {
326 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
327 new SSLSocketDataProvider(ASYNC
, OK
));
328 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
331 void AddDataWithSSLSocketDataProvider(
332 StaticSocketDataProvider
* data
,
333 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
334 DCHECK(!deterministic_
);
335 data_vector_
.push_back(data
);
336 if (test_params_
.ssl_type
== SPDYNPN
)
337 ssl_provider
->SetNextProto(test_params_
.protocol
);
339 if (test_params_
.ssl_type
== SPDYNPN
||
340 test_params_
.ssl_type
== SPDYSSL
) {
341 session_deps_
->socket_factory
->AddSSLSocketDataProvider(
344 ssl_vector_
.push_back(ssl_provider
.release());
346 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
347 if (test_params_
.ssl_type
== SPDYNPN
) {
348 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
349 StaticSocketDataProvider
* hanging_non_alternate_protocol_socket
=
350 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
351 hanging_non_alternate_protocol_socket
->set_connect_data(
352 never_finishing_connect
);
353 session_deps_
->socket_factory
->AddSocketDataProvider(
354 hanging_non_alternate_protocol_socket
);
355 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
359 void AddDeterministicData(DeterministicSocketData
* data
) {
360 DCHECK(deterministic_
);
361 data_vector_
.push_back(data
);
362 SSLSocketDataProvider
* ssl_provider
=
363 new SSLSocketDataProvider(ASYNC
, OK
);
364 if (test_params_
.ssl_type
== SPDYNPN
)
365 ssl_provider
->SetNextProto(test_params_
.protocol
);
367 ssl_vector_
.push_back(ssl_provider
);
368 if (test_params_
.ssl_type
== SPDYNPN
||
369 test_params_
.ssl_type
== SPDYSSL
) {
370 session_deps_
->deterministic_socket_factory
->
371 AddSSLSocketDataProvider(ssl_provider
);
373 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
374 if (test_params_
.ssl_type
== SPDYNPN
) {
375 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
376 DeterministicSocketData
* hanging_non_alternate_protocol_socket
=
377 new DeterministicSocketData(NULL
, 0, NULL
, 0);
378 hanging_non_alternate_protocol_socket
->set_connect_data(
379 never_finishing_connect
);
380 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
381 hanging_non_alternate_protocol_socket
);
382 alternate_deterministic_vector_
.push_back(
383 hanging_non_alternate_protocol_socket
);
387 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
390 HttpNetworkTransaction
* trans() { return trans_
.get(); }
391 void ResetTrans() { trans_
.reset(); }
392 TransactionHelperResult
& output() { return output_
; }
393 const HttpRequestInfo
& request() const { return request_
; }
394 const scoped_refptr
<HttpNetworkSession
>& session() const {
397 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
398 return session_deps_
;
400 int port() const { return port_
; }
401 SpdyNetworkTransactionTestParams
test_params() const {
406 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
407 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
408 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
409 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
410 HttpRequestInfo request_
;
411 RequestPriority priority_
;
412 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
413 scoped_refptr
<HttpNetworkSession
> session_
;
414 TransactionHelperResult output_
;
415 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
416 SSLVector ssl_vector_
;
417 TestCompletionCallback callback_
;
418 scoped_ptr
<HttpNetworkTransaction
> trans_
;
419 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
420 DataVector data_vector_
;
421 AlternateVector alternate_vector_
;
422 AlternateDeterministicVector alternate_deterministic_vector_
;
423 const BoundNetLog log_
;
424 SpdyNetworkTransactionTestParams test_params_
;
430 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
431 int expected_status
);
433 void ConnectStatusHelper(const MockRead
& status
);
435 const HttpRequestInfo
& CreateGetPushRequest() {
436 google_get_push_request_
.method
= "GET";
437 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
438 google_get_push_request_
.load_flags
= 0;
439 return google_get_push_request_
;
442 const HttpRequestInfo
& CreateGetRequest() {
443 if (!google_get_request_initialized_
) {
444 google_get_request_
.method
= "GET";
445 google_get_request_
.url
= GURL(kDefaultURL
);
446 google_get_request_
.load_flags
= 0;
447 google_get_request_initialized_
= true;
449 return google_get_request_
;
452 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
453 if (!google_get_request_initialized_
) {
454 google_get_request_
.method
= "GET";
455 google_get_request_
.url
= GURL(kDefaultURL
);
456 google_get_request_
.load_flags
= 0;
457 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
458 google_get_request_initialized_
= true;
460 return google_get_request_
;
463 const HttpRequestInfo
& CreatePostRequest() {
464 if (!google_post_request_initialized_
) {
465 ScopedVector
<UploadElementReader
> element_readers
;
466 element_readers
.push_back(
467 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
468 upload_data_stream_
.reset(
469 new ElementsUploadDataStream(element_readers
.Pass(), 0));
471 google_post_request_
.method
= "POST";
472 google_post_request_
.url
= GURL(kDefaultURL
);
473 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
474 google_post_request_initialized_
= true;
476 return google_post_request_
;
479 const HttpRequestInfo
& CreateFilePostRequest() {
480 if (!google_post_request_initialized_
) {
481 base::FilePath file_path
;
482 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
483 CHECK_EQ(static_cast<int>(kUploadDataSize
),
484 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
486 ScopedVector
<UploadElementReader
> element_readers
;
487 element_readers
.push_back(
488 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
493 upload_data_stream_
.reset(
494 new ElementsUploadDataStream(element_readers
.Pass(), 0));
496 google_post_request_
.method
= "POST";
497 google_post_request_
.url
= GURL(kDefaultURL
);
498 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
499 google_post_request_initialized_
= true;
501 return google_post_request_
;
504 const HttpRequestInfo
& CreateUnreadableFilePostRequest() {
505 if (google_post_request_initialized_
)
506 return google_post_request_
;
508 base::FilePath file_path
;
509 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
510 CHECK_EQ(static_cast<int>(kUploadDataSize
),
511 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
512 CHECK(base::MakeFileUnreadable(file_path
));
514 ScopedVector
<UploadElementReader
> element_readers
;
515 element_readers
.push_back(
516 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
521 upload_data_stream_
.reset(
522 new ElementsUploadDataStream(element_readers
.Pass(), 0));
524 google_post_request_
.method
= "POST";
525 google_post_request_
.url
= GURL(kDefaultURL
);
526 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
527 google_post_request_initialized_
= true;
528 return google_post_request_
;
531 const HttpRequestInfo
& CreateComplexPostRequest() {
532 if (!google_post_request_initialized_
) {
533 const int kFileRangeOffset
= 1;
534 const int kFileRangeLength
= 3;
535 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
537 base::FilePath file_path
;
538 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
539 CHECK_EQ(static_cast<int>(kUploadDataSize
),
540 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
542 ScopedVector
<UploadElementReader
> element_readers
;
543 element_readers
.push_back(
544 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
545 element_readers
.push_back(
546 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
551 element_readers
.push_back(new UploadBytesElementReader(
552 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
553 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
554 upload_data_stream_
.reset(
555 new ElementsUploadDataStream(element_readers
.Pass(), 0));
557 google_post_request_
.method
= "POST";
558 google_post_request_
.url
= GURL(kDefaultURL
);
559 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
560 google_post_request_initialized_
= true;
562 return google_post_request_
;
565 const HttpRequestInfo
& CreateChunkedPostRequest() {
566 if (!google_chunked_post_request_initialized_
) {
567 upload_chunked_data_stream_
.reset(new ChunkedUploadDataStream(0));
568 google_chunked_post_request_
.method
= "POST";
569 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
570 google_chunked_post_request_
.upload_data_stream
=
571 upload_chunked_data_stream_
.get();
572 google_chunked_post_request_initialized_
= true;
574 return google_chunked_post_request_
;
577 // Read the result of a particular transaction, knowing that we've got
578 // multiple transactions in the read pipeline; so as we read, we may have
579 // to skip over data destined for other transactions while we consume
580 // the data for |trans|.
581 int ReadResult(HttpNetworkTransaction
* trans
,
582 StaticSocketDataProvider
* data
,
583 std::string
* result
) {
584 const int kSize
= 3000;
587 scoped_refptr
<IOBufferWithSize
> buf(new IOBufferWithSize(kSize
));
588 TestCompletionCallback callback
;
590 int rv
= trans
->Read(buf
.get(), kSize
, callback
.callback());
591 if (rv
== ERR_IO_PENDING
) {
592 // Multiple transactions may be in the data set. Keep pulling off
593 // reads until we complete our callback.
594 while (!callback
.have_result()) {
595 data
->CompleteRead();
596 base::RunLoop().RunUntilIdle();
598 rv
= callback
.WaitForResult();
599 } else if (rv
<= 0) {
602 result
->append(buf
->data(), rv
);
608 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
609 // This lengthy block is reaching into the pool to dig out the active
610 // session. Once we have the session, we verify that the streams are
611 // all closed and not leaked at this point.
612 const GURL
& url
= helper
.request().url
;
613 int port
= helper
.test_params().ssl_type
== SPDYNPN
? 443 : 80;
614 HostPortPair
host_port_pair(url
.host(), port
);
615 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
616 PRIVACY_MODE_DISABLED
);
618 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
619 base::WeakPtr
<SpdySession
> spdy_session
=
620 session
->spdy_session_pool()->FindAvailableSession(key
, log
);
621 ASSERT_TRUE(spdy_session
!= NULL
);
622 EXPECT_EQ(0u, spdy_session
->num_active_streams());
623 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
626 void RunServerPushTest(OrderedSocketData
* data
,
627 HttpResponseInfo
* response
,
628 HttpResponseInfo
* push_response
,
629 const std::string
& expected
) {
630 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
631 BoundNetLog(), GetParam(), NULL
);
632 helper
.RunPreTestSetup();
633 helper
.AddData(data
);
635 HttpNetworkTransaction
* trans
= helper
.trans();
637 // Start the transaction with basic parameters.
638 TestCompletionCallback callback
;
639 int rv
= trans
->Start(
640 &CreateGetRequest(), callback
.callback(), BoundNetLog());
641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
642 rv
= callback
.WaitForResult();
644 // Request the pushed path.
645 scoped_ptr
<HttpNetworkTransaction
> trans2(
646 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
648 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
649 EXPECT_EQ(ERR_IO_PENDING
, rv
);
650 base::RunLoop().RunUntilIdle();
652 // The data for the pushed path may be coming in more than 1 frame. Compile
653 // the results into a single string.
655 // Read the server push body.
657 ReadResult(trans2
.get(), data
, &result2
);
658 // Read the response body.
660 ReadResult(trans
, data
, &result
);
662 // Verify that we consumed all test data.
663 EXPECT_TRUE(data
->at_read_eof());
664 EXPECT_TRUE(data
->at_write_eof());
666 // Verify that the received push data is same as the expected push data.
667 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
669 << "||||| Expected data: "
672 // Verify the SYN_REPLY.
673 // Copy the response info, because trans goes away.
674 *response
= *trans
->GetResponseInfo();
675 *push_response
= *trans2
->GetResponseInfo();
677 VerifyStreamsClosed(helper
);
680 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
682 helper
->ResetTrans();
685 static void StartTransactionCallback(
686 const scoped_refptr
<HttpNetworkSession
>& session
,
688 scoped_ptr
<HttpNetworkTransaction
> trans(
689 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
690 TestCompletionCallback callback
;
691 HttpRequestInfo request
;
692 request
.method
= "GET";
693 request
.url
= GURL("http://www.google.com/");
694 request
.load_flags
= 0;
695 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
696 EXPECT_EQ(ERR_IO_PENDING
, rv
);
697 callback
.WaitForResult();
700 ChunkedUploadDataStream
* upload_chunked_data_stream() const {
701 return upload_chunked_data_stream_
.get();
704 SpdyTestUtil spdy_util_
;
707 scoped_ptr
<ChunkedUploadDataStream
> upload_chunked_data_stream_
;
708 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
709 bool google_get_request_initialized_
;
710 bool google_post_request_initialized_
;
711 bool google_chunked_post_request_initialized_
;
712 HttpRequestInfo google_get_request_
;
713 HttpRequestInfo google_post_request_
;
714 HttpRequestInfo google_chunked_post_request_
;
715 HttpRequestInfo google_get_push_request_
;
716 base::ScopedTempDir temp_dir_
;
719 //-----------------------------------------------------------------------------
720 // All tests are run with three different connection types: SPDY after NPN
721 // negotiation, SPDY without SSL, and SPDY with SSL.
723 // TODO(akalin): Use ::testing::Combine() when we are able to use
725 INSTANTIATE_TEST_CASE_P(
727 SpdyNetworkTransactionTest
,
729 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNOSSL
),
730 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYSSL
),
731 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
),
732 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNOSSL
),
733 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYSSL
),
734 SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
735 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNOSSL
),
736 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYSSL
),
737 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNPN
)));
739 // Verify HttpNetworkTransaction constructor.
740 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
741 scoped_ptr
<SpdySessionDependencies
> session_deps(
742 CreateSpdySessionDependencies(GetParam()));
743 scoped_refptr
<HttpNetworkSession
> session(
744 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
745 scoped_ptr
<HttpTransaction
> trans(
746 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
749 TEST_P(SpdyNetworkTransactionTest
, Get
) {
750 // Construct the request.
751 scoped_ptr
<SpdyFrame
> req(
752 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
753 MockWrite writes
[] = { CreateMockWrite(*req
) };
755 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
756 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
758 CreateMockRead(*resp
),
759 CreateMockRead(*body
),
760 MockRead(ASYNC
, 0, 0) // EOF
763 DelayedSocketData
data(1, reads
, arraysize(reads
),
764 writes
, arraysize(writes
));
765 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
766 BoundNetLog(), GetParam(), NULL
);
767 helper
.RunToCompletion(&data
);
768 TransactionHelperResult out
= helper
.output();
769 EXPECT_EQ(OK
, out
.rv
);
770 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
771 EXPECT_EQ("hello!", out
.response_data
);
774 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
775 for (RequestPriority p
= MINIMUM_PRIORITY
; p
<= MAXIMUM_PRIORITY
;
776 p
= RequestPriority(p
+ 1)) {
777 // Construct the request.
778 scoped_ptr
<SpdyFrame
> req(
779 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
780 MockWrite writes
[] = { CreateMockWrite(*req
) };
782 SpdyPriority spdy_prio
= 0;
783 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
784 // this repeats the RequestPriority-->SpdyPriority mapping from
785 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
786 // sure it's being done right.
787 if (spdy_util_
.spdy_version() < SPDY3
) {
790 EXPECT_EQ(0, spdy_prio
);
793 EXPECT_EQ(1, spdy_prio
);
797 EXPECT_EQ(2, spdy_prio
);
800 EXPECT_EQ(3, spdy_prio
);
808 EXPECT_EQ(0, spdy_prio
);
811 EXPECT_EQ(1, spdy_prio
);
814 EXPECT_EQ(2, spdy_prio
);
817 EXPECT_EQ(3, spdy_prio
);
820 EXPECT_EQ(4, spdy_prio
);
827 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
828 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
830 CreateMockRead(*resp
),
831 CreateMockRead(*body
),
832 MockRead(ASYNC
, 0, 0) // EOF
835 DelayedSocketData
data(1, reads
, arraysize(reads
),
836 writes
, arraysize(writes
));
837 HttpRequestInfo http_req
= CreateGetRequest();
839 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
841 helper
.RunToCompletion(&data
);
842 TransactionHelperResult out
= helper
.output();
843 EXPECT_EQ(OK
, out
.rv
);
844 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
845 EXPECT_EQ("hello!", out
.response_data
);
849 // Start three gets simultaniously; making sure that multiplexed
850 // streams work properly.
852 // This can't use the TransactionHelper method, since it only
853 // handles a single transaction, and finishes them as soon
854 // as it launches them.
856 // TODO(gavinp): create a working generalized TransactionHelper that
857 // can allow multiple streams in flight.
859 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
860 scoped_ptr
<SpdyFrame
> req(
861 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
862 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
863 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
864 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
866 scoped_ptr
<SpdyFrame
> req2(
867 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
868 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
869 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
870 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
872 scoped_ptr
<SpdyFrame
> req3(
873 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
874 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
875 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
876 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
878 MockWrite writes
[] = {
879 CreateMockWrite(*req
),
880 CreateMockWrite(*req2
),
881 CreateMockWrite(*req3
),
884 CreateMockRead(*resp
, 1),
885 CreateMockRead(*body
),
886 CreateMockRead(*resp2
, 4),
887 CreateMockRead(*body2
),
888 CreateMockRead(*resp3
, 7),
889 CreateMockRead(*body3
),
891 CreateMockRead(*fbody
),
892 CreateMockRead(*fbody2
),
893 CreateMockRead(*fbody3
),
895 MockRead(ASYNC
, 0, 0), // EOF
897 OrderedSocketData
data(reads
, arraysize(reads
),
898 writes
, arraysize(writes
));
899 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
902 TransactionHelperResult out
;
903 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
904 BoundNetLog(), GetParam(), NULL
);
905 helper
.RunPreTestSetup();
906 helper
.AddData(&data
);
907 // We require placeholder data because three get requests are sent out, so
908 // there needs to be three sets of SSL connection data.
909 helper
.AddData(&data_placeholder
);
910 helper
.AddData(&data_placeholder
);
911 scoped_ptr
<HttpNetworkTransaction
> trans1(
912 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
913 scoped_ptr
<HttpNetworkTransaction
> trans2(
914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
915 scoped_ptr
<HttpNetworkTransaction
> trans3(
916 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
918 TestCompletionCallback callback1
;
919 TestCompletionCallback callback2
;
920 TestCompletionCallback callback3
;
922 HttpRequestInfo httpreq1
= CreateGetRequest();
923 HttpRequestInfo httpreq2
= CreateGetRequest();
924 HttpRequestInfo httpreq3
= CreateGetRequest();
926 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
927 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
928 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
929 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
930 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
931 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
933 out
.rv
= callback1
.WaitForResult();
934 ASSERT_EQ(OK
, out
.rv
);
935 out
.rv
= callback3
.WaitForResult();
936 ASSERT_EQ(OK
, out
.rv
);
938 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
939 EXPECT_TRUE(response1
->headers
.get() != NULL
);
940 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
941 out
.status_line
= response1
->headers
->GetStatusLine();
942 out
.response_info
= *response1
;
944 trans2
->GetResponseInfo();
946 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
947 helper
.VerifyDataConsumed();
948 EXPECT_EQ(OK
, out
.rv
);
950 EXPECT_EQ(OK
, out
.rv
);
951 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
952 EXPECT_EQ("hello!hello!", out
.response_data
);
955 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
956 scoped_ptr
<SpdyFrame
> req(
957 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
958 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
959 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
960 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
962 scoped_ptr
<SpdyFrame
> req2(
963 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
964 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
965 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
966 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
968 MockWrite writes
[] = {
969 CreateMockWrite(*req
),
970 CreateMockWrite(*req2
),
973 CreateMockRead(*resp
, 1),
974 CreateMockRead(*body
),
975 CreateMockRead(*resp2
, 4),
976 CreateMockRead(*body2
),
977 CreateMockRead(*fbody
),
978 CreateMockRead(*fbody2
),
979 MockRead(ASYNC
, 0, 0), // EOF
981 OrderedSocketData
data(reads
, arraysize(reads
),
982 writes
, arraysize(writes
));
984 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
986 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
987 data_placeholder
.set_connect_data(never_finishing_connect
);
990 TransactionHelperResult out
;
991 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
992 BoundNetLog(), GetParam(), NULL
);
993 helper
.RunPreTestSetup();
994 helper
.AddData(&data
);
995 // We require placeholder data because two get requests are sent out, so
996 // there needs to be two sets of SSL connection data.
997 helper
.AddData(&data_placeholder
);
998 scoped_ptr
<HttpNetworkTransaction
> trans1(
999 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1000 scoped_ptr
<HttpNetworkTransaction
> trans2(
1001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1003 TestCompletionCallback callback1
;
1004 TestCompletionCallback callback2
;
1006 HttpRequestInfo httpreq1
= CreateGetRequest();
1007 HttpRequestInfo httpreq2
= CreateGetRequest();
1009 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1010 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1011 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1012 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1014 out
.rv
= callback1
.WaitForResult();
1015 ASSERT_EQ(OK
, out
.rv
);
1016 out
.rv
= callback2
.WaitForResult();
1017 ASSERT_EQ(OK
, out
.rv
);
1019 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1020 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1021 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1022 out
.status_line
= response1
->headers
->GetStatusLine();
1023 out
.response_info
= *response1
;
1024 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1025 EXPECT_EQ(OK
, out
.rv
);
1026 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1027 EXPECT_EQ("hello!hello!", out
.response_data
);
1029 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1030 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1031 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1032 out
.status_line
= response2
->headers
->GetStatusLine();
1033 out
.response_info
= *response2
;
1034 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1035 EXPECT_EQ(OK
, out
.rv
);
1036 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1037 EXPECT_EQ("hello!hello!", out
.response_data
);
1039 helper
.VerifyDataConsumed();
1042 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
1043 scoped_ptr
<SpdyFrame
> req(
1044 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1045 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1046 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1047 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1049 scoped_ptr
<SpdyFrame
> req2(
1050 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1051 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1052 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1053 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1055 MockWrite writes
[] = {
1056 CreateMockWrite(*req
),
1057 CreateMockWrite(*req2
),
1059 MockRead reads
[] = {
1060 CreateMockRead(*resp
, 1),
1061 CreateMockRead(*body
),
1062 CreateMockRead(*resp2
, 4),
1063 CreateMockRead(*body2
),
1064 CreateMockRead(*fbody
),
1065 CreateMockRead(*fbody2
),
1066 MockRead(ASYNC
, 0, 0), // EOF
1068 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
1069 writes
, arraysize(writes
));
1071 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1073 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1074 data_placeholder
.set_connect_data(never_finishing_connect
);
1077 TransactionHelperResult out
;
1078 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1079 BoundNetLog(), GetParam(), NULL
);
1080 helper
.RunPreTestSetup();
1081 helper
.AddData(&preconnect_data
);
1082 // We require placeholder data because 3 connections are attempted (first is
1083 // the preconnect, 2nd and 3rd are the never finished connections.
1084 helper
.AddData(&data_placeholder
);
1085 helper
.AddData(&data_placeholder
);
1087 scoped_ptr
<HttpNetworkTransaction
> trans1(
1088 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1089 scoped_ptr
<HttpNetworkTransaction
> trans2(
1090 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1092 TestCompletionCallback callback1
;
1093 TestCompletionCallback callback2
;
1095 HttpRequestInfo httpreq
= CreateGetRequest();
1097 // Preconnect the first.
1098 SSLConfig preconnect_ssl_config
;
1099 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1100 HttpStreamFactory
* http_stream_factory
=
1101 helper
.session()->http_stream_factory();
1102 helper
.session()->GetNextProtos(&preconnect_ssl_config
.next_protos
);
1104 http_stream_factory
->PreconnectStreams(
1105 1, httpreq
, DEFAULT_PRIORITY
,
1106 preconnect_ssl_config
, preconnect_ssl_config
);
1108 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1109 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1110 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1111 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1113 out
.rv
= callback1
.WaitForResult();
1114 ASSERT_EQ(OK
, out
.rv
);
1115 out
.rv
= callback2
.WaitForResult();
1116 ASSERT_EQ(OK
, out
.rv
);
1118 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1119 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1120 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1121 out
.status_line
= response1
->headers
->GetStatusLine();
1122 out
.response_info
= *response1
;
1123 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1124 EXPECT_EQ(OK
, out
.rv
);
1125 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1126 EXPECT_EQ("hello!hello!", out
.response_data
);
1128 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1129 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1130 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1131 out
.status_line
= response2
->headers
->GetStatusLine();
1132 out
.response_info
= *response2
;
1133 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1134 EXPECT_EQ(OK
, out
.rv
);
1135 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1136 EXPECT_EQ("hello!hello!", out
.response_data
);
1138 helper
.VerifyDataConsumed();
1141 // Similar to ThreeGets above, however this test adds a SETTINGS
1142 // frame. The SETTINGS frame is read during the IO loop waiting on
1143 // the first transaction completion, and sets a maximum concurrent
1144 // stream limit of 1. This means that our IO loop exists after the
1145 // second transaction completes, so we can assert on read_index().
1146 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1147 // Construct the request.
1148 scoped_ptr
<SpdyFrame
> req(
1149 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1150 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1151 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1152 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1154 scoped_ptr
<SpdyFrame
> req2(
1155 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1156 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1157 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1158 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1160 scoped_ptr
<SpdyFrame
> req3(
1161 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1162 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1163 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1164 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1166 SettingsMap settings
;
1167 const uint32 max_concurrent_streams
= 1;
1168 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1169 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1170 scoped_ptr
<SpdyFrame
> settings_frame(
1171 spdy_util_
.ConstructSpdySettings(settings
));
1172 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1174 MockWrite writes
[] = {
1175 CreateMockWrite(*req
),
1176 CreateMockWrite(*settings_ack
, 2),
1177 CreateMockWrite(*req2
),
1178 CreateMockWrite(*req3
),
1181 MockRead reads
[] = {
1182 CreateMockRead(*settings_frame
, 1),
1183 CreateMockRead(*resp
),
1184 CreateMockRead(*body
),
1185 CreateMockRead(*fbody
),
1186 CreateMockRead(*resp2
, 8),
1187 CreateMockRead(*body2
),
1188 CreateMockRead(*fbody2
),
1189 CreateMockRead(*resp3
, 13),
1190 CreateMockRead(*body3
),
1191 CreateMockRead(*fbody3
),
1193 MockRead(ASYNC
, 0, 0), // EOF
1196 OrderedSocketData
data(reads
, arraysize(reads
),
1197 writes
, arraysize(writes
));
1198 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1201 TransactionHelperResult out
;
1203 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1204 BoundNetLog(), GetParam(), NULL
);
1205 helper
.RunPreTestSetup();
1206 helper
.AddData(&data
);
1207 // We require placeholder data because three get requests are sent out, so
1208 // there needs to be three sets of SSL connection data.
1209 helper
.AddData(&data_placeholder
);
1210 helper
.AddData(&data_placeholder
);
1211 scoped_ptr
<HttpNetworkTransaction
> trans1(
1212 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1213 scoped_ptr
<HttpNetworkTransaction
> trans2(
1214 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1215 scoped_ptr
<HttpNetworkTransaction
> trans3(
1216 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1218 TestCompletionCallback callback1
;
1219 TestCompletionCallback callback2
;
1220 TestCompletionCallback callback3
;
1222 HttpRequestInfo httpreq1
= CreateGetRequest();
1223 HttpRequestInfo httpreq2
= CreateGetRequest();
1224 HttpRequestInfo httpreq3
= CreateGetRequest();
1226 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1227 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1228 // Run transaction 1 through quickly to force a read of our SETTINGS
1230 out
.rv
= callback1
.WaitForResult();
1231 ASSERT_EQ(OK
, out
.rv
);
1233 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1234 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1235 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1236 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1237 out
.rv
= callback2
.WaitForResult();
1238 ASSERT_EQ(OK
, out
.rv
);
1239 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1241 out
.rv
= callback3
.WaitForResult();
1242 ASSERT_EQ(OK
, out
.rv
);
1244 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1245 ASSERT_TRUE(response1
!= NULL
);
1246 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1247 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1248 out
.status_line
= response1
->headers
->GetStatusLine();
1249 out
.response_info
= *response1
;
1250 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1251 EXPECT_EQ(OK
, out
.rv
);
1252 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1253 EXPECT_EQ("hello!hello!", out
.response_data
);
1255 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1256 out
.status_line
= response2
->headers
->GetStatusLine();
1257 out
.response_info
= *response2
;
1258 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1259 EXPECT_EQ(OK
, out
.rv
);
1260 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1261 EXPECT_EQ("hello!hello!", out
.response_data
);
1263 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1264 out
.status_line
= response3
->headers
->GetStatusLine();
1265 out
.response_info
= *response3
;
1266 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1267 EXPECT_EQ(OK
, out
.rv
);
1268 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1269 EXPECT_EQ("hello!hello!", out
.response_data
);
1271 helper
.VerifyDataConsumed();
1273 EXPECT_EQ(OK
, out
.rv
);
1276 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1277 // a fourth transaction. The third and fourth transactions have
1278 // different data ("hello!" vs "hello!hello!") and because of the
1279 // user specified priority, we expect to see them inverted in
1280 // the response from the server.
1281 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1282 // Construct the request.
1283 scoped_ptr
<SpdyFrame
> req(
1284 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1285 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1286 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1287 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1289 scoped_ptr
<SpdyFrame
> req2(
1290 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1291 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1292 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1293 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1295 scoped_ptr
<SpdyFrame
> req4(
1296 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1297 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1298 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1300 scoped_ptr
<SpdyFrame
> req3(
1301 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1302 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1303 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1304 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1306 SettingsMap settings
;
1307 const uint32 max_concurrent_streams
= 1;
1308 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1309 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1310 scoped_ptr
<SpdyFrame
> settings_frame(
1311 spdy_util_
.ConstructSpdySettings(settings
));
1312 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1314 MockWrite writes
[] = { CreateMockWrite(*req
),
1315 CreateMockWrite(*settings_ack
, 2),
1316 CreateMockWrite(*req2
),
1317 CreateMockWrite(*req4
),
1318 CreateMockWrite(*req3
),
1320 MockRead reads
[] = {
1321 CreateMockRead(*settings_frame
, 1),
1322 CreateMockRead(*resp
),
1323 CreateMockRead(*body
),
1324 CreateMockRead(*fbody
),
1325 CreateMockRead(*resp2
, 8),
1326 CreateMockRead(*body2
),
1327 CreateMockRead(*fbody2
),
1328 CreateMockRead(*resp4
, 14),
1329 CreateMockRead(*fbody4
),
1330 CreateMockRead(*resp3
, 17),
1331 CreateMockRead(*body3
),
1332 CreateMockRead(*fbody3
),
1334 MockRead(ASYNC
, 0, 0), // EOF
1337 OrderedSocketData
data(reads
, arraysize(reads
),
1338 writes
, arraysize(writes
));
1339 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1342 TransactionHelperResult out
;
1343 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1344 BoundNetLog(), GetParam(), NULL
);
1345 helper
.RunPreTestSetup();
1346 helper
.AddData(&data
);
1347 // We require placeholder data because four get requests are sent out, so
1348 // there needs to be four sets of SSL connection data.
1349 helper
.AddData(&data_placeholder
);
1350 helper
.AddData(&data_placeholder
);
1351 helper
.AddData(&data_placeholder
);
1352 scoped_ptr
<HttpNetworkTransaction
> trans1(
1353 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1354 scoped_ptr
<HttpNetworkTransaction
> trans2(
1355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1356 scoped_ptr
<HttpNetworkTransaction
> trans3(
1357 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1358 scoped_ptr
<HttpNetworkTransaction
> trans4(
1359 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1361 TestCompletionCallback callback1
;
1362 TestCompletionCallback callback2
;
1363 TestCompletionCallback callback3
;
1364 TestCompletionCallback callback4
;
1366 HttpRequestInfo httpreq1
= CreateGetRequest();
1367 HttpRequestInfo httpreq2
= CreateGetRequest();
1368 HttpRequestInfo httpreq3
= CreateGetRequest();
1369 HttpRequestInfo httpreq4
= CreateGetRequest();
1371 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1372 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1373 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1374 out
.rv
= callback1
.WaitForResult();
1375 ASSERT_EQ(OK
, out
.rv
);
1377 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1378 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1379 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1380 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1381 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1382 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1384 out
.rv
= callback2
.WaitForResult();
1385 ASSERT_EQ(OK
, out
.rv
);
1386 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1388 out
.rv
= callback3
.WaitForResult();
1389 ASSERT_EQ(OK
, out
.rv
);
1391 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1392 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1393 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1394 out
.status_line
= response1
->headers
->GetStatusLine();
1395 out
.response_info
= *response1
;
1396 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1397 EXPECT_EQ(OK
, out
.rv
);
1398 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1399 EXPECT_EQ("hello!hello!", out
.response_data
);
1401 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1402 out
.status_line
= response2
->headers
->GetStatusLine();
1403 out
.response_info
= *response2
;
1404 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1405 EXPECT_EQ(OK
, out
.rv
);
1406 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1407 EXPECT_EQ("hello!hello!", out
.response_data
);
1409 // notice: response3 gets two hellos, response4 gets one
1410 // hello, so we know dequeuing priority was respected.
1411 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1412 out
.status_line
= response3
->headers
->GetStatusLine();
1413 out
.response_info
= *response3
;
1414 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1415 EXPECT_EQ(OK
, out
.rv
);
1416 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1417 EXPECT_EQ("hello!hello!", out
.response_data
);
1419 out
.rv
= callback4
.WaitForResult();
1420 EXPECT_EQ(OK
, out
.rv
);
1421 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1422 out
.status_line
= response4
->headers
->GetStatusLine();
1423 out
.response_info
= *response4
;
1424 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1425 EXPECT_EQ(OK
, out
.rv
);
1426 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1427 EXPECT_EQ("hello!", out
.response_data
);
1428 helper
.VerifyDataConsumed();
1429 EXPECT_EQ(OK
, out
.rv
);
1432 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1433 // deletes a session in the middle of the transaction to insure
1434 // that we properly remove pendingcreatestream objects from
1436 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1437 // Construct the request.
1438 scoped_ptr
<SpdyFrame
> req(
1439 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1440 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1441 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1442 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1444 scoped_ptr
<SpdyFrame
> req2(
1445 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1446 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1447 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1448 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1450 SettingsMap settings
;
1451 const uint32 max_concurrent_streams
= 1;
1452 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1453 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1454 scoped_ptr
<SpdyFrame
> settings_frame(
1455 spdy_util_
.ConstructSpdySettings(settings
));
1456 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1458 MockWrite writes
[] = {
1459 CreateMockWrite(*req
),
1460 CreateMockWrite(*settings_ack
, 2),
1461 CreateMockWrite(*req2
),
1463 MockRead reads
[] = {
1464 CreateMockRead(*settings_frame
, 1),
1465 CreateMockRead(*resp
),
1466 CreateMockRead(*body
),
1467 CreateMockRead(*fbody
),
1468 CreateMockRead(*resp2
, 8),
1469 CreateMockRead(*body2
),
1470 CreateMockRead(*fbody2
),
1471 MockRead(ASYNC
, 0, 0), // EOF
1474 OrderedSocketData
data(reads
, arraysize(reads
),
1475 writes
, arraysize(writes
));
1476 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1479 TransactionHelperResult out
;
1480 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1481 BoundNetLog(), GetParam(), NULL
);
1482 helper
.RunPreTestSetup();
1483 helper
.AddData(&data
);
1484 // We require placeholder data because three get requests are sent out, so
1485 // there needs to be three sets of SSL connection data.
1486 helper
.AddData(&data_placeholder
);
1487 helper
.AddData(&data_placeholder
);
1488 scoped_ptr
<HttpNetworkTransaction
> trans1(
1489 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1490 scoped_ptr
<HttpNetworkTransaction
> trans2(
1491 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1492 scoped_ptr
<HttpNetworkTransaction
> trans3(
1493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1495 TestCompletionCallback callback1
;
1496 TestCompletionCallback callback2
;
1497 TestCompletionCallback callback3
;
1499 HttpRequestInfo httpreq1
= CreateGetRequest();
1500 HttpRequestInfo httpreq2
= CreateGetRequest();
1501 HttpRequestInfo httpreq3
= CreateGetRequest();
1503 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1504 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1505 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1506 out
.rv
= callback1
.WaitForResult();
1507 ASSERT_EQ(OK
, out
.rv
);
1509 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1510 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1511 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1512 delete trans3
.release();
1513 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1514 out
.rv
= callback2
.WaitForResult();
1515 ASSERT_EQ(OK
, out
.rv
);
1517 EXPECT_EQ(8U, data
.read_index());
1519 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1520 ASSERT_TRUE(response1
!= NULL
);
1521 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1522 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1523 out
.status_line
= response1
->headers
->GetStatusLine();
1524 out
.response_info
= *response1
;
1525 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1526 EXPECT_EQ(OK
, out
.rv
);
1527 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1528 EXPECT_EQ("hello!hello!", out
.response_data
);
1530 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1531 ASSERT_TRUE(response2
!= NULL
);
1532 out
.status_line
= response2
->headers
->GetStatusLine();
1533 out
.response_info
= *response2
;
1534 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1535 EXPECT_EQ(OK
, out
.rv
);
1536 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1537 EXPECT_EQ("hello!hello!", out
.response_data
);
1538 helper
.VerifyDataConsumed();
1539 EXPECT_EQ(OK
, out
.rv
);
1544 // The KillerCallback will delete the transaction on error as part of the
1546 class KillerCallback
: public TestCompletionCallbackBase
{
1548 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1549 : transaction_(transaction
),
1550 callback_(base::Bind(&KillerCallback::OnComplete
,
1551 base::Unretained(this))) {
1554 ~KillerCallback() override
{}
1556 const CompletionCallback
& callback() const { return callback_
; }
1559 void OnComplete(int result
) {
1561 delete transaction_
;
1566 HttpNetworkTransaction
* transaction_
;
1567 CompletionCallback callback_
;
1572 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1573 // closes the socket while we have a pending transaction waiting for
1574 // a pending stream creation. http://crbug.com/52901
1575 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1576 // Construct the request.
1577 scoped_ptr
<SpdyFrame
> req(
1578 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1579 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1580 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1581 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1583 scoped_ptr
<SpdyFrame
> req2(
1584 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1585 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1587 SettingsMap settings
;
1588 const uint32 max_concurrent_streams
= 1;
1589 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1590 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1591 scoped_ptr
<SpdyFrame
> settings_frame(
1592 spdy_util_
.ConstructSpdySettings(settings
));
1593 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1595 MockWrite writes
[] = {
1596 CreateMockWrite(*req
),
1597 CreateMockWrite(*settings_ack
, 2),
1598 CreateMockWrite(*req2
),
1600 MockRead reads
[] = {
1601 CreateMockRead(*settings_frame
, 1),
1602 CreateMockRead(*resp
),
1603 CreateMockRead(*body
),
1604 CreateMockRead(*fin_body
),
1605 CreateMockRead(*resp2
, 8),
1606 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1609 OrderedSocketData
data(reads
, arraysize(reads
),
1610 writes
, arraysize(writes
));
1611 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1614 TransactionHelperResult out
;
1615 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1616 BoundNetLog(), GetParam(), NULL
);
1617 helper
.RunPreTestSetup();
1618 helper
.AddData(&data
);
1619 // We require placeholder data because three get requests are sent out, so
1620 // there needs to be three sets of SSL connection data.
1621 helper
.AddData(&data_placeholder
);
1622 helper
.AddData(&data_placeholder
);
1623 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1624 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1625 HttpNetworkTransaction
* trans3(
1626 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1628 TestCompletionCallback callback1
;
1629 TestCompletionCallback callback2
;
1630 KillerCallback
callback3(trans3
);
1632 HttpRequestInfo httpreq1
= CreateGetRequest();
1633 HttpRequestInfo httpreq2
= CreateGetRequest();
1634 HttpRequestInfo httpreq3
= CreateGetRequest();
1636 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1637 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1638 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1639 out
.rv
= callback1
.WaitForResult();
1640 ASSERT_EQ(OK
, out
.rv
);
1642 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1643 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1644 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1645 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1646 out
.rv
= callback3
.WaitForResult();
1647 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1649 EXPECT_EQ(6U, data
.read_index());
1651 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1652 ASSERT_TRUE(response1
!= NULL
);
1653 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1654 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1655 out
.status_line
= response1
->headers
->GetStatusLine();
1656 out
.response_info
= *response1
;
1657 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1658 EXPECT_EQ(OK
, out
.rv
);
1660 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1661 ASSERT_TRUE(response2
!= NULL
);
1662 out
.status_line
= response2
->headers
->GetStatusLine();
1663 out
.response_info
= *response2
;
1664 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1665 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1667 helper
.VerifyDataConsumed();
1670 // Test that a simple PUT request works.
1671 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1672 // Setup the request
1673 HttpRequestInfo request
;
1674 request
.method
= "PUT";
1675 request
.url
= GURL("http://www.google.com/");
1677 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1678 spdy_util_
.ConstructPutHeaderBlock("http://www.google.com", 0));
1679 scoped_ptr
<SpdyFrame
> req(
1680 spdy_util_
.ConstructSpdySyn(1, *put_headers
, LOWEST
, false, true));
1681 MockWrite writes
[] = {
1682 CreateMockWrite(*req
),
1685 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1686 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1687 MockRead reads
[] = {
1688 CreateMockRead(*resp
),
1689 CreateMockRead(*body
),
1690 MockRead(ASYNC
, 0, 0) // EOF
1693 DelayedSocketData
data(1, reads
, arraysize(reads
),
1694 writes
, arraysize(writes
));
1695 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1696 BoundNetLog(), GetParam(), NULL
);
1697 helper
.RunToCompletion(&data
);
1698 TransactionHelperResult out
= helper
.output();
1700 EXPECT_EQ(OK
, out
.rv
);
1701 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1704 // Test that a simple HEAD request works.
1705 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1706 // Setup the request
1707 HttpRequestInfo request
;
1708 request
.method
= "HEAD";
1709 request
.url
= GURL("http://www.google.com/");
1711 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1712 spdy_util_
.ConstructHeadHeaderBlock("http://www.google.com", 0));
1713 scoped_ptr
<SpdyFrame
> req(
1714 spdy_util_
.ConstructSpdySyn(1, *head_headers
, LOWEST
, false, true));
1715 MockWrite writes
[] = {
1716 CreateMockWrite(*req
),
1719 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1720 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1721 MockRead reads
[] = {
1722 CreateMockRead(*resp
),
1723 CreateMockRead(*body
),
1724 MockRead(ASYNC
, 0, 0) // EOF
1727 DelayedSocketData
data(1, reads
, arraysize(reads
),
1728 writes
, arraysize(writes
));
1729 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1730 BoundNetLog(), GetParam(), NULL
);
1731 helper
.RunToCompletion(&data
);
1732 TransactionHelperResult out
= helper
.output();
1734 EXPECT_EQ(OK
, out
.rv
);
1735 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1738 // Test that a simple POST works.
1739 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1740 scoped_ptr
<SpdyFrame
> req(
1741 spdy_util_
.ConstructSpdyPost(
1742 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1743 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1744 MockWrite writes
[] = {
1745 CreateMockWrite(*req
),
1746 CreateMockWrite(*body
), // POST upload frame
1749 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1750 MockRead reads
[] = {
1751 CreateMockRead(*resp
),
1752 CreateMockRead(*body
),
1753 MockRead(ASYNC
, 0, 0) // EOF
1756 DelayedSocketData
data(2, reads
, arraysize(reads
),
1757 writes
, arraysize(writes
));
1758 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
1759 BoundNetLog(), GetParam(), NULL
);
1760 helper
.RunToCompletion(&data
);
1761 TransactionHelperResult out
= helper
.output();
1762 EXPECT_EQ(OK
, out
.rv
);
1763 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1764 EXPECT_EQ("hello!", out
.response_data
);
1767 // Test that a POST with a file works.
1768 TEST_P(SpdyNetworkTransactionTest
, FilePost
) {
1769 scoped_ptr
<SpdyFrame
> req(
1770 spdy_util_
.ConstructSpdyPost(
1771 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1772 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1773 MockWrite writes
[] = {
1774 CreateMockWrite(*req
),
1775 CreateMockWrite(*body
), // POST upload frame
1778 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1779 MockRead reads
[] = {
1780 CreateMockRead(*resp
),
1781 CreateMockRead(*body
),
1782 MockRead(ASYNC
, 0, 0) // EOF
1785 DelayedSocketData
data(2, reads
, arraysize(reads
),
1786 writes
, arraysize(writes
));
1787 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(), DEFAULT_PRIORITY
,
1788 BoundNetLog(), GetParam(), NULL
);
1789 helper
.RunToCompletion(&data
);
1790 TransactionHelperResult out
= helper
.output();
1791 EXPECT_EQ(OK
, out
.rv
);
1792 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1793 EXPECT_EQ("hello!", out
.response_data
);
1796 // Test that a POST with a unreadable file fails.
1797 TEST_P(SpdyNetworkTransactionTest
, UnreadableFilePost
) {
1798 MockWrite writes
[] = {
1799 MockWrite(ASYNC
, 0, 0) // EOF
1801 MockRead reads
[] = {
1802 MockRead(ASYNC
, 0, 0) // EOF
1805 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1806 NormalSpdyTransactionHelper
helper(CreateUnreadableFilePostRequest(),
1808 BoundNetLog(), GetParam(), NULL
);
1809 helper
.RunPreTestSetup();
1810 helper
.AddData(&data
);
1811 helper
.RunDefaultTest();
1813 base::RunLoop().RunUntilIdle();
1814 helper
.VerifyDataNotConsumed();
1815 EXPECT_EQ(ERR_ACCESS_DENIED
, helper
.output().rv
);
1818 // Test that a complex POST works.
1819 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1820 scoped_ptr
<SpdyFrame
> req(
1821 spdy_util_
.ConstructSpdyPost(
1822 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1823 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1824 MockWrite writes
[] = {
1825 CreateMockWrite(*req
),
1826 CreateMockWrite(*body
), // POST upload frame
1829 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1830 MockRead reads
[] = {
1831 CreateMockRead(*resp
),
1832 CreateMockRead(*body
),
1833 MockRead(ASYNC
, 0, 0) // EOF
1836 DelayedSocketData
data(2, reads
, arraysize(reads
),
1837 writes
, arraysize(writes
));
1838 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1840 BoundNetLog(), GetParam(), NULL
);
1841 helper
.RunToCompletion(&data
);
1842 TransactionHelperResult out
= helper
.output();
1843 EXPECT_EQ(OK
, out
.rv
);
1844 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1845 EXPECT_EQ("hello!", out
.response_data
);
1848 // Test that a chunked POST works.
1849 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1850 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1851 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1852 MockWrite writes
[] = {
1853 CreateMockWrite(*req
),
1854 CreateMockWrite(*body
),
1857 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1858 MockRead reads
[] = {
1859 CreateMockRead(*resp
),
1860 CreateMockRead(*body
),
1861 MockRead(ASYNC
, 0, 0) // EOF
1864 DelayedSocketData
data(2, reads
, arraysize(reads
),
1865 writes
, arraysize(writes
));
1866 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1868 BoundNetLog(), GetParam(), NULL
);
1870 // These chunks get merged into a single frame when being sent.
1871 const int kFirstChunkSize
= kUploadDataSize
/2;
1872 upload_chunked_data_stream()->AppendData(kUploadData
, kFirstChunkSize
, false);
1873 upload_chunked_data_stream()->AppendData(
1874 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1876 helper
.RunToCompletion(&data
);
1877 TransactionHelperResult out
= helper
.output();
1878 EXPECT_EQ(OK
, out
.rv
);
1879 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1880 EXPECT_EQ(kUploadData
, out
.response_data
);
1883 // Test that a chunked POST works with chunks appended after transaction starts.
1884 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1885 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1886 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1887 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1888 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1889 MockWrite writes
[] = {
1890 CreateMockWrite(*req
),
1891 CreateMockWrite(*chunk1
),
1892 CreateMockWrite(*chunk2
),
1893 CreateMockWrite(*chunk3
),
1896 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1897 MockRead reads
[] = {
1898 CreateMockRead(*resp
),
1899 CreateMockRead(*chunk1
),
1900 CreateMockRead(*chunk2
),
1901 CreateMockRead(*chunk3
),
1902 MockRead(ASYNC
, 0, 0) // EOF
1905 DelayedSocketData
data(4, reads
, arraysize(reads
),
1906 writes
, arraysize(writes
));
1907 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1909 BoundNetLog(), GetParam(), NULL
);
1911 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1913 helper
.RunPreTestSetup();
1914 helper
.AddData(&data
);
1915 ASSERT_TRUE(helper
.StartDefaultTest());
1917 base::RunLoop().RunUntilIdle();
1918 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, false);
1919 base::RunLoop().RunUntilIdle();
1920 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
1922 helper
.FinishDefaultTest();
1923 helper
.VerifyDataConsumed();
1925 std::string expected_response
;
1926 expected_response
+= kUploadData
;
1927 expected_response
+= kUploadData
;
1928 expected_response
+= kUploadData
;
1930 TransactionHelperResult out
= helper
.output();
1931 EXPECT_EQ(OK
, out
.rv
);
1932 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1933 EXPECT_EQ(expected_response
, out
.response_data
);
1936 // Test that a POST without any post data works.
1937 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1938 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1939 // Setup the request
1940 HttpRequestInfo request
;
1941 request
.method
= "POST";
1942 request
.url
= GURL(kRequestUrl
);
1943 // Create an empty UploadData.
1944 request
.upload_data_stream
= NULL
;
1946 // When request.upload_data_stream is NULL for post, content-length is
1947 // expected to be 0.
1948 scoped_ptr
<SpdyHeaderBlock
> req_block(
1949 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, 0));
1950 scoped_ptr
<SpdyFrame
> req(
1951 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1953 MockWrite writes
[] = {
1954 CreateMockWrite(*req
),
1957 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1958 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1959 MockRead reads
[] = {
1960 CreateMockRead(*resp
),
1961 CreateMockRead(*body
),
1962 MockRead(ASYNC
, 0, 0) // EOF
1965 DelayedSocketData
data(1, reads
, arraysize(reads
),
1966 writes
, arraysize(writes
));
1968 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1969 BoundNetLog(), GetParam(), NULL
);
1970 helper
.RunToCompletion(&data
);
1971 TransactionHelperResult out
= helper
.output();
1972 EXPECT_EQ(OK
, out
.rv
);
1973 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1974 EXPECT_EQ("hello!", out
.response_data
);
1977 // Test that a simple POST works.
1978 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1979 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1980 // Create an empty UploadDataStream.
1981 ScopedVector
<UploadElementReader
> element_readers
;
1982 ElementsUploadDataStream
stream(element_readers
.Pass(), 0);
1984 // Setup the request
1985 HttpRequestInfo request
;
1986 request
.method
= "POST";
1987 request
.url
= GURL(kRequestUrl
);
1988 request
.upload_data_stream
= &stream
;
1990 const uint64 kContentLength
= 0;
1992 scoped_ptr
<SpdyHeaderBlock
> req_block(
1993 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, kContentLength
));
1994 scoped_ptr
<SpdyFrame
> req(
1995 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1997 MockWrite writes
[] = {
1998 CreateMockWrite(*req
),
2001 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2002 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2003 MockRead reads
[] = {
2004 CreateMockRead(*resp
),
2005 CreateMockRead(*body
),
2006 MockRead(ASYNC
, 0, 0) // EOF
2009 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
2011 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
2012 BoundNetLog(), GetParam(), NULL
);
2013 helper
.RunToCompletion(&data
);
2014 TransactionHelperResult out
= helper
.output();
2015 EXPECT_EQ(OK
, out
.rv
);
2016 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2017 EXPECT_EQ("hello!", out
.response_data
);
2020 // While we're doing a post, the server sends the reply before upload completes.
2021 TEST_P(SpdyNetworkTransactionTest
, ResponseBeforePostCompletes
) {
2022 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
2023 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2024 MockWrite writes
[] = {
2025 CreateMockWrite(*req
, 0),
2026 CreateMockWrite(*body
, 3),
2028 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2029 MockRead reads
[] = {
2030 CreateMockRead(*resp
, 1),
2031 CreateMockRead(*body
, 2),
2032 MockRead(ASYNC
, 0, 4) // EOF
2035 // Write the request headers, and read the complete response
2036 // while still waiting for chunked request data.
2037 DeterministicSocketData
data(reads
, arraysize(reads
),
2038 writes
, arraysize(writes
));
2039 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
2041 BoundNetLog(), GetParam(), NULL
);
2042 helper
.SetDeterministic();
2043 helper
.RunPreTestSetup();
2044 helper
.AddDeterministicData(&data
);
2046 ASSERT_TRUE(helper
.StartDefaultTest());
2048 // Process the request headers, SYN_REPLY, and response body.
2049 // The request body is still in flight.
2052 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
2053 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2055 // Finish sending the request body.
2056 upload_chunked_data_stream()->AppendData(kUploadData
, kUploadDataSize
, true);
2059 std::string response_body
;
2060 EXPECT_EQ(OK
, ReadTransaction(helper
.trans(), &response_body
));
2061 EXPECT_EQ(kUploadData
, response_body
);
2062 helper
.VerifyDataConsumed();
2065 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2066 // socket causes the TCP write to return zero. This test checks that the client
2067 // tries to queue up the RST_STREAM frame again.
2068 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2069 scoped_ptr
<SpdyFrame
> req(
2070 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2071 scoped_ptr
<SpdyFrame
> rst(
2072 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2073 MockWrite writes
[] = {
2074 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2075 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2076 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2079 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2080 MockRead reads
[] = {
2081 CreateMockRead(*resp
.get(), 1, ASYNC
),
2082 MockRead(ASYNC
, 0, 0, 4) // EOF
2085 DeterministicSocketData
data(reads
, arraysize(reads
),
2086 writes
, arraysize(writes
));
2087 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2088 BoundNetLog(), GetParam(), NULL
);
2089 helper
.SetDeterministic();
2090 helper
.RunPreTestSetup();
2091 helper
.AddDeterministicData(&data
);
2092 HttpNetworkTransaction
* trans
= helper
.trans();
2094 TestCompletionCallback callback
;
2095 int rv
= trans
->Start(
2096 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2097 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2101 helper
.ResetTrans();
2105 helper
.VerifyDataConsumed();
2108 // Test that the transaction doesn't crash when we don't have a reply.
2109 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2110 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2111 MockRead reads
[] = {
2112 CreateMockRead(*body
),
2113 MockRead(ASYNC
, 0, 0) // EOF
2116 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2117 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2118 BoundNetLog(), GetParam(), NULL
);
2119 helper
.RunToCompletion(&data
);
2120 TransactionHelperResult out
= helper
.output();
2121 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2124 // Test that the transaction doesn't crash when we get two replies on the same
2125 // stream ID. See http://crbug.com/45639.
2126 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2127 scoped_ptr
<SpdyFrame
> req(
2128 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2129 scoped_ptr
<SpdyFrame
> rst(
2130 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2131 MockWrite writes
[] = {
2132 CreateMockWrite(*req
),
2133 CreateMockWrite(*rst
),
2136 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2137 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2138 MockRead reads
[] = {
2139 CreateMockRead(*resp
),
2140 CreateMockRead(*resp
),
2141 CreateMockRead(*body
),
2142 MockRead(ASYNC
, 0, 0) // EOF
2145 DelayedSocketData
data(1, reads
, arraysize(reads
),
2146 writes
, arraysize(writes
));
2148 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2149 BoundNetLog(), GetParam(), NULL
);
2150 helper
.RunPreTestSetup();
2151 helper
.AddData(&data
);
2153 HttpNetworkTransaction
* trans
= helper
.trans();
2155 TestCompletionCallback callback
;
2156 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2158 rv
= callback
.WaitForResult();
2161 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2162 ASSERT_TRUE(response
!= NULL
);
2163 EXPECT_TRUE(response
->headers
.get() != NULL
);
2164 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2165 std::string response_data
;
2166 rv
= ReadTransaction(trans
, &response_data
);
2167 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2169 helper
.VerifyDataConsumed();
2172 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2173 // Construct the request.
2174 scoped_ptr
<SpdyFrame
> req(
2175 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2176 scoped_ptr
<SpdyFrame
> rst(
2177 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2178 MockWrite writes
[] = {
2179 CreateMockWrite(*req
),
2180 CreateMockWrite(*rst
),
2183 const char* const headers
[] = {
2184 "transfer-encoding", "chunked"
2186 scoped_ptr
<SpdyFrame
> resp(
2187 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2188 scoped_ptr
<SpdyFrame
> body(
2189 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2190 MockRead reads
[] = {
2191 CreateMockRead(*resp
),
2192 CreateMockRead(*body
),
2193 MockRead(ASYNC
, 0, 0) // EOF
2196 DelayedSocketData
data(1, reads
, arraysize(reads
),
2197 writes
, arraysize(writes
));
2198 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2199 BoundNetLog(), GetParam(), NULL
);
2200 helper
.RunToCompletion(&data
);
2201 TransactionHelperResult out
= helper
.output();
2202 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2204 helper
.session()->spdy_session_pool()->CloseAllSessions();
2205 helper
.VerifyDataConsumed();
2208 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2209 // Construct the request.
2210 scoped_ptr
<SpdyFrame
> req(
2211 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2212 scoped_ptr
<SpdyFrame
> rst(
2213 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2214 MockWrite writes
[] = {
2215 CreateMockWrite(*req
),
2216 CreateMockWrite(*rst
),
2219 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2220 const char* const headers
[] = {
2221 "transfer-encoding", "chunked"
2223 scoped_ptr
<SpdyFrame
> push(
2224 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2225 2, 1, "http://www.google.com/1"));
2226 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2227 MockRead reads
[] = {
2228 CreateMockRead(*resp
),
2229 CreateMockRead(*push
),
2230 CreateMockRead(*body
),
2231 MockRead(ASYNC
, 0, 0) // EOF
2234 DelayedSocketData
data(1, reads
, arraysize(reads
),
2235 writes
, arraysize(writes
));
2236 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2237 BoundNetLog(), GetParam(), NULL
);
2238 helper
.RunToCompletion(&data
);
2239 TransactionHelperResult out
= helper
.output();
2240 EXPECT_EQ(OK
, out
.rv
);
2241 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2242 EXPECT_EQ("hello!", out
.response_data
);
2244 helper
.session()->spdy_session_pool()->CloseAllSessions();
2245 helper
.VerifyDataConsumed();
2248 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2249 // Construct the request.
2250 scoped_ptr
<SpdyFrame
> req(
2251 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2252 MockWrite writes
[] = {
2253 CreateMockWrite(*req
),
2256 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2257 MockRead reads
[] = {
2258 CreateMockRead(*resp
),
2259 // This following read isn't used by the test, except during the
2260 // RunUntilIdle() call at the end since the SpdySession survives the
2261 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2262 // MockRead will do here.
2263 MockRead(ASYNC
, 0, 0) // EOF
2266 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2267 writes
, arraysize(writes
));
2269 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2270 BoundNetLog(), GetParam(), NULL
);
2271 helper
.RunPreTestSetup();
2272 helper
.AddData(&data
);
2273 HttpNetworkTransaction
* trans
= helper
.trans();
2275 TestCompletionCallback callback
;
2276 int rv
= trans
->Start(
2277 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2278 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2279 helper
.ResetTrans(); // Cancel the transaction.
2281 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2282 // MockClientSocketFactory) are still alive.
2283 base::RunLoop().RunUntilIdle();
2284 helper
.VerifyDataNotConsumed();
2287 // Verify that the client sends a Rst Frame upon cancelling the stream.
2288 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2289 scoped_ptr
<SpdyFrame
> req(
2290 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2291 scoped_ptr
<SpdyFrame
> rst(
2292 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2293 MockWrite writes
[] = {
2294 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2295 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2298 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2299 MockRead reads
[] = {
2300 CreateMockRead(*resp
, 1, ASYNC
),
2301 MockRead(ASYNC
, 0, 0, 3) // EOF
2304 DeterministicSocketData
data(reads
, arraysize(reads
),
2305 writes
, arraysize(writes
));
2307 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2310 helper
.SetDeterministic();
2311 helper
.RunPreTestSetup();
2312 helper
.AddDeterministicData(&data
);
2313 HttpNetworkTransaction
* trans
= helper
.trans();
2315 TestCompletionCallback callback
;
2317 int rv
= trans
->Start(
2318 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2319 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2323 helper
.ResetTrans();
2327 helper
.VerifyDataConsumed();
2330 // Verify that the client can correctly deal with the user callback attempting
2331 // to start another transaction on a session that is closing down. See
2332 // http://crbug.com/47455
2333 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2334 scoped_ptr
<SpdyFrame
> req(
2335 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2336 MockWrite writes
[] = { CreateMockWrite(*req
) };
2337 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2339 // The indicated length of this frame is longer than its actual length. When
2340 // the session receives an empty frame after this one, it shuts down the
2341 // session, and calls the read callback with the incomplete data.
2342 const uint8 kGetBodyFrame2
[] = {
2343 0x00, 0x00, 0x00, 0x01,
2344 0x01, 0x00, 0x00, 0x07,
2345 'h', 'e', 'l', 'l', 'o', '!',
2348 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2349 MockRead reads
[] = {
2350 CreateMockRead(*resp
, 2),
2351 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2352 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2353 arraysize(kGetBodyFrame2
), 4),
2354 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2355 MockRead(ASYNC
, 0, 0, 6), // EOF
2357 MockRead reads2
[] = {
2358 CreateMockRead(*resp
, 2),
2359 MockRead(ASYNC
, 0, 0, 3), // EOF
2362 OrderedSocketData
data(reads
, arraysize(reads
),
2363 writes
, arraysize(writes
));
2364 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2365 writes2
, arraysize(writes2
));
2367 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2368 BoundNetLog(), GetParam(), NULL
);
2369 helper
.RunPreTestSetup();
2370 helper
.AddData(&data
);
2371 helper
.AddData(&data2
);
2372 HttpNetworkTransaction
* trans
= helper
.trans();
2374 // Start the transaction with basic parameters.
2375 TestCompletionCallback callback
;
2376 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2377 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2378 rv
= callback
.WaitForResult();
2380 const int kSize
= 3000;
2381 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSize
));
2385 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2387 // This forces an err_IO_pending, which sets the callback.
2388 data
.CompleteRead();
2389 // This finishes the read.
2390 data
.CompleteRead();
2391 helper
.VerifyDataConsumed();
2394 // Verify that the client can correctly deal with the user callback deleting the
2395 // transaction. Failures will usually be valgrind errors. See
2396 // http://crbug.com/46925
2397 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2398 scoped_ptr
<SpdyFrame
> req(
2399 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2400 MockWrite writes
[] = { CreateMockWrite(*req
) };
2402 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2403 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2404 MockRead reads
[] = {
2405 CreateMockRead(*resp
.get(), 2),
2406 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2407 CreateMockRead(*body
.get(), 4),
2408 MockRead(ASYNC
, 0, 0, 5), // EOF
2411 OrderedSocketData
data(reads
, arraysize(reads
),
2412 writes
, arraysize(writes
));
2414 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2415 BoundNetLog(), GetParam(), NULL
);
2416 helper
.RunPreTestSetup();
2417 helper
.AddData(&data
);
2418 HttpNetworkTransaction
* trans
= helper
.trans();
2420 // Start the transaction with basic parameters.
2421 TestCompletionCallback callback
;
2422 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2424 rv
= callback
.WaitForResult();
2426 // Setup a user callback which will delete the session, and clear out the
2427 // memory holding the stream object. Note that the callback deletes trans.
2428 const int kSize
= 3000;
2429 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSize
));
2433 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2434 base::Unretained(&helper
)));
2435 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2436 data
.CompleteRead();
2438 // Finish running rest of tasks.
2439 base::RunLoop().RunUntilIdle();
2440 helper
.VerifyDataConsumed();
2443 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2444 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2445 scoped_ptr
<SpdyHeaderBlock
> headers(
2446 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2447 (*headers
)["user-agent"] = "";
2448 (*headers
)["accept-encoding"] = "gzip, deflate";
2449 scoped_ptr
<SpdyHeaderBlock
> headers2(
2450 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2451 (*headers2
)["user-agent"] = "";
2452 (*headers2
)["accept-encoding"] = "gzip, deflate";
2454 // Setup writes/reads to www.google.com
2455 scoped_ptr
<SpdyFrame
> req(
2456 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2457 scoped_ptr
<SpdyFrame
> req2(
2458 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2459 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2460 MockWrite writes
[] = {
2461 CreateMockWrite(*req
, 1),
2463 MockRead reads
[] = {
2464 CreateMockRead(*resp
, 2),
2465 MockRead(ASYNC
, 0, 0, 3) // EOF
2468 // Setup writes/reads to www.foo.com
2469 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2470 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2471 MockWrite writes2
[] = {
2472 CreateMockWrite(*req2
, 1),
2474 MockRead reads2
[] = {
2475 CreateMockRead(*resp2
, 2),
2476 CreateMockRead(*body2
, 3),
2477 MockRead(ASYNC
, 0, 0, 4) // EOF
2479 OrderedSocketData
data(reads
, arraysize(reads
),
2480 writes
, arraysize(writes
));
2481 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2482 writes2
, arraysize(writes2
));
2484 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2487 SpdyURLRequestContext
spdy_url_request_context(
2488 GetParam().protocol
,
2489 false /* force_spdy_over_ssl*/,
2490 true /* force_spdy_always */);
2491 scoped_ptr
<URLRequest
> r(spdy_url_request_context
.CreateRequest(
2492 GURL("http://www.google.com/"), DEFAULT_PRIORITY
, &d
));
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(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(spdy_url_request_context
.CreateRequest(
2584 GURL("http://www.google.com/"), DEFAULT_PRIORITY
, &d
));
2585 spdy_url_request_context
.socket_factory().
2586 AddSocketDataProvider(&data
);
2589 base::RunLoop().Run();
2591 EXPECT_EQ(0, d
.received_redirect_count());
2592 std::string
contents("hello!");
2593 EXPECT_EQ(contents
, d
.data_received());
2595 scoped_ptr
<URLRequest
> r2(spdy_url_request_context
.CreateRequest(
2596 GURL("http://www.google.com/foo.dat"), DEFAULT_PRIORITY
, &d2
));
2597 spdy_url_request_context
.socket_factory().
2598 AddSocketDataProvider(&data2
);
2600 d2
.set_quit_on_redirect(true);
2602 base::RunLoop().Run();
2603 EXPECT_EQ(1, d2
.received_redirect_count());
2605 r2
->FollowDeferredRedirect();
2606 base::RunLoop().Run();
2607 EXPECT_EQ(1, d2
.response_started_count());
2608 EXPECT_FALSE(d2
.received_data_before_response());
2609 EXPECT_EQ(URLRequestStatus::SUCCESS
, r2
->status().status());
2610 std::string
contents2("hello!");
2611 EXPECT_EQ(contents2
, d2
.data_received());
2613 data
.CompleteRead();
2614 data2
.CompleteRead();
2615 EXPECT_TRUE(data
.at_read_eof());
2616 EXPECT_TRUE(data
.at_write_eof());
2617 EXPECT_TRUE(data2
.at_read_eof());
2618 EXPECT_TRUE(data2
.at_write_eof());
2621 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2622 scoped_ptr
<SpdyFrame
> stream1_syn(
2623 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2624 scoped_ptr
<SpdyFrame
> stream1_body(
2625 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2626 MockWrite writes
[] = {
2627 CreateMockWrite(*stream1_syn
, 1),
2630 scoped_ptr
<SpdyFrame
>
2631 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2632 scoped_ptr
<SpdyFrame
>
2633 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2637 "http://www.google.com/foo.dat"));
2638 const char kPushedData
[] = "pushed";
2639 scoped_ptr
<SpdyFrame
> stream2_body(
2640 spdy_util_
.ConstructSpdyBodyFrame(
2641 2, kPushedData
, strlen(kPushedData
), true));
2642 MockRead reads
[] = {
2643 CreateMockRead(*stream1_reply
, 2),
2644 CreateMockRead(*stream2_syn
, 3),
2645 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2646 CreateMockRead(*stream2_body
, 5),
2647 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2650 HttpResponseInfo response
;
2651 HttpResponseInfo response2
;
2652 std::string
expected_push_result("pushed");
2653 OrderedSocketData
data(reads
, arraysize(reads
),
2654 writes
, arraysize(writes
));
2655 RunServerPushTest(&data
,
2658 expected_push_result
);
2660 // Verify the SYN_REPLY.
2661 EXPECT_TRUE(response
.headers
.get() != NULL
);
2662 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2664 // Verify the pushed stream.
2665 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2666 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2669 TEST_P(SpdyNetworkTransactionTest
, ServerPushBeforeSynReply
) {
2670 scoped_ptr
<SpdyFrame
> stream1_syn(
2671 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2672 scoped_ptr
<SpdyFrame
> stream1_body(
2673 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2674 MockWrite writes
[] = {
2675 CreateMockWrite(*stream1_syn
, 1),
2678 scoped_ptr
<SpdyFrame
>
2679 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2680 scoped_ptr
<SpdyFrame
>
2681 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2685 "http://www.google.com/foo.dat"));
2686 const char kPushedData
[] = "pushed";
2687 scoped_ptr
<SpdyFrame
> stream2_body(
2688 spdy_util_
.ConstructSpdyBodyFrame(
2689 2, kPushedData
, strlen(kPushedData
), true));
2690 MockRead reads
[] = {
2691 CreateMockRead(*stream2_syn
, 2),
2692 CreateMockRead(*stream1_reply
, 3),
2693 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2694 CreateMockRead(*stream2_body
, 5),
2695 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2698 HttpResponseInfo response
;
2699 HttpResponseInfo response2
;
2700 std::string
expected_push_result("pushed");
2701 OrderedSocketData
data(reads
, arraysize(reads
),
2702 writes
, arraysize(writes
));
2703 RunServerPushTest(&data
,
2706 expected_push_result
);
2708 // Verify the SYN_REPLY.
2709 EXPECT_TRUE(response
.headers
.get() != NULL
);
2710 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2712 // Verify the pushed stream.
2713 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2714 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2717 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2718 scoped_ptr
<SpdyFrame
> stream1_syn(
2719 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2720 MockWrite writes
[] = { CreateMockWrite(*stream1_syn
, 1), };
2722 scoped_ptr
<SpdyFrame
>
2723 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2724 scoped_ptr
<SpdyFrame
>
2725 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2729 "http://www.google.com/foo.dat"));
2730 const char kPushedData
[] = "pushed";
2731 scoped_ptr
<SpdyFrame
> stream2_body(
2732 spdy_util_
.ConstructSpdyBodyFrame(
2733 2, kPushedData
, strlen(kPushedData
), true));
2734 scoped_ptr
<SpdyFrame
>
2735 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2736 MockRead reads
[] = {
2737 CreateMockRead(*stream1_reply
, 2),
2738 CreateMockRead(*stream2_syn
, 3),
2739 CreateMockRead(*stream2_body
, 4),
2740 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2741 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2744 HttpResponseInfo response
;
2745 HttpResponseInfo response2
;
2746 std::string
expected_push_result("pushed");
2747 OrderedSocketData
data(reads
, arraysize(reads
),
2748 writes
, arraysize(writes
));
2749 RunServerPushTest(&data
,
2752 expected_push_result
);
2754 // Verify the SYN_REPLY.
2755 EXPECT_TRUE(response
.headers
.get() != NULL
);
2756 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2758 // Verify the pushed stream.
2759 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2760 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2763 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2764 scoped_ptr
<SpdyFrame
> stream1_syn(
2765 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2766 scoped_ptr
<SpdyFrame
> stream1_body(
2767 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2768 MockWrite writes
[] = {
2769 CreateMockWrite(*stream1_syn
, 1),
2772 scoped_ptr
<SpdyFrame
>
2773 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2774 scoped_ptr
<SpdyFrame
>
2775 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2779 "http://www.google.com/foo.dat"));
2780 scoped_ptr
<SpdyFrame
> stream2_rst(
2781 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2782 MockRead reads
[] = {
2783 CreateMockRead(*stream1_reply
, 2),
2784 CreateMockRead(*stream2_syn
, 3),
2785 CreateMockRead(*stream2_rst
, 4),
2786 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2787 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2790 OrderedSocketData
data(reads
, arraysize(reads
),
2791 writes
, arraysize(writes
));
2792 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2793 BoundNetLog(), GetParam(), NULL
);
2795 helper
.RunPreTestSetup();
2796 helper
.AddData(&data
);
2798 HttpNetworkTransaction
* trans
= helper
.trans();
2800 // Start the transaction with basic parameters.
2801 TestCompletionCallback callback
;
2802 int rv
= trans
->Start(
2803 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2804 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2805 rv
= callback
.WaitForResult();
2808 // Verify that we consumed all test data.
2809 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2810 << data
.read_count()
2812 << data
.read_index();
2813 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2814 << data
.write_count()
2816 << data
.write_index();
2818 // Verify the SYN_REPLY.
2819 HttpResponseInfo response
= *trans
->GetResponseInfo();
2820 EXPECT_TRUE(response
.headers
.get() != NULL
);
2821 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2824 // Verify that we don't leak streams and that we properly send a reset
2825 // if the server pushes the same stream twice.
2826 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2827 scoped_ptr
<SpdyFrame
> stream1_syn(
2828 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2829 scoped_ptr
<SpdyFrame
> stream1_body(
2830 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2831 scoped_ptr
<SpdyFrame
> stream3_rst(
2832 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR
));
2833 MockWrite writes
[] = {
2834 CreateMockWrite(*stream1_syn
, 1),
2835 CreateMockWrite(*stream3_rst
, 5),
2838 scoped_ptr
<SpdyFrame
>
2839 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2840 scoped_ptr
<SpdyFrame
>
2841 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2845 "http://www.google.com/foo.dat"));
2846 const char kPushedData
[] = "pushed";
2847 scoped_ptr
<SpdyFrame
> stream2_body(
2848 spdy_util_
.ConstructSpdyBodyFrame(
2849 2, kPushedData
, strlen(kPushedData
), true));
2850 scoped_ptr
<SpdyFrame
>
2851 stream3_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2855 "http://www.google.com/foo.dat"));
2856 MockRead reads
[] = {
2857 CreateMockRead(*stream1_reply
, 2),
2858 CreateMockRead(*stream2_syn
, 3),
2859 CreateMockRead(*stream3_syn
, 4),
2860 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
2861 CreateMockRead(*stream2_body
, 7),
2862 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
2865 HttpResponseInfo response
;
2866 HttpResponseInfo response2
;
2867 std::string
expected_push_result("pushed");
2868 OrderedSocketData
data(reads
, arraysize(reads
),
2869 writes
, arraysize(writes
));
2870 RunServerPushTest(&data
,
2873 expected_push_result
);
2875 // Verify the SYN_REPLY.
2876 EXPECT_TRUE(response
.headers
.get() != NULL
);
2877 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2879 // Verify the pushed stream.
2880 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2881 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2884 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2885 scoped_ptr
<SpdyFrame
> stream1_syn(
2886 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2887 scoped_ptr
<SpdyFrame
> stream1_body(
2888 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2889 MockWrite writes
[] = {
2890 CreateMockWrite(*stream1_syn
, 1),
2893 scoped_ptr
<SpdyFrame
>
2894 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2895 scoped_ptr
<SpdyFrame
>
2896 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2900 "http://www.google.com/foo.dat"));
2901 static const char kPushedData
[] = "pushed my darling hello my baby";
2902 scoped_ptr
<SpdyFrame
> stream2_body_base(
2903 spdy_util_
.ConstructSpdyBodyFrame(
2904 2, kPushedData
, strlen(kPushedData
), true));
2905 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2906 scoped_ptr
<SpdyFrame
> stream2_body1(
2907 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2908 scoped_ptr
<SpdyFrame
> stream2_body2(
2909 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2910 scoped_ptr
<SpdyFrame
> stream2_body3(
2911 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2912 kChunkSize
, false));
2913 scoped_ptr
<SpdyFrame
> stream2_body4(
2914 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2915 stream2_body_base
->size() - 3 * kChunkSize
, false));
2916 MockRead reads
[] = {
2917 CreateMockRead(*stream1_reply
, 2),
2918 CreateMockRead(*stream2_syn
, 3),
2919 CreateMockRead(*stream2_body1
, 4),
2920 CreateMockRead(*stream2_body2
, 5),
2921 CreateMockRead(*stream2_body3
, 6),
2922 CreateMockRead(*stream2_body4
, 7),
2923 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
2924 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
2927 HttpResponseInfo response
;
2928 HttpResponseInfo response2
;
2929 std::string
expected_push_result("pushed my darling hello my baby");
2930 OrderedSocketData
data(reads
, arraysize(reads
),
2931 writes
, arraysize(writes
));
2932 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2934 // Verify the SYN_REPLY.
2935 EXPECT_TRUE(response
.headers
.get() != NULL
);
2936 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2938 // Verify the pushed stream.
2939 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2940 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2943 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2944 scoped_ptr
<SpdyFrame
> stream1_syn(
2945 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2946 scoped_ptr
<SpdyFrame
> stream1_body(
2947 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2948 MockWrite writes
[] = {
2949 CreateMockWrite(*stream1_syn
, 1),
2952 scoped_ptr
<SpdyFrame
>
2953 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2954 scoped_ptr
<SpdyFrame
>
2955 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2959 "http://www.google.com/foo.dat"));
2960 static const char kPushedData
[] = "pushed my darling hello my baby";
2961 scoped_ptr
<SpdyFrame
> stream2_body_base(
2962 spdy_util_
.ConstructSpdyBodyFrame(
2963 2, kPushedData
, strlen(kPushedData
), true));
2964 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2965 scoped_ptr
<SpdyFrame
> stream2_body1(
2966 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2967 scoped_ptr
<SpdyFrame
> stream2_body2(
2968 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2969 scoped_ptr
<SpdyFrame
> stream2_body3(
2970 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2971 kChunkSize
, false));
2972 scoped_ptr
<SpdyFrame
> stream2_body4(
2973 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2974 stream2_body_base
->size() - 3 * kChunkSize
, false));
2975 MockRead reads
[] = {
2976 CreateMockRead(*stream1_reply
, 2),
2977 CreateMockRead(*stream2_syn
, 3),
2978 CreateMockRead(*stream2_body1
, 4),
2979 CreateMockRead(*stream2_body2
, 5),
2980 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2981 CreateMockRead(*stream2_body3
, 7),
2982 CreateMockRead(*stream2_body4
, 8),
2983 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
2984 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
2987 HttpResponseInfo response
;
2988 HttpResponseInfo response2
;
2989 OrderedSocketData
data(reads
, arraysize(reads
),
2990 writes
, arraysize(writes
));
2991 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2993 // Verify the SYN_REPLY.
2994 EXPECT_TRUE(response
.headers
.get() != NULL
);
2995 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2997 // Verify the pushed stream.
2998 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2999 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3002 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
3003 if (spdy_util_
.spdy_version() == SPDY4
) {
3004 // PUSH_PROMISE with stream id 0 is connection-level error.
3005 // TODO(baranovich): Test session going away.
3009 scoped_ptr
<SpdyFrame
> stream1_syn(
3010 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3011 scoped_ptr
<SpdyFrame
> stream1_body(
3012 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3013 scoped_ptr
<SpdyFrame
> stream2_rst(
3014 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
3015 MockWrite writes
[] = {
3016 CreateMockWrite(*stream1_syn
, 1),
3017 CreateMockWrite(*stream2_rst
, 4),
3020 scoped_ptr
<SpdyFrame
>
3021 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3022 scoped_ptr
<SpdyFrame
>
3023 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3027 "http://www.google.com/foo.dat"));
3028 MockRead reads
[] = {
3029 CreateMockRead(*stream1_reply
, 2),
3030 CreateMockRead(*stream2_syn
, 3),
3031 CreateMockRead(*stream1_body
, 4),
3032 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3035 OrderedSocketData
data(reads
, arraysize(reads
),
3036 writes
, arraysize(writes
));
3037 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3038 BoundNetLog(), GetParam(), NULL
);
3040 helper
.RunPreTestSetup();
3041 helper
.AddData(&data
);
3043 HttpNetworkTransaction
* trans
= helper
.trans();
3045 // Start the transaction with basic parameters.
3046 TestCompletionCallback callback
;
3047 int rv
= trans
->Start(
3048 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3050 rv
= callback
.WaitForResult();
3053 // Verify that we consumed all test data.
3054 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3055 << data
.read_count()
3057 << data
.read_index();
3058 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3059 << data
.write_count()
3061 << data
.write_index();
3063 // Verify the SYN_REPLY.
3064 HttpResponseInfo response
= *trans
->GetResponseInfo();
3065 EXPECT_TRUE(response
.headers
.get() != NULL
);
3066 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3069 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3070 scoped_ptr
<SpdyFrame
> stream1_syn(
3071 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3072 scoped_ptr
<SpdyFrame
> stream1_body(
3073 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3074 scoped_ptr
<SpdyFrame
> stream2_rst(
3075 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM
));
3076 MockWrite writes
[] = {
3077 CreateMockWrite(*stream1_syn
, 1),
3078 CreateMockWrite(*stream2_rst
, 4),
3081 scoped_ptr
<SpdyFrame
>
3082 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3083 scoped_ptr
<SpdyFrame
>
3084 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3088 "http://www.google.com/foo.dat"));
3089 MockRead reads
[] = {
3090 CreateMockRead(*stream1_reply
, 2),
3091 CreateMockRead(*stream2_syn
, 3),
3092 CreateMockRead(*stream1_body
, 4),
3093 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3096 OrderedSocketData
data(reads
, arraysize(reads
),
3097 writes
, arraysize(writes
));
3098 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3099 BoundNetLog(), GetParam(), NULL
);
3101 helper
.RunPreTestSetup();
3102 helper
.AddData(&data
);
3104 HttpNetworkTransaction
* trans
= helper
.trans();
3106 // Start the transaction with basic parameters.
3107 TestCompletionCallback callback
;
3108 int rv
= trans
->Start(
3109 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3110 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3111 rv
= callback
.WaitForResult();
3114 // Verify that we consumed all test data.
3115 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3116 << data
.read_count()
3118 << data
.read_index();
3119 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3120 << data
.write_count()
3122 << data
.write_index();
3124 // Verify the SYN_REPLY.
3125 HttpResponseInfo response
= *trans
->GetResponseInfo();
3126 EXPECT_TRUE(response
.headers
.get() != NULL
);
3127 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3130 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3131 scoped_ptr
<SpdyFrame
> stream1_syn(
3132 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3133 scoped_ptr
<SpdyFrame
> stream1_body(
3134 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3135 scoped_ptr
<SpdyFrame
> stream2_rst(
3136 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
3137 MockWrite writes
[] = {
3138 CreateMockWrite(*stream1_syn
, 1),
3139 CreateMockWrite(*stream2_rst
, 4),
3142 scoped_ptr
<SpdyFrame
>
3143 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3144 scoped_ptr
<SpdyHeaderBlock
> incomplete_headers(new SpdyHeaderBlock());
3145 (*incomplete_headers
)["hello"] = "bye";
3146 (*incomplete_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
3147 (*incomplete_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
3148 scoped_ptr
<SpdyFrame
> stream2_syn(spdy_util_
.ConstructInitialSpdyPushFrame(
3149 incomplete_headers
.Pass(), 2, 1));
3150 MockRead reads
[] = {
3151 CreateMockRead(*stream1_reply
, 2),
3152 CreateMockRead(*stream2_syn
, 3),
3153 CreateMockRead(*stream1_body
, 4),
3154 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3157 OrderedSocketData
data(reads
, arraysize(reads
),
3158 writes
, arraysize(writes
));
3159 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3160 BoundNetLog(), GetParam(), NULL
);
3162 helper
.RunPreTestSetup();
3163 helper
.AddData(&data
);
3165 HttpNetworkTransaction
* trans
= helper
.trans();
3167 // Start the transaction with basic parameters.
3168 TestCompletionCallback callback
;
3169 int rv
= trans
->Start(
3170 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3171 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3172 rv
= callback
.WaitForResult();
3174 // Verify that we consumed all test data.
3175 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3176 << data
.read_count()
3178 << data
.read_index();
3179 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3180 << data
.write_count()
3182 << data
.write_index();
3184 // Verify the SYN_REPLY.
3185 HttpResponseInfo response
= *trans
->GetResponseInfo();
3186 EXPECT_TRUE(response
.headers
.get() != NULL
);
3187 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3190 // Verify that various SynReply headers parse correctly through the
3192 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3193 struct SynReplyHeadersTests
{
3195 const char* extra_headers
[5];
3196 SpdyHeaderBlock expected_headers
;
3198 // This uses a multi-valued cookie header.
3201 "cookie", "val2", // will get appended separated by NULL
3205 // This is the minimalist set of headers.
3209 // Headers with a comma separated list.
3211 { "cookie", "val1,val2",
3217 test_cases
[0].expected_headers
["cookie"] = "val1";
3218 test_cases
[0].expected_headers
["cookie"] += '\0';
3219 test_cases
[0].expected_headers
["cookie"] += "val2";
3220 test_cases
[0].expected_headers
["hello"] = "bye";
3221 test_cases
[0].expected_headers
["status"] = "200";
3223 test_cases
[1].expected_headers
["hello"] = "bye";
3224 test_cases
[1].expected_headers
["status"] = "200";
3226 test_cases
[2].expected_headers
["cookie"] = "val1,val2";
3227 test_cases
[2].expected_headers
["hello"] = "bye";
3228 test_cases
[2].expected_headers
["status"] = "200";
3230 if (spdy_util_
.spdy_version() < SPDY4
) {
3231 // SPDY4/HTTP2 eliminates use of the :version header.
3232 test_cases
[0].expected_headers
["version"] = "HTTP/1.1";
3233 test_cases
[1].expected_headers
["version"] = "HTTP/1.1";
3234 test_cases
[2].expected_headers
["version"] = "HTTP/1.1";
3237 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3238 scoped_ptr
<SpdyFrame
> req(
3239 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3240 MockWrite writes
[] = { CreateMockWrite(*req
) };
3242 scoped_ptr
<SpdyFrame
> resp(
3243 spdy_util_
.ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3244 test_cases
[i
].num_headers
,
3246 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3247 MockRead reads
[] = {
3248 CreateMockRead(*resp
),
3249 CreateMockRead(*body
),
3250 MockRead(ASYNC
, 0, 0) // EOF
3253 DelayedSocketData
data(1, reads
, arraysize(reads
),
3254 writes
, arraysize(writes
));
3255 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3256 BoundNetLog(), GetParam(), NULL
);
3257 helper
.RunToCompletion(&data
);
3258 TransactionHelperResult out
= helper
.output();
3260 EXPECT_EQ(OK
, out
.rv
);
3261 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3262 EXPECT_EQ("hello!", out
.response_data
);
3264 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3265 EXPECT_TRUE(headers
.get() != NULL
);
3267 std::string name
, value
;
3268 SpdyHeaderBlock header_block
;
3269 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3270 if (header_block
[name
].empty()) {
3271 header_block
[name
] = value
;
3273 header_block
[name
] += '\0';
3274 header_block
[name
] += value
;
3277 EXPECT_EQ(test_cases
[i
].expected_headers
, header_block
);
3281 // Verify that various SynReply headers parse vary fields correctly
3282 // through the HTTP layer, and the response matches the request.
3283 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3284 // Modify the following data to change/add test cases:
3285 struct SynReplyTests
{
3288 const char* extra_headers
[2][16];
3290 // Test the case of a multi-valued cookie. When the value is delimited
3291 // with NUL characters, it needs to be unfolded into multiple headers.
3295 { { "cookie", "val1,val2",
3299 spdy_util_
.GetStatusKey(), "200",
3300 spdy_util_
.GetPathKey(), "/index.php",
3301 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3305 }, { // Multiple vary fields.
3308 { { "friend", "barney",
3309 "enemy", "snaggletooth",
3314 spdy_util_
.GetStatusKey(), "200",
3315 spdy_util_
.GetPathKey(), "/index.php",
3316 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3320 }, { // Test a '*' vary field.
3323 { { "cookie", "val1,val2",
3327 spdy_util_
.GetStatusKey(), "200",
3328 spdy_util_
.GetPathKey(), "/index.php",
3329 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3333 }, { // Multiple comma-separated vary fields.
3336 { { "friend", "barney",
3337 "enemy", "snaggletooth",
3340 { "vary", "friend,enemy",
3341 spdy_util_
.GetStatusKey(), "200",
3342 spdy_util_
.GetPathKey(), "/index.php",
3343 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3350 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3351 // Construct the request.
3352 scoped_ptr
<SpdyFrame
> frame_req(
3353 spdy_util_
.ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3354 test_cases
[i
].num_headers
[0],
3355 false, 1, LOWEST
, true));
3357 MockWrite writes
[] = {
3358 CreateMockWrite(*frame_req
),
3361 // Construct the reply.
3362 SpdyHeaderBlock reply_headers
;
3363 AppendToHeaderBlock(test_cases
[i
].extra_headers
[1],
3364 test_cases
[i
].num_headers
[1],
3366 scoped_ptr
<SpdyFrame
> frame_reply(
3367 spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3369 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3370 MockRead reads
[] = {
3371 CreateMockRead(*frame_reply
),
3372 CreateMockRead(*body
),
3373 MockRead(ASYNC
, 0, 0) // EOF
3376 // Attach the headers to the request.
3377 int header_count
= test_cases
[i
].num_headers
[0];
3379 HttpRequestInfo request
= CreateGetRequest();
3380 for (int ct
= 0; ct
< header_count
; ct
++) {
3381 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3382 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3383 request
.extra_headers
.SetHeader(header_key
, header_value
);
3386 DelayedSocketData
data(1, reads
, arraysize(reads
),
3387 writes
, arraysize(writes
));
3388 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
3389 BoundNetLog(), GetParam(), NULL
);
3390 helper
.RunToCompletion(&data
);
3391 TransactionHelperResult out
= helper
.output();
3393 EXPECT_EQ(OK
, out
.rv
) << i
;
3394 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3395 EXPECT_EQ("hello!", out
.response_data
) << i
;
3397 // Test the response information.
3398 EXPECT_TRUE(out
.response_info
.response_time
>
3399 out
.response_info
.request_time
) << i
;
3400 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3401 out
.response_info
.request_time
;
3402 base::TimeDelta min_expected_delay
;
3403 min_expected_delay
.FromMilliseconds(10);
3404 EXPECT_GT(test_delay
.InMillisecondsF(),
3405 min_expected_delay
.InMillisecondsF()) << i
;
3406 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3407 test_cases
[i
].vary_matches
) << i
;
3409 // Check the headers.
3410 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3411 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3413 std::string name
, value
, lines
;
3414 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3417 lines
.append(value
);
3421 // Construct the expected header reply string.
3422 std::string expected_reply
=
3423 spdy_util_
.ConstructSpdyReplyString(reply_headers
);
3424 EXPECT_EQ(expected_reply
, lines
) << i
;
3428 // Verify that we don't crash on invalid SynReply responses.
3429 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3430 struct InvalidSynReplyTests
{
3432 const char* headers
[10];
3434 // SYN_REPLY missing status header
3438 spdy_util_
.GetPathKey(), "/index.php",
3439 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3443 // SYN_REPLY missing version header
3446 spdy_util_
.GetPathKey(), "/index.php",
3450 // SYN_REPLY with no headers
3454 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3455 scoped_ptr
<SpdyFrame
> req(
3456 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3457 scoped_ptr
<SpdyFrame
> rst(
3458 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3459 MockWrite writes
[] = {
3460 CreateMockWrite(*req
),
3461 CreateMockWrite(*rst
),
3464 // Construct the reply.
3465 SpdyHeaderBlock reply_headers
;
3466 AppendToHeaderBlock(
3467 test_cases
[i
].headers
, test_cases
[i
].num_headers
, &reply_headers
);
3468 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyReply(1, reply_headers
));
3469 MockRead reads
[] = {
3470 CreateMockRead(*resp
),
3471 MockRead(ASYNC
, 0, 0) // EOF
3474 DelayedSocketData
data(1, reads
, arraysize(reads
),
3475 writes
, arraysize(writes
));
3476 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3477 BoundNetLog(), GetParam(), NULL
);
3478 helper
.RunToCompletion(&data
);
3479 TransactionHelperResult out
= helper
.output();
3480 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3484 // Verify that we don't crash on some corrupt frames.
3485 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3486 // connection error. I'd like to backport this behavior to SPDY3 as well.
3487 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3488 if (spdy_util_
.spdy_version() >= SPDY4
) {
3491 // This is the length field that's too short.
3492 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3493 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3494 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3496 (spdy_util_
.spdy_version() < SPDY4
) ?
3497 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize() :
3498 syn_reply_wrong_length
->size();
3499 size_t wrong_size
= right_size
- 4;
3500 test::SetFrameLength(syn_reply_wrong_length
.get(),
3502 spdy_util_
.spdy_version());
3504 struct SynReplyTests
{
3505 const SpdyFrame
* syn_reply
;
3507 { syn_reply_wrong_length
.get(), },
3510 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
3511 scoped_ptr
<SpdyFrame
> req(
3512 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3513 scoped_ptr
<SpdyFrame
> rst(
3514 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3515 MockWrite writes
[] = {
3516 CreateMockWrite(*req
),
3517 CreateMockWrite(*rst
),
3520 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3521 MockRead reads
[] = {
3522 MockRead(ASYNC
, test_cases
[i
].syn_reply
->data(), wrong_size
),
3523 CreateMockRead(*body
),
3524 MockRead(ASYNC
, 0, 0) // EOF
3527 DelayedSocketData
data(1, reads
, arraysize(reads
),
3528 writes
, arraysize(writes
));
3529 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3530 BoundNetLog(), GetParam(), NULL
);
3531 helper
.RunToCompletion(&data
);
3532 TransactionHelperResult out
= helper
.output();
3533 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3537 // SPDY4 treats a header decompression failure as a connection-level error.
3538 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionErrorSpdy4
) {
3539 if (spdy_util_
.spdy_version() < SPDY4
) {
3542 // This is the length field that's too short.
3543 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3544 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3545 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3547 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize();
3548 size_t wrong_size
= right_size
- 4;
3549 test::SetFrameLength(syn_reply_wrong_length
.get(),
3551 spdy_util_
.spdy_version());
3553 scoped_ptr
<SpdyFrame
> req(
3554 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3555 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3556 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3557 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3559 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3560 MockRead reads
[] = {
3561 MockRead(ASYNC
, syn_reply_wrong_length
->data(),
3562 syn_reply_wrong_length
->size() - 4),
3565 DelayedSocketData
data(1, reads
, arraysize(reads
),
3566 writes
, arraysize(writes
));
3567 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3568 BoundNetLog(), GetParam(), NULL
);
3569 helper
.RunToCompletion(&data
);
3570 TransactionHelperResult out
= helper
.output();
3571 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3574 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnDecompressionFailure
) {
3575 if (GetParam().protocol
< kProtoSPDY4MinimumVersion
) {
3576 // Decompression failures are a stream error in SPDY3 and above.
3579 scoped_ptr
<SpdyFrame
> req(
3580 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3581 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3582 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3583 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3585 // Read HEADERS with corrupted payload.
3586 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3587 memset(resp
->data() + 12, 0xff, resp
->size() - 12);
3588 MockRead reads
[] = {CreateMockRead(*resp
)};
3590 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3591 NormalSpdyTransactionHelper
helper(
3592 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3593 helper
.RunToCompletion(&data
);
3594 TransactionHelperResult out
= helper
.output();
3595 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3598 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnFrameSizeError
) {
3599 scoped_ptr
<SpdyFrame
> req(
3600 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3601 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3602 0, GOAWAY_PROTOCOL_ERROR
, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3603 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*goaway
)};
3605 // Read WINDOW_UPDATE with incorrectly-sized payload.
3606 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3607 // which is mapped to a protocol error, and not a frame size error.
3608 scoped_ptr
<SpdyFrame
> bad_window_update(
3609 spdy_util_
.ConstructSpdyWindowUpdate(1, 1));
3610 test::SetFrameLength(bad_window_update
.get(),
3611 bad_window_update
->size() - 1,
3612 spdy_util_
.spdy_version());
3613 MockRead reads
[] = {CreateMockRead(*bad_window_update
)};
3615 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
3616 NormalSpdyTransactionHelper
helper(
3617 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
3618 helper
.RunToCompletion(&data
);
3619 TransactionHelperResult out
= helper
.output();
3620 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3623 // Test that we shutdown correctly on write errors.
3624 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3625 scoped_ptr
<SpdyFrame
> req(
3626 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3627 MockWrite writes
[] = {
3628 // We'll write 10 bytes successfully
3629 MockWrite(ASYNC
, req
->data(), 10, 0),
3630 // Followed by ERROR!
3631 MockWrite(ASYNC
, ERR_FAILED
, 1),
3632 // Session drains and attempts to write a GOAWAY: Another ERROR!
3633 MockWrite(ASYNC
, ERR_FAILED
, 2),
3636 MockRead reads
[] = {
3637 MockRead(ASYNC
, 0, 3) // EOF
3640 DeterministicSocketData
data(reads
, arraysize(reads
),
3641 writes
, arraysize(writes
));
3643 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3644 BoundNetLog(), GetParam(), NULL
);
3645 helper
.SetDeterministic();
3646 helper
.RunPreTestSetup();
3647 helper
.AddDeterministicData(&data
);
3648 EXPECT_TRUE(helper
.StartDefaultTest());
3650 helper
.FinishDefaultTest();
3651 EXPECT_TRUE(data
.at_write_eof());
3652 EXPECT_TRUE(!data
.at_read_eof());
3653 TransactionHelperResult out
= helper
.output();
3654 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3657 // Test that partial writes work.
3658 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3659 // Chop the SYN_STREAM frame into 5 chunks.
3660 scoped_ptr
<SpdyFrame
> req(
3661 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3662 const int kChunks
= 5;
3663 scoped_ptr
<MockWrite
[]> writes(ChopWriteFrame(*req
.get(), kChunks
));
3665 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3666 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3667 MockRead reads
[] = {
3668 CreateMockRead(*resp
),
3669 CreateMockRead(*body
),
3670 MockRead(ASYNC
, 0, 0) // EOF
3673 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
3674 writes
.get(), kChunks
);
3675 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3676 BoundNetLog(), GetParam(), NULL
);
3677 helper
.RunToCompletion(&data
);
3678 TransactionHelperResult out
= helper
.output();
3679 EXPECT_EQ(OK
, out
.rv
);
3680 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3681 EXPECT_EQ("hello!", out
.response_data
);
3684 // In this test, we enable compression, but get a uncompressed SynReply from
3685 // the server. Verify that teardown is all clean.
3686 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3687 if (spdy_util_
.spdy_version() >= SPDY4
) {
3688 // HPACK doesn't use deflate compression.
3691 scoped_ptr
<SpdyFrame
> compressed(
3692 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
, true));
3693 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3694 0, GOAWAY_COMPRESSION_ERROR
, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3695 MockWrite writes
[] = {CreateMockWrite(*compressed
), CreateMockWrite(*goaway
)};
3697 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3698 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3699 MockRead reads
[] = {
3700 CreateMockRead(*resp
),
3703 DelayedSocketData
data(1, reads
, arraysize(reads
),
3704 writes
, arraysize(writes
));
3705 SpdySessionDependencies
* session_deps
=
3706 CreateSpdySessionDependencies(GetParam());
3707 session_deps
->enable_compression
= true;
3708 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3709 BoundNetLog(), GetParam(), session_deps
);
3710 helper
.RunToCompletion(&data
);
3711 TransactionHelperResult out
= helper
.output();
3712 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR
, out
.rv
);
3716 // Test that the NetLog contains good data for a simple GET request.
3717 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3718 static const char* const kExtraHeaders
[] = {
3719 "user-agent", "Chrome",
3721 scoped_ptr
<SpdyFrame
> req(
3722 spdy_util_
.ConstructSpdyGet(kExtraHeaders
, 1, false, 1, LOWEST
, true));
3723 MockWrite writes
[] = { CreateMockWrite(*req
) };
3725 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3726 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3727 MockRead reads
[] = {
3728 CreateMockRead(*resp
),
3729 CreateMockRead(*body
),
3730 MockRead(ASYNC
, 0, 0) // EOF
3733 CapturingBoundNetLog log
;
3735 DelayedSocketData
data(1, reads
, arraysize(reads
),
3736 writes
, arraysize(writes
));
3737 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3739 log
.bound(), GetParam(), NULL
);
3740 helper
.RunToCompletion(&data
);
3741 TransactionHelperResult out
= helper
.output();
3742 EXPECT_EQ(OK
, out
.rv
);
3743 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3744 EXPECT_EQ("hello!", out
.response_data
);
3746 // Check that the NetLog was filled reasonably.
3747 // This test is intentionally non-specific about the exact ordering of the
3748 // log; instead we just check to make sure that certain events exist, and that
3749 // they are in the right order.
3750 CapturingNetLog::CapturedEntryList entries
;
3751 log
.GetEntries(&entries
);
3753 EXPECT_LT(0u, entries
.size());
3755 pos
= ExpectLogContainsSomewhere(entries
, 0,
3756 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3757 NetLog::PHASE_BEGIN
);
3758 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3759 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3761 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3762 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3763 NetLog::PHASE_BEGIN
);
3764 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3765 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3767 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3768 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3769 NetLog::PHASE_BEGIN
);
3770 pos
= ExpectLogContainsSomewhere(entries
, pos
+ 1,
3771 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3774 // Check that we logged all the headers correctly
3775 const NetLog::EventType type
= (GetParam().protocol
<= kProtoSPDY31
)
3776 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3777 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS
;
3778 pos
= ExpectLogContainsSomewhere(entries
, 0, type
, NetLog::PHASE_NONE
);
3780 base::ListValue
* header_list
;
3781 ASSERT_TRUE(entries
[pos
].params
.get());
3782 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3784 std::vector
<std::string
> expected
;
3785 expected
.push_back(std::string(spdy_util_
.GetHostKey()) + ": www.google.com");
3786 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3787 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": http");
3788 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3789 expected
.push_back("user-agent: Chrome");
3790 if (spdy_util_
.spdy_version() < SPDY4
) {
3791 // SPDY4/HTTP2 eliminates use of the :version header.
3792 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3794 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3795 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3796 it
!= expected
.end();
3798 base::StringValue
header(*it
);
3799 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3800 "Header not found: " << *it
;
3804 // Since we buffer the IO from the stream to the renderer, this test verifies
3805 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3806 // on the network, but issued a Read for only 5 of those bytes) that the data
3807 // flow still works correctly.
3808 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3809 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3811 scoped_ptr
<SpdyFrame
> req(
3812 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3813 MockWrite writes
[] = { CreateMockWrite(*req
) };
3815 // 2 data frames in a single read.
3816 scoped_ptr
<SpdyFrame
> data_frame_1(
3817 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3818 scoped_ptr
<SpdyFrame
> data_frame_2(
3819 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3820 const SpdyFrame
* data_frames
[2] = {
3824 char combined_data_frames
[100];
3825 int combined_data_frames_len
=
3826 CombineFrames(data_frames
, arraysize(data_frames
),
3827 combined_data_frames
, arraysize(combined_data_frames
));
3828 scoped_ptr
<SpdyFrame
> last_frame(
3829 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3831 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3832 MockRead reads
[] = {
3833 CreateMockRead(*resp
),
3834 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3835 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3836 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3837 CreateMockRead(*last_frame
),
3838 MockRead(ASYNC
, 0, 0) // EOF
3841 DelayedSocketData
data(1, reads
, arraysize(reads
),
3842 writes
, arraysize(writes
));
3844 TestCompletionCallback callback
;
3846 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3847 BoundNetLog(), GetParam(), NULL
);
3848 helper
.RunPreTestSetup();
3849 helper
.AddData(&data
);
3850 HttpNetworkTransaction
* trans
= helper
.trans();
3851 int rv
= trans
->Start(
3852 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3853 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3855 TransactionHelperResult out
= helper
.output();
3856 out
.rv
= callback
.WaitForResult();
3857 EXPECT_EQ(out
.rv
, OK
);
3859 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3860 EXPECT_TRUE(response
->headers
.get() != NULL
);
3861 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3862 out
.status_line
= response
->headers
->GetStatusLine();
3863 out
.response_info
= *response
; // Make a copy so we can verify.
3866 TestCompletionCallback read_callback
;
3868 std::string content
;
3870 // Read small chunks at a time.
3871 const int kSmallReadSize
= 3;
3872 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
3873 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3874 if (rv
== ERR_IO_PENDING
) {
3875 data
.CompleteRead();
3876 rv
= read_callback
.WaitForResult();
3879 content
.append(buf
->data(), rv
);
3880 } else if (rv
< 0) {
3885 out
.response_data
.swap(content
);
3887 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3888 // MockClientSocketFactory) are still alive.
3889 base::RunLoop().RunUntilIdle();
3891 // Verify that we consumed all test data.
3892 helper
.VerifyDataConsumed();
3894 EXPECT_EQ(OK
, out
.rv
);
3895 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3896 EXPECT_EQ("goodbye world", out
.response_data
);
3899 // Verify that basic buffering works; when multiple data frames arrive
3900 // at the same time, ensure that we don't notify a read completion for
3901 // each data frame individually.
3902 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3903 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3905 scoped_ptr
<SpdyFrame
> req(
3906 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3907 MockWrite writes
[] = { CreateMockWrite(*req
) };
3909 // 4 data frames in a single read.
3910 scoped_ptr
<SpdyFrame
> data_frame(
3911 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3912 scoped_ptr
<SpdyFrame
> data_frame_fin(
3913 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3914 const SpdyFrame
* data_frames
[4] = {
3918 data_frame_fin
.get()
3920 char combined_data_frames
[100];
3921 int combined_data_frames_len
=
3922 CombineFrames(data_frames
, arraysize(data_frames
),
3923 combined_data_frames
, arraysize(combined_data_frames
));
3925 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3926 MockRead reads
[] = {
3927 CreateMockRead(*resp
),
3928 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3929 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3930 MockRead(ASYNC
, 0, 0) // EOF
3933 DelayedSocketData
data(1, reads
, arraysize(reads
),
3934 writes
, arraysize(writes
));
3936 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3937 BoundNetLog(), GetParam(), NULL
);
3938 helper
.RunPreTestSetup();
3939 helper
.AddData(&data
);
3940 HttpNetworkTransaction
* trans
= helper
.trans();
3942 TestCompletionCallback callback
;
3943 int rv
= trans
->Start(
3944 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3947 TransactionHelperResult out
= helper
.output();
3948 out
.rv
= callback
.WaitForResult();
3949 EXPECT_EQ(out
.rv
, OK
);
3951 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3952 EXPECT_TRUE(response
->headers
.get() != NULL
);
3953 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3954 out
.status_line
= response
->headers
->GetStatusLine();
3955 out
.response_info
= *response
; // Make a copy so we can verify.
3958 TestCompletionCallback read_callback
;
3960 std::string content
;
3961 int reads_completed
= 0;
3963 // Read small chunks at a time.
3964 const int kSmallReadSize
= 14;
3965 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
3966 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3967 if (rv
== ERR_IO_PENDING
) {
3968 data
.CompleteRead();
3969 rv
= read_callback
.WaitForResult();
3972 EXPECT_EQ(kSmallReadSize
, rv
);
3973 content
.append(buf
->data(), rv
);
3974 } else if (rv
< 0) {
3975 FAIL() << "Unexpected read error: " << rv
;
3980 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3982 out
.response_data
.swap(content
);
3984 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3985 // MockClientSocketFactory) are still alive.
3986 base::RunLoop().RunUntilIdle();
3988 // Verify that we consumed all test data.
3989 helper
.VerifyDataConsumed();
3991 EXPECT_EQ(OK
, out
.rv
);
3992 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3993 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
3996 // Verify the case where we buffer data but read it after it has been buffered.
3997 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
3998 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4000 scoped_ptr
<SpdyFrame
> req(
4001 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4002 MockWrite writes
[] = { CreateMockWrite(*req
) };
4004 // 5 data frames in a single read.
4005 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4006 scoped_ptr
<SpdyFrame
> data_frame(
4007 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4008 scoped_ptr
<SpdyFrame
> data_frame_fin(
4009 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4010 const SpdyFrame
* frames
[5] = {reply
.get(), data_frame
.get(), data_frame
.get(),
4011 data_frame
.get(), data_frame_fin
.get()};
4012 char combined_frames
[200];
4013 int combined_frames_len
=
4014 CombineFrames(frames
, arraysize(frames
),
4015 combined_frames
, arraysize(combined_frames
));
4017 MockRead reads
[] = {
4018 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4019 MockRead(ASYNC
, 0, 0) // EOF
4022 DelayedSocketData
data(1, reads
, arraysize(reads
),
4023 writes
, arraysize(writes
));
4025 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4026 BoundNetLog(), GetParam(), NULL
);
4027 helper
.RunPreTestSetup();
4028 helper
.AddData(&data
);
4029 HttpNetworkTransaction
* trans
= helper
.trans();
4031 TestCompletionCallback callback
;
4032 int rv
= trans
->Start(
4033 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4034 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4036 TransactionHelperResult out
= helper
.output();
4037 out
.rv
= callback
.WaitForResult();
4038 EXPECT_EQ(out
.rv
, OK
);
4040 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4041 EXPECT_TRUE(response
->headers
.get() != NULL
);
4042 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4043 out
.status_line
= response
->headers
->GetStatusLine();
4044 out
.response_info
= *response
; // Make a copy so we can verify.
4047 TestCompletionCallback read_callback
;
4049 std::string content
;
4050 int reads_completed
= 0;
4052 // Read small chunks at a time.
4053 const int kSmallReadSize
= 14;
4054 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
4055 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4057 EXPECT_EQ(kSmallReadSize
, rv
);
4058 content
.append(buf
->data(), rv
);
4059 } else if (rv
< 0) {
4060 FAIL() << "Unexpected read error: " << rv
;
4065 EXPECT_EQ(3, reads_completed
);
4067 out
.response_data
.swap(content
);
4069 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4070 // MockClientSocketFactory) are still alive.
4071 base::RunLoop().RunUntilIdle();
4073 // Verify that we consumed all test data.
4074 helper
.VerifyDataConsumed();
4076 EXPECT_EQ(OK
, out
.rv
);
4077 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4078 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4081 // Verify the case where we buffer data and close the connection.
4082 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
4083 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4085 scoped_ptr
<SpdyFrame
> req(
4086 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4087 MockWrite writes
[] = { CreateMockWrite(*req
) };
4089 // All data frames in a single read.
4090 // NOTE: We don't FIN the stream.
4091 scoped_ptr
<SpdyFrame
> data_frame(
4092 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4093 const SpdyFrame
* data_frames
[4] = {
4099 char combined_data_frames
[100];
4100 int combined_data_frames_len
=
4101 CombineFrames(data_frames
, arraysize(data_frames
),
4102 combined_data_frames
, arraysize(combined_data_frames
));
4103 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4104 MockRead reads
[] = {
4105 CreateMockRead(*resp
),
4106 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4107 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4108 MockRead(ASYNC
, 0, 0) // EOF
4111 DelayedSocketData
data(1, reads
, arraysize(reads
),
4112 writes
, arraysize(writes
));
4114 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4115 BoundNetLog(), GetParam(), NULL
);
4116 helper
.RunPreTestSetup();
4117 helper
.AddData(&data
);
4118 HttpNetworkTransaction
* trans
= helper
.trans();
4120 TestCompletionCallback callback
;
4122 int rv
= trans
->Start(
4123 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4124 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4126 TransactionHelperResult out
= helper
.output();
4127 out
.rv
= callback
.WaitForResult();
4128 EXPECT_EQ(out
.rv
, OK
);
4130 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4131 EXPECT_TRUE(response
->headers
.get() != NULL
);
4132 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4133 out
.status_line
= response
->headers
->GetStatusLine();
4134 out
.response_info
= *response
; // Make a copy so we can verify.
4137 TestCompletionCallback read_callback
;
4139 std::string content
;
4140 int reads_completed
= 0;
4142 // Read small chunks at a time.
4143 const int kSmallReadSize
= 14;
4144 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kSmallReadSize
));
4145 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4146 if (rv
== ERR_IO_PENDING
) {
4147 data
.CompleteRead();
4148 rv
= read_callback
.WaitForResult();
4151 content
.append(buf
->data(), rv
);
4152 } else if (rv
< 0) {
4153 // This test intentionally closes the connection, and will get an error.
4154 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4160 EXPECT_EQ(0, reads_completed
);
4162 out
.response_data
.swap(content
);
4164 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4165 // MockClientSocketFactory) are still alive.
4166 base::RunLoop().RunUntilIdle();
4168 // Verify that we consumed all test data.
4169 helper
.VerifyDataConsumed();
4172 // Verify the case where we buffer data and cancel the transaction.
4173 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4174 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4176 scoped_ptr
<SpdyFrame
> req(
4177 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4178 scoped_ptr
<SpdyFrame
> rst(
4179 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
4180 MockWrite writes
[] = {CreateMockWrite(*req
), CreateMockWrite(*rst
)};
4182 // NOTE: We don't FIN the stream.
4183 scoped_ptr
<SpdyFrame
> data_frame(
4184 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4186 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4187 MockRead reads
[] = {
4188 CreateMockRead(*resp
),
4189 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4190 CreateMockRead(*data_frame
),
4191 MockRead(ASYNC
, 0, 0) // EOF
4194 DelayedSocketData
data(1, reads
, arraysize(reads
),
4195 writes
, arraysize(writes
));
4197 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4198 BoundNetLog(), GetParam(), NULL
);
4199 helper
.RunPreTestSetup();
4200 helper
.AddData(&data
);
4201 HttpNetworkTransaction
* trans
= helper
.trans();
4202 TestCompletionCallback callback
;
4204 int rv
= trans
->Start(
4205 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4206 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4208 TransactionHelperResult out
= helper
.output();
4209 out
.rv
= callback
.WaitForResult();
4210 EXPECT_EQ(out
.rv
, OK
);
4212 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4213 EXPECT_TRUE(response
->headers
.get() != NULL
);
4214 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4215 out
.status_line
= response
->headers
->GetStatusLine();
4216 out
.response_info
= *response
; // Make a copy so we can verify.
4219 TestCompletionCallback read_callback
;
4221 const int kReadSize
= 256;
4222 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kReadSize
));
4223 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4224 ASSERT_EQ(ERR_IO_PENDING
, rv
) << "Unexpected read: " << rv
;
4226 // Complete the read now, which causes buffering to start.
4227 data
.CompleteRead();
4228 // Destroy the transaction, causing the stream to get cancelled
4229 // and orphaning the buffered IO task.
4230 helper
.ResetTrans();
4232 // Flush the MessageLoop; this will cause the buffered IO task
4233 // to run for the final time.
4234 base::RunLoop().RunUntilIdle();
4236 // Verify that we consumed all test data.
4237 helper
.VerifyDataConsumed();
4240 // Test that if the server requests persistence of settings, that we save
4241 // the settings in the HttpServerProperties.
4242 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4243 if (spdy_util_
.spdy_version() >= SPDY4
) {
4244 // SPDY4 doesn't support settings persistence.
4247 static const SpdyHeaderInfo kSynReplyInfo
= {
4248 SYN_REPLY
, // Syn Reply
4250 0, // Associated Stream ID
4251 ConvertRequestPriorityToSpdyPriority(
4252 LOWEST
, spdy_util_
.spdy_version()),
4253 kSpdyCredentialSlotUnused
,
4254 CONTROL_FLAG_NONE
, // Control Flags
4255 false, // Compressed
4256 RST_STREAM_INVALID
, // Status
4259 DATA_FLAG_NONE
// Data Flags
4262 BoundNetLog net_log
;
4263 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4264 net_log
, GetParam(), NULL
);
4265 helper
.RunPreTestSetup();
4267 // Verify that no settings exist initially.
4268 HostPortPair
host_port_pair("www.google.com", helper
.port());
4269 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4270 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4271 host_port_pair
).empty());
4273 // Construct the request.
4274 scoped_ptr
<SpdyFrame
> req(
4275 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4276 MockWrite writes
[] = { CreateMockWrite(*req
) };
4278 // Construct the reply.
4279 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4280 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4281 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4282 scoped_ptr
<SpdyFrame
> reply(
4283 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4285 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4286 unsigned int kSampleValue1
= 0x0a0a0a0a;
4287 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4288 unsigned int kSampleValue2
= 0x0b0b0b0b;
4289 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4290 unsigned int kSampleValue3
= 0x0c0c0c0c;
4291 scoped_ptr
<SpdyFrame
> settings_frame
;
4293 // Construct the SETTINGS frame.
4294 SettingsMap settings
;
4295 // First add a persisted setting.
4296 settings
[kSampleId1
] =
4297 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4298 // Next add a non-persisted setting.
4299 settings
[kSampleId2
] =
4300 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4301 // Next add another persisted setting.
4302 settings
[kSampleId3
] =
4303 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4304 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4307 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4308 MockRead reads
[] = {
4309 CreateMockRead(*reply
),
4310 CreateMockRead(*body
),
4311 CreateMockRead(*settings_frame
),
4312 MockRead(ASYNC
, 0, 0) // EOF
4315 DelayedSocketData
data(1, reads
, arraysize(reads
),
4316 writes
, arraysize(writes
));
4317 helper
.AddData(&data
);
4318 helper
.RunDefaultTest();
4319 helper
.VerifyDataConsumed();
4320 TransactionHelperResult out
= helper
.output();
4321 EXPECT_EQ(OK
, out
.rv
);
4322 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4323 EXPECT_EQ("hello!", out
.response_data
);
4326 // Verify we had two persisted settings.
4327 const SettingsMap
& settings_map
=
4328 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4330 ASSERT_EQ(2u, settings_map
.size());
4332 // Verify the first persisted setting.
4333 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4334 EXPECT_TRUE(it1
!= settings_map
.end());
4335 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4336 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4337 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4339 // Verify the second persisted setting.
4340 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4341 EXPECT_TRUE(it3
!= settings_map
.end());
4342 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4343 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4344 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4348 // Test that when there are settings saved that they are sent back to the
4349 // server upon session establishment.
4350 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4351 if (spdy_util_
.spdy_version() >= SPDY4
) {
4352 // SPDY4 doesn't support settings persistence.
4355 static const SpdyHeaderInfo kSynReplyInfo
= {
4356 SYN_REPLY
, // Syn Reply
4358 0, // Associated Stream ID
4359 ConvertRequestPriorityToSpdyPriority(
4360 LOWEST
, spdy_util_
.spdy_version()),
4361 kSpdyCredentialSlotUnused
,
4362 CONTROL_FLAG_NONE
, // Control Flags
4363 false, // Compressed
4364 RST_STREAM_INVALID
, // Status
4367 DATA_FLAG_NONE
// Data Flags
4370 BoundNetLog net_log
;
4371 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4372 net_log
, GetParam(), NULL
);
4373 helper
.RunPreTestSetup();
4375 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4377 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4378 pool_peer
.SetEnableSendingInitialData(true);
4380 // Verify that no settings exist initially.
4381 HostPortPair
host_port_pair("www.google.com", helper
.port());
4382 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4383 host_port_pair
).empty());
4385 const SpdySettingsIds kSampleId1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
4386 unsigned int kSampleValue1
= 0x0a0a0a0a;
4387 const SpdySettingsIds kSampleId2
= SETTINGS_INITIAL_WINDOW_SIZE
;
4388 unsigned int kSampleValue2
= 0x0c0c0c0c;
4390 // First add a persisted setting.
4391 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4394 SETTINGS_FLAG_PLEASE_PERSIST
,
4397 // Next add another persisted setting.
4398 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4401 SETTINGS_FLAG_PLEASE_PERSIST
,
4404 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4405 host_port_pair
).size());
4407 // Construct the initial SETTINGS frame.
4408 SettingsMap initial_settings
;
4409 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4410 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4411 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4412 spdy_util_
.ConstructSpdySettings(initial_settings
));
4414 // Construct the initial window update.
4415 scoped_ptr
<SpdyFrame
> initial_window_update(
4416 spdy_util_
.ConstructSpdyWindowUpdate(
4417 kSessionFlowControlStreamId
,
4418 kDefaultInitialRecvWindowSize
-
4419 SpdySession::GetInitialWindowSize(GetParam().protocol
)));
4421 // Construct the persisted SETTINGS frame.
4422 const SettingsMap
& settings
=
4423 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4425 scoped_ptr
<SpdyFrame
> settings_frame(
4426 spdy_util_
.ConstructSpdySettings(settings
));
4428 // Construct the request.
4429 scoped_ptr
<SpdyFrame
> req(
4430 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4432 std::vector
<MockWrite
> writes
;
4433 if ((GetParam().protocol
>= kProtoSPDY4MinimumVersion
) &&
4434 (GetParam().protocol
<= kProtoSPDY4MaximumVersion
)) {
4437 kHttp2ConnectionHeaderPrefix
,
4438 kHttp2ConnectionHeaderPrefixSize
));
4440 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4441 if (GetParam().protocol
>= kProtoSPDY31
) {
4442 writes
.push_back(CreateMockWrite(*initial_window_update
));
4444 writes
.push_back(CreateMockWrite(*settings_frame
));
4445 writes
.push_back(CreateMockWrite(*req
));
4447 // Construct the reply.
4448 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4449 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4450 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4451 scoped_ptr
<SpdyFrame
> reply(
4452 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4454 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4455 MockRead reads
[] = {
4456 CreateMockRead(*reply
),
4457 CreateMockRead(*body
),
4458 MockRead(ASYNC
, 0, 0) // EOF
4461 DelayedSocketData
data(2, reads
, arraysize(reads
),
4462 vector_as_array(&writes
), writes
.size());
4463 helper
.AddData(&data
);
4464 helper
.RunDefaultTest();
4465 helper
.VerifyDataConsumed();
4466 TransactionHelperResult out
= helper
.output();
4467 EXPECT_EQ(OK
, out
.rv
);
4468 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4469 EXPECT_EQ("hello!", out
.response_data
);
4472 // Verify we had two persisted settings.
4473 const SettingsMap
& settings_map
=
4474 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4476 ASSERT_EQ(2u, settings_map
.size());
4478 // Verify the first persisted setting.
4479 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4480 EXPECT_TRUE(it1
!= settings_map
.end());
4481 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4482 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4483 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4485 // Verify the second persisted setting.
4486 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4487 EXPECT_TRUE(it2
!= settings_map
.end());
4488 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4489 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4490 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4494 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4495 scoped_ptr
<SpdyFrame
> req(
4496 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4497 MockWrite writes
[] = { CreateMockWrite(*req
) };
4499 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4500 MockRead reads
[] = {
4501 CreateMockRead(*go_away
),
4504 DelayedSocketData
data(1, reads
, arraysize(reads
),
4505 writes
, arraysize(writes
));
4506 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4507 BoundNetLog(), GetParam(), NULL
);
4508 helper
.AddData(&data
);
4509 helper
.RunToCompletion(&data
);
4510 TransactionHelperResult out
= helper
.output();
4511 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4514 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4515 scoped_ptr
<SpdyFrame
> req(
4516 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4517 MockWrite writes
[] = { CreateMockWrite(*req
) };
4519 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4520 MockRead reads
[] = {
4521 CreateMockRead(*resp
),
4522 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4525 DelayedSocketData
data(1, reads
, arraysize(reads
),
4526 writes
, arraysize(writes
));
4528 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4529 log
, GetParam(), NULL
);
4530 helper
.RunPreTestSetup();
4531 helper
.AddData(&data
);
4532 HttpNetworkTransaction
* trans
= helper
.trans();
4534 TestCompletionCallback callback
;
4535 TransactionHelperResult out
;
4536 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4538 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4539 out
.rv
= callback
.WaitForResult();
4540 EXPECT_EQ(out
.rv
, OK
);
4542 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4543 EXPECT_TRUE(response
->headers
.get() != NULL
);
4544 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4545 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4546 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4548 // Verify that we consumed all test data.
4549 helper
.VerifyDataConsumed();
4552 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4553 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredError
) {
4554 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4555 if (spdy_util_
.spdy_version() < SPDY4
)
4558 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4559 BoundNetLog(), GetParam(), nullptr);
4561 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4562 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4563 MockRead reads
[] = {
4564 CreateMockRead(*go_away
),
4566 DelayedSocketData
data(0, reads
, arraysize(reads
), nullptr, 0);
4568 helper
.RunToCompletion(&data
);
4569 TransactionHelperResult out
= helper
.output();
4570 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED
, out
.rv
);
4573 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4574 // protocol negotiation happens, instead this test forces protocols for both
4576 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredRetry
) {
4577 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4578 if (spdy_util_
.spdy_version() < SPDY4
)
4580 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4581 // only spoken over SSL.
4582 if (GetParam().ssl_type
!= SPDYSSL
)
4585 HttpRequestInfo request
;
4586 request
.method
= "GET";
4587 request
.url
= GURL("https://www.google.com/");
4588 scoped_ptr
<SpdySessionDependencies
> session_deps(
4589 CreateSpdySessionDependencies(GetParam()));
4590 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4591 session_deps
->force_spdy_over_ssl
= false;
4592 session_deps
->force_spdy_always
= false;
4593 session_deps
->next_protos
= SpdyNextProtos();
4594 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4595 GetParam(), session_deps
.release());
4597 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4598 const char* url
= "https://www.google.com/";
4599 scoped_ptr
<SpdyHeaderBlock
> headers(spdy_util_
.ConstructGetHeaderBlock(url
));
4600 scoped_ptr
<SpdyFrame
> req(
4601 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4602 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4603 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4604 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4605 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4606 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4607 arraysize(writes0
));
4609 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4610 new SSLSocketDataProvider(ASYNC
, OK
));
4611 // Expect HTTP/2 protocols too in SSLConfig.
4612 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4613 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4614 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4615 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4
);
4617 ssl_provider0
->SetNextProto(GetParam().protocol
);
4618 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4620 // Second socket: falling back to HTTP/1.1.
4621 MockWrite writes1
[] = {MockWrite(
4622 "GET / HTTP/1.1\r\n"
4623 "Host: www.google.com\r\n"
4624 "Connection: keep-alive\r\n\r\n")};
4625 MockRead reads1
[] = {MockRead(
4626 "HTTP/1.1 200 OK\r\n"
4627 "Content-Length: 5\r\n\r\n"
4629 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4630 arraysize(writes1
));
4632 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4633 new SSLSocketDataProvider(ASYNC
, OK
));
4634 // Expect only HTTP/1.1 protocol in SSLConfig.
4635 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4637 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4638 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4640 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4641 helper
.session()->spdy_session_pool()->http_server_properties();
4642 const HostPortPair host_port_pair
= HostPortPair::FromURL(GURL(url
));
4643 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4645 helper
.RunPreTestSetup();
4646 helper
.StartDefaultTest();
4647 helper
.FinishDefaultTestWithoutVerification();
4648 helper
.VerifyDataConsumed();
4649 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(host_port_pair
));
4651 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4652 ASSERT_TRUE(response
!= nullptr);
4653 ASSERT_TRUE(response
->headers
.get() != nullptr);
4654 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4655 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4656 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4657 EXPECT_TRUE(response
->was_npn_negotiated
);
4658 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4659 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4660 EXPECT_EQ(443, response
->socket_address
.port());
4661 std::string response_data
;
4662 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4663 EXPECT_EQ("hello", response_data
);
4666 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4667 // proxy. Note that no actual protocol negotiation happens, instead this test
4668 // forces protocols for both sockets.
4669 TEST_P(SpdyNetworkTransactionTest
, HTTP11RequiredProxyRetry
) {
4670 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4671 if (spdy_util_
.spdy_version() < SPDY4
)
4673 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4674 // only spoken over SSL.
4675 if (GetParam().ssl_type
!= SPDYSSL
)
4678 HttpRequestInfo request
;
4679 request
.method
= "GET";
4680 request
.url
= GURL("https://www.google.com/");
4681 scoped_ptr
<SpdySessionDependencies
> session_deps(
4682 CreateSpdySessionDependencies(
4684 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4685 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4686 session_deps
->force_spdy_over_ssl
= false;
4687 session_deps
->force_spdy_always
= false;
4688 session_deps
->next_protos
= SpdyNextProtos();
4689 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
, BoundNetLog(),
4690 GetParam(), session_deps
.release());
4692 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4693 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
4694 nullptr, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
4695 MockWrite writes0
[] = {CreateMockWrite(*req
)};
4696 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway(
4697 0, GOAWAY_HTTP_1_1_REQUIRED
, "Try again using HTTP/1.1 please."));
4698 MockRead reads0
[] = {CreateMockRead(*go_away
)};
4699 DelayedSocketData
data0(1, reads0
, arraysize(reads0
), writes0
,
4700 arraysize(writes0
));
4702 scoped_ptr
<SSLSocketDataProvider
> ssl_provider0(
4703 new SSLSocketDataProvider(ASYNC
, OK
));
4704 // Expect HTTP/2 protocols too in SSLConfig.
4705 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4706 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY31
);
4707 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4_14
);
4708 ssl_provider0
->next_protos_expected_in_ssl_config
.push_back(kProtoSPDY4
);
4710 ssl_provider0
->SetNextProto(GetParam().protocol
);
4711 helper
.AddDataWithSSLSocketDataProvider(&data0
, ssl_provider0
.Pass());
4713 // Second socket: retry using HTTP/1.1.
4714 MockWrite writes1
[] = {
4716 "CONNECT www.google.com:443 HTTP/1.1\r\n"
4717 "Host: www.google.com\r\n"
4718 "Proxy-Connection: keep-alive\r\n\r\n"),
4720 "GET / HTTP/1.1\r\n"
4721 "Host: www.google.com\r\n"
4722 "Connection: keep-alive\r\n\r\n"),
4725 MockRead reads1
[] = {
4726 MockRead(ASYNC
, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4728 "HTTP/1.1 200 OK\r\n"
4729 "Content-Length: 5\r\n\r\n"
4732 DelayedSocketData
data1(1, reads1
, arraysize(reads1
), writes1
,
4733 arraysize(writes1
));
4735 scoped_ptr
<SSLSocketDataProvider
> ssl_provider1(
4736 new SSLSocketDataProvider(ASYNC
, OK
));
4737 // Expect only HTTP/1.1 protocol in SSLConfig.
4738 ssl_provider1
->next_protos_expected_in_ssl_config
.push_back(kProtoHTTP11
);
4740 ssl_provider1
->SetNextProto(kProtoHTTP11
);
4741 helper
.AddDataWithSSLSocketDataProvider(&data1
, ssl_provider1
.Pass());
4743 // A third socket is needed for the tunnelled connection.
4744 scoped_ptr
<SSLSocketDataProvider
> ssl_provider2(
4745 new SSLSocketDataProvider(ASYNC
, OK
));
4746 helper
.session_deps()->socket_factory
->AddSSLSocketDataProvider(
4747 ssl_provider2
.get());
4749 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
4750 helper
.session()->spdy_session_pool()->http_server_properties();
4751 const HostPortPair proxy_host_port_pair
= HostPortPair("myproxy", 70);
4752 EXPECT_FALSE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4754 helper
.RunPreTestSetup();
4755 helper
.StartDefaultTest();
4756 helper
.FinishDefaultTestWithoutVerification();
4757 helper
.VerifyDataConsumed();
4758 EXPECT_TRUE(http_server_properties
->RequiresHTTP11(proxy_host_port_pair
));
4760 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
4761 ASSERT_TRUE(response
!= nullptr);
4762 ASSERT_TRUE(response
->headers
.get() != nullptr);
4763 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4764 EXPECT_FALSE(response
->was_fetched_via_spdy
);
4765 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
, response
->connection_info
);
4766 EXPECT_FALSE(response
->was_npn_negotiated
);
4767 EXPECT_TRUE(request
.url
.SchemeIs("https"));
4768 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
4769 EXPECT_EQ(70, response
->socket_address
.port());
4770 std::string response_data
;
4771 ASSERT_EQ(OK
, ReadTransaction(helper
.trans(), &response_data
));
4772 EXPECT_EQ("hello", response_data
);
4775 // Test to make sure we can correctly connect through a proxy.
4776 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4777 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4778 BoundNetLog(), GetParam(), NULL
);
4779 helper
.session_deps().reset(CreateSpdySessionDependencies(
4781 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4782 helper
.SetSession(make_scoped_refptr(
4783 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4784 helper
.RunPreTestSetup();
4785 HttpNetworkTransaction
* trans
= helper
.trans();
4787 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4788 "Host: www.google.com\r\n"
4789 "Proxy-Connection: keep-alive\r\n\r\n"};
4790 const char kConnect80
[] = {
4791 "CONNECT www.google.com:80 HTTP/1.1\r\n"
4792 "Host: www.google.com:80\r\n"
4793 "Proxy-Connection: keep-alive\r\n\r\n"};
4794 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4795 scoped_ptr
<SpdyFrame
> req(
4796 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4797 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4798 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4800 MockWrite writes_SPDYNPN
[] = {
4801 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4802 CreateMockWrite(*req
, 2),
4804 MockRead reads_SPDYNPN
[] = {
4805 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4806 CreateMockRead(*resp
, 3),
4807 CreateMockRead(*body
.get(), 4),
4808 MockRead(ASYNC
, 0, 0, 5),
4811 MockWrite writes_SPDYSSL
[] = {
4812 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4813 CreateMockWrite(*req
, 2),
4815 MockRead reads_SPDYSSL
[] = {
4816 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4817 CreateMockRead(*resp
, 3),
4818 CreateMockRead(*body
.get(), 4),
4819 MockRead(ASYNC
, 0, 0, 5),
4822 MockWrite writes_SPDYNOSSL
[] = {
4823 CreateMockWrite(*req
, 0),
4826 MockRead reads_SPDYNOSSL
[] = {
4827 CreateMockRead(*resp
, 1),
4828 CreateMockRead(*body
.get(), 2),
4829 MockRead(ASYNC
, 0, 0, 3),
4832 scoped_ptr
<OrderedSocketData
> data
;
4833 switch (GetParam().ssl_type
) {
4835 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4836 arraysize(reads_SPDYNOSSL
),
4838 arraysize(writes_SPDYNOSSL
)));
4841 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4842 arraysize(reads_SPDYSSL
),
4844 arraysize(writes_SPDYSSL
)));
4847 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4848 arraysize(reads_SPDYNPN
),
4850 arraysize(writes_SPDYNPN
)));
4856 helper
.AddData(data
.get());
4857 TestCompletionCallback callback
;
4859 int rv
= trans
->Start(
4860 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4863 rv
= callback
.WaitForResult();
4866 // Verify the SYN_REPLY.
4867 HttpResponseInfo response
= *trans
->GetResponseInfo();
4868 EXPECT_TRUE(response
.headers
.get() != NULL
);
4869 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4871 std::string response_data
;
4872 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4873 EXPECT_EQ("hello!", response_data
);
4874 helper
.VerifyDataConsumed();
4877 // Test to make sure we can correctly connect through a proxy to www.google.com,
4878 // if there already exists a direct spdy connection to www.google.com. See
4879 // http://crbug.com/49874
4880 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4881 // When setting up the first transaction, we store the SpdySessionPool so that
4882 // we can use the same pool in the second transaction.
4883 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4884 BoundNetLog(), GetParam(), NULL
);
4886 // Use a proxy service which returns a proxy fallback list from DIRECT to
4887 // myproxy:70. For this test there will be no fallback, so it is equivalent
4888 // to simply DIRECT. The reason for appending the second proxy is to verify
4889 // that the session pool key used does is just "DIRECT".
4890 helper
.session_deps().reset(CreateSpdySessionDependencies(
4892 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4893 helper
.SetSession(make_scoped_refptr(
4894 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4896 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4897 helper
.RunPreTestSetup();
4899 // Construct and send a simple GET request.
4900 scoped_ptr
<SpdyFrame
> req(
4901 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4902 MockWrite writes
[] = {
4903 CreateMockWrite(*req
, 1),
4906 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4907 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4908 MockRead reads
[] = {
4909 CreateMockRead(*resp
, 2),
4910 CreateMockRead(*body
, 3),
4911 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4912 MockRead(ASYNC
, 0, 5) // EOF
4914 OrderedSocketData
data(reads
, arraysize(reads
),
4915 writes
, arraysize(writes
));
4916 helper
.AddData(&data
);
4917 HttpNetworkTransaction
* trans
= helper
.trans();
4919 TestCompletionCallback callback
;
4920 TransactionHelperResult out
;
4921 out
.rv
= trans
->Start(
4922 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4924 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4925 out
.rv
= callback
.WaitForResult();
4926 EXPECT_EQ(out
.rv
, OK
);
4928 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4929 EXPECT_TRUE(response
->headers
.get() != NULL
);
4930 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4931 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4932 EXPECT_EQ(OK
, out
.rv
);
4933 out
.status_line
= response
->headers
->GetStatusLine();
4934 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4935 EXPECT_EQ("hello!", out
.response_data
);
4937 // Check that the SpdySession is still in the SpdySessionPool.
4938 HostPortPair
host_port_pair("www.google.com", helper
.port());
4939 SpdySessionKey
session_pool_key_direct(
4940 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4941 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4942 SpdySessionKey
session_pool_key_proxy(
4944 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4945 PRIVACY_MODE_DISABLED
);
4946 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4948 // Set up data for the proxy connection.
4949 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4950 "Host: www.google.com\r\n"
4951 "Proxy-Connection: keep-alive\r\n\r\n"};
4952 const char kConnect80
[] = {
4953 "CONNECT www.google.com:80 HTTP/1.1\r\n"
4954 "Host: www.google.com:80\r\n"
4955 "Proxy-Connection: keep-alive\r\n\r\n"};
4956 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4957 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4958 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4959 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4960 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4962 MockWrite writes_SPDYNPN
[] = {
4963 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4964 CreateMockWrite(*req2
, 2),
4966 MockRead reads_SPDYNPN
[] = {
4967 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4968 CreateMockRead(*resp2
, 3),
4969 CreateMockRead(*body2
, 4),
4970 MockRead(ASYNC
, 0, 5) // EOF
4973 MockWrite writes_SPDYNOSSL
[] = {
4974 CreateMockWrite(*req2
, 0),
4976 MockRead reads_SPDYNOSSL
[] = {
4977 CreateMockRead(*resp2
, 1),
4978 CreateMockRead(*body2
, 2),
4979 MockRead(ASYNC
, 0, 3) // EOF
4982 MockWrite writes_SPDYSSL
[] = {
4983 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4984 CreateMockWrite(*req2
, 2),
4986 MockRead reads_SPDYSSL
[] = {
4987 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4988 CreateMockRead(*resp2
, 3),
4989 CreateMockRead(*body2
, 4),
4990 MockRead(ASYNC
, 0, 0, 5),
4993 scoped_ptr
<OrderedSocketData
> data_proxy
;
4994 switch (GetParam().ssl_type
) {
4996 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
4997 arraysize(reads_SPDYNPN
),
4999 arraysize(writes_SPDYNPN
)));
5002 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
5003 arraysize(reads_SPDYNOSSL
),
5005 arraysize(writes_SPDYNOSSL
)));
5008 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
5009 arraysize(reads_SPDYSSL
),
5011 arraysize(writes_SPDYSSL
)));
5017 // Create another request to www.google.com, but this time through a proxy.
5018 HttpRequestInfo request_proxy
;
5019 request_proxy
.method
= "GET";
5020 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
5021 request_proxy
.load_flags
= 0;
5022 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
5023 CreateSpdySessionDependencies(GetParam()));
5024 // Ensure that this transaction uses the same SpdySessionPool.
5025 scoped_refptr
<HttpNetworkSession
> session_proxy(
5026 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
5027 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
5028 BoundNetLog(), GetParam(), NULL
);
5029 HttpNetworkSessionPeer
session_peer(session_proxy
);
5030 scoped_ptr
<ProxyService
> proxy_service(
5031 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5032 session_peer
.SetProxyService(proxy_service
.get());
5033 helper_proxy
.session_deps().swap(ssd_proxy
);
5034 helper_proxy
.SetSession(session_proxy
);
5035 helper_proxy
.RunPreTestSetup();
5036 helper_proxy
.AddData(data_proxy
.get());
5038 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
5039 TestCompletionCallback callback_proxy
;
5040 int rv
= trans_proxy
->Start(
5041 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
5042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5043 rv
= callback_proxy
.WaitForResult();
5046 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
5047 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
5048 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
5050 std::string response_data
;
5051 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
5052 EXPECT_EQ("hello!", response_data
);
5054 data
.CompleteRead();
5055 helper_proxy
.VerifyDataConsumed();
5058 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5059 // on a new connection, if the connection was previously known to be good.
5060 // This can happen when a server reboots without saying goodbye, or when
5061 // we're behind a NAT that masked the RST.
5062 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
5063 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5064 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5065 MockRead reads
[] = {
5066 CreateMockRead(*resp
),
5067 CreateMockRead(*body
),
5068 MockRead(ASYNC
, ERR_IO_PENDING
),
5069 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
5072 MockRead reads2
[] = {
5073 CreateMockRead(*resp
),
5074 CreateMockRead(*body
),
5075 MockRead(ASYNC
, 0, 0) // EOF
5078 // This test has a couple of variants.
5080 // Induce the RST while waiting for our transaction to send.
5081 VARIANT_RST_DURING_SEND_COMPLETION
,
5082 // Induce the RST while waiting for our transaction to read.
5083 // In this case, the send completed - everything copied into the SNDBUF.
5084 VARIANT_RST_DURING_READ_COMPLETION
5087 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
5088 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
5090 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
5092 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
5094 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5095 BoundNetLog(), GetParam(), NULL
);
5096 helper
.AddData(&data1
);
5097 helper
.AddData(&data2
);
5098 helper
.RunPreTestSetup();
5100 for (int i
= 0; i
< 2; ++i
) {
5101 scoped_ptr
<HttpNetworkTransaction
> trans(
5102 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5104 TestCompletionCallback callback
;
5105 int rv
= trans
->Start(
5106 &helper
.request(), callback
.callback(), BoundNetLog());
5107 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5108 // On the second transaction, we trigger the RST.
5110 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
5111 // Writes to the socket complete asynchronously on SPDY by running
5112 // through the message loop. Complete the write here.
5113 base::RunLoop().RunUntilIdle();
5116 // Now schedule the ERR_CONNECTION_RESET.
5117 EXPECT_EQ(3u, data1
.read_index());
5118 data1
.CompleteRead();
5119 EXPECT_EQ(4u, data1
.read_index());
5121 rv
= callback
.WaitForResult();
5124 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5125 ASSERT_TRUE(response
!= NULL
);
5126 EXPECT_TRUE(response
->headers
.get() != NULL
);
5127 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5128 std::string response_data
;
5129 rv
= ReadTransaction(trans
.get(), &response_data
);
5131 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5132 EXPECT_EQ("hello!", response_data
);
5135 helper
.VerifyDataConsumed();
5139 // Test that turning SPDY on and off works properly.
5140 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
5141 HttpStreamFactory::set_spdy_enabled(true);
5142 scoped_ptr
<SpdyFrame
> req(
5143 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5144 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
5146 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5147 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5148 MockRead spdy_reads
[] = {
5149 CreateMockRead(*resp
),
5150 CreateMockRead(*body
),
5151 MockRead(ASYNC
, 0, 0) // EOF
5154 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
5155 spdy_writes
, arraysize(spdy_writes
));
5156 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5157 BoundNetLog(), GetParam(), NULL
);
5158 helper
.RunToCompletion(&data
);
5159 TransactionHelperResult out
= helper
.output();
5160 EXPECT_EQ(OK
, out
.rv
);
5161 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5162 EXPECT_EQ("hello!", out
.response_data
);
5164 HttpStreamFactory::set_spdy_enabled(false);
5165 MockRead http_reads
[] = {
5166 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5167 MockRead("hello from http"),
5168 MockRead(SYNCHRONOUS
, OK
),
5170 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
5171 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
5172 BoundNetLog(), GetParam(), NULL
);
5173 helper2
.SetSpdyDisabled();
5174 helper2
.RunToCompletion(&data2
);
5175 TransactionHelperResult out2
= helper2
.output();
5176 EXPECT_EQ(OK
, out2
.rv
);
5177 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
5178 EXPECT_EQ("hello from http", out2
.response_data
);
5180 HttpStreamFactory::set_spdy_enabled(true);
5183 // Tests that Basic authentication works over SPDY
5184 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
5185 HttpStreamFactory::set_spdy_enabled(true);
5187 // The first request will be a bare GET, the second request will be a
5188 // GET with an Authorization header.
5189 scoped_ptr
<SpdyFrame
> req_get(
5190 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5191 const char* const kExtraAuthorizationHeaders
[] = {
5192 "authorization", "Basic Zm9vOmJhcg=="
5194 scoped_ptr
<SpdyFrame
> req_get_authorization(
5195 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
5196 arraysize(kExtraAuthorizationHeaders
) / 2,
5197 false, 3, LOWEST
, true));
5198 MockWrite spdy_writes
[] = {
5199 CreateMockWrite(*req_get
, 1),
5200 CreateMockWrite(*req_get_authorization
, 4),
5203 // The first response is a 401 authentication challenge, and the second
5204 // response will be a 200 response since the second request includes a valid
5205 // Authorization header.
5206 const char* const kExtraAuthenticationHeaders
[] = {
5208 "Basic realm=\"MyRealm\""
5210 scoped_ptr
<SpdyFrame
> resp_authentication(
5211 spdy_util_
.ConstructSpdySynReplyError(
5212 "401 Authentication Required",
5213 kExtraAuthenticationHeaders
,
5214 arraysize(kExtraAuthenticationHeaders
) / 2,
5216 scoped_ptr
<SpdyFrame
> body_authentication(
5217 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5218 scoped_ptr
<SpdyFrame
> resp_data(
5219 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5220 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5221 MockRead spdy_reads
[] = {
5222 CreateMockRead(*resp_authentication
, 2),
5223 CreateMockRead(*body_authentication
, 3),
5224 CreateMockRead(*resp_data
, 5),
5225 CreateMockRead(*body_data
, 6),
5226 MockRead(ASYNC
, 0, 7),
5229 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5230 spdy_writes
, arraysize(spdy_writes
));
5231 HttpRequestInfo
request(CreateGetRequest());
5232 BoundNetLog net_log
;
5233 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5234 net_log
, GetParam(), NULL
);
5236 helper
.RunPreTestSetup();
5237 helper
.AddData(&data
);
5238 HttpNetworkTransaction
* trans
= helper
.trans();
5239 TestCompletionCallback callback
;
5240 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5241 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5242 const int rv_start_complete
= callback
.WaitForResult();
5243 EXPECT_EQ(OK
, rv_start_complete
);
5245 // Make sure the response has an auth challenge.
5246 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5247 ASSERT_TRUE(response_start
!= NULL
);
5248 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5249 EXPECT_EQ(401, response_start
->headers
->response_code());
5250 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5251 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5252 ASSERT_TRUE(auth_challenge
!= NULL
);
5253 EXPECT_FALSE(auth_challenge
->is_proxy
);
5254 EXPECT_EQ("basic", auth_challenge
->scheme
);
5255 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5257 // Restart with a username/password.
5258 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5259 base::ASCIIToUTF16("bar"));
5260 TestCompletionCallback callback_restart
;
5261 const int rv_restart
= trans
->RestartWithAuth(
5262 credentials
, callback_restart
.callback());
5263 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5264 const int rv_restart_complete
= callback_restart
.WaitForResult();
5265 EXPECT_EQ(OK
, rv_restart_complete
);
5266 // TODO(cbentzel): This is actually the same response object as before, but
5267 // data has changed.
5268 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5269 ASSERT_TRUE(response_restart
!= NULL
);
5270 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5271 EXPECT_EQ(200, response_restart
->headers
->response_code());
5272 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5275 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5276 scoped_ptr
<SpdyFrame
> stream1_syn(
5277 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5278 scoped_ptr
<SpdyFrame
> stream1_body(
5279 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5280 MockWrite writes
[] = {
5281 CreateMockWrite(*stream1_syn
, 1),
5284 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5285 spdy_util_
.AddUrlToHeaderBlock(
5286 "http://www.google.com/foo.dat", initial_headers
.get());
5287 scoped_ptr
<SpdyFrame
> stream2_syn(
5288 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5290 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5291 (*late_headers
)["hello"] = "bye";
5292 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5293 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5294 scoped_ptr
<SpdyFrame
> stream2_headers(
5295 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5303 scoped_ptr
<SpdyFrame
>
5304 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5305 const char kPushedData
[] = "pushed";
5306 scoped_ptr
<SpdyFrame
> stream2_body(
5307 spdy_util_
.ConstructSpdyBodyFrame(
5308 2, kPushedData
, strlen(kPushedData
), true));
5309 MockRead reads
[] = {
5310 CreateMockRead(*stream1_reply
, 2),
5311 CreateMockRead(*stream2_syn
, 3),
5312 CreateMockRead(*stream2_headers
, 4),
5313 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5314 CreateMockRead(*stream2_body
, 5),
5315 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5318 HttpResponseInfo response
;
5319 HttpResponseInfo response2
;
5320 std::string
expected_push_result("pushed");
5321 OrderedSocketData
data(reads
, arraysize(reads
),
5322 writes
, arraysize(writes
));
5323 RunServerPushTest(&data
,
5326 expected_push_result
);
5328 // Verify the SYN_REPLY.
5329 EXPECT_TRUE(response
.headers
.get() != NULL
);
5330 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5332 // Verify the pushed stream.
5333 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5334 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5337 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5338 // We push a stream and attempt to claim it before the headers come down.
5339 scoped_ptr
<SpdyFrame
> stream1_syn(
5340 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5341 scoped_ptr
<SpdyFrame
> stream1_body(
5342 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5343 MockWrite writes
[] = {
5344 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5347 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5348 spdy_util_
.AddUrlToHeaderBlock(
5349 "http://www.google.com/foo.dat", initial_headers
.get());
5350 scoped_ptr
<SpdyFrame
> stream2_syn(
5351 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5353 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5354 (*late_headers
)["hello"] = "bye";
5355 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5356 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5357 scoped_ptr
<SpdyFrame
> stream2_headers(
5358 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5366 scoped_ptr
<SpdyFrame
>
5367 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5368 const char kPushedData
[] = "pushed";
5369 scoped_ptr
<SpdyFrame
> stream2_body(
5370 spdy_util_
.ConstructSpdyBodyFrame(
5371 2, kPushedData
, strlen(kPushedData
), true));
5372 MockRead reads
[] = {
5373 CreateMockRead(*stream1_reply
, 1),
5374 CreateMockRead(*stream2_syn
, 2),
5375 CreateMockRead(*stream1_body
, 3),
5376 CreateMockRead(*stream2_headers
, 4),
5377 CreateMockRead(*stream2_body
, 5),
5378 MockRead(ASYNC
, 0, 6), // EOF
5381 HttpResponseInfo response
;
5382 HttpResponseInfo response2
;
5383 std::string
expected_push_result("pushed");
5384 DeterministicSocketData
data(reads
, arraysize(reads
),
5385 writes
, arraysize(writes
));
5387 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5388 BoundNetLog(), GetParam(), NULL
);
5389 helper
.SetDeterministic();
5390 helper
.AddDeterministicData(&data
);
5391 helper
.RunPreTestSetup();
5393 HttpNetworkTransaction
* trans
= helper
.trans();
5395 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5396 // and the body of the primary stream, but before we've received the HEADERS
5397 // for the pushed stream.
5400 // Start the transaction.
5401 TestCompletionCallback callback
;
5402 int rv
= trans
->Start(
5403 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5404 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5406 rv
= callback
.WaitForResult();
5409 // Request the pushed path. At this point, we've received the push, but the
5410 // headers are not yet complete.
5411 scoped_ptr
<HttpNetworkTransaction
> trans2(
5412 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5414 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5415 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5417 base::RunLoop().RunUntilIdle();
5419 // Read the server push body.
5420 std::string result2
;
5421 ReadResult(trans2
.get(), &data
, &result2
);
5422 // Read the response body.
5424 ReadResult(trans
, &data
, &result
);
5426 // Verify that the received push data is same as the expected push data.
5427 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5428 << "Received data: "
5430 << "||||| Expected data: "
5431 << expected_push_result
;
5433 // Verify the SYN_REPLY.
5434 // Copy the response info, because trans goes away.
5435 response
= *trans
->GetResponseInfo();
5436 response2
= *trans2
->GetResponseInfo();
5438 VerifyStreamsClosed(helper
);
5440 // Verify the SYN_REPLY.
5441 EXPECT_TRUE(response
.headers
.get() != NULL
);
5442 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5444 // Verify the pushed stream.
5445 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5446 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5448 // Read the final EOF (which will close the session)
5451 // Verify that we consumed all test data.
5452 EXPECT_TRUE(data
.at_read_eof());
5453 EXPECT_TRUE(data
.at_write_eof());
5456 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5457 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5458 // We push a stream and attempt to claim it before the headers come down.
5459 scoped_ptr
<SpdyFrame
> stream1_syn(
5460 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5461 scoped_ptr
<SpdyFrame
> stream1_body(
5462 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5463 MockWrite writes
[] = {
5464 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5467 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5468 if (spdy_util_
.spdy_version() < SPDY4
) {
5469 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5470 (*initial_headers
)["alpha"] = "beta";
5472 spdy_util_
.AddUrlToHeaderBlock(
5473 "http://www.google.com/foo.dat", initial_headers
.get());
5474 scoped_ptr
<SpdyFrame
> stream2_syn(
5475 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5477 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5478 (*middle_headers
)["hello"] = "bye";
5479 scoped_ptr
<SpdyFrame
> stream2_headers1(
5480 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5488 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5489 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5490 if (spdy_util_
.spdy_version() < SPDY4
) {
5491 // SPDY4/HTTP2 eliminates use of the :version header.
5492 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5494 scoped_ptr
<SpdyFrame
> stream2_headers2(
5495 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5503 scoped_ptr
<SpdyFrame
>
5504 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5505 const char kPushedData
[] = "pushed";
5506 scoped_ptr
<SpdyFrame
> stream2_body(
5507 spdy_util_
.ConstructSpdyBodyFrame(
5508 2, kPushedData
, strlen(kPushedData
), true));
5509 MockRead reads
[] = {
5510 CreateMockRead(*stream1_reply
, 1),
5511 CreateMockRead(*stream2_syn
, 2),
5512 CreateMockRead(*stream1_body
, 3),
5513 CreateMockRead(*stream2_headers1
, 4),
5514 CreateMockRead(*stream2_headers2
, 5),
5515 CreateMockRead(*stream2_body
, 6),
5516 MockRead(ASYNC
, 0, 7), // EOF
5519 HttpResponseInfo response
;
5520 HttpResponseInfo response2
;
5521 std::string
expected_push_result("pushed");
5522 DeterministicSocketData
data(reads
, arraysize(reads
),
5523 writes
, arraysize(writes
));
5525 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5526 BoundNetLog(), GetParam(), NULL
);
5527 helper
.SetDeterministic();
5528 helper
.AddDeterministicData(&data
);
5529 helper
.RunPreTestSetup();
5531 HttpNetworkTransaction
* trans
= helper
.trans();
5533 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5534 // the first HEADERS frame, and the body of the primary stream, but before
5535 // we've received the final HEADERS for the pushed stream.
5538 // Start the transaction.
5539 TestCompletionCallback callback
;
5540 int rv
= trans
->Start(
5541 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5542 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5544 rv
= callback
.WaitForResult();
5547 // Request the pushed path. At this point, we've received the push, but the
5548 // headers are not yet complete.
5549 scoped_ptr
<HttpNetworkTransaction
> trans2(
5550 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5552 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5553 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5555 base::RunLoop().RunUntilIdle();
5557 // Read the server push body.
5558 std::string result2
;
5559 ReadResult(trans2
.get(), &data
, &result2
);
5560 // Read the response body.
5562 ReadResult(trans
, &data
, &result
);
5564 // Verify that the received push data is same as the expected push data.
5565 EXPECT_EQ(expected_push_result
, result2
);
5567 // Verify the SYN_REPLY.
5568 // Copy the response info, because trans goes away.
5569 response
= *trans
->GetResponseInfo();
5570 response2
= *trans2
->GetResponseInfo();
5572 VerifyStreamsClosed(helper
);
5574 // Verify the SYN_REPLY.
5575 EXPECT_TRUE(response
.headers
.get() != NULL
);
5576 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5578 // Verify the pushed stream.
5579 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5580 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5582 // Verify we got all the headers from all header blocks.
5583 if (spdy_util_
.spdy_version() < SPDY4
)
5584 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5585 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5586 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5588 // Read the final EOF (which will close the session)
5591 // Verify that we consumed all test data.
5592 EXPECT_TRUE(data
.at_read_eof());
5593 EXPECT_TRUE(data
.at_write_eof());
5596 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5597 // We push a stream and attempt to claim it before the headers come down.
5598 scoped_ptr
<SpdyFrame
> stream1_syn(
5599 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5600 scoped_ptr
<SpdyFrame
> stream1_body(
5601 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5602 MockWrite writes
[] = {
5603 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5606 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5607 spdy_util_
.AddUrlToHeaderBlock(
5608 "http://www.google.com/foo.dat", initial_headers
.get());
5609 scoped_ptr
<SpdyFrame
> stream2_syn(
5610 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5612 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5613 (*middle_headers
)["hello"] = "bye";
5614 scoped_ptr
<SpdyFrame
> stream2_headers1(
5615 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5623 scoped_ptr
<SpdyFrame
>
5624 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5625 const char kPushedData
[] = "pushed";
5626 scoped_ptr
<SpdyFrame
> stream2_body(
5627 spdy_util_
.ConstructSpdyBodyFrame(
5628 2, kPushedData
, strlen(kPushedData
), true));
5629 MockRead reads
[] = {
5630 CreateMockRead(*stream1_reply
, 1),
5631 CreateMockRead(*stream2_syn
, 2),
5632 CreateMockRead(*stream1_body
, 3),
5633 CreateMockRead(*stream2_headers1
, 4),
5634 CreateMockRead(*stream2_body
, 5),
5635 MockRead(ASYNC
, 0, 6), // EOF
5638 DeterministicSocketData
data(reads
, arraysize(reads
),
5639 writes
, arraysize(writes
));
5641 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5642 BoundNetLog(), GetParam(), NULL
);
5643 helper
.SetDeterministic();
5644 helper
.AddDeterministicData(&data
);
5645 helper
.RunPreTestSetup();
5647 HttpNetworkTransaction
* trans
= helper
.trans();
5649 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5650 // the first HEADERS frame, and the body of the primary stream, but before
5651 // we've received the final HEADERS for the pushed stream.
5654 // Start the transaction.
5655 TestCompletionCallback callback
;
5656 int rv
= trans
->Start(
5657 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5658 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5660 rv
= callback
.WaitForResult();
5663 // Request the pushed path. At this point, we've received the push, but the
5664 // headers are not yet complete.
5665 scoped_ptr
<HttpNetworkTransaction
> trans2(
5666 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5668 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5669 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5671 base::RunLoop().RunUntilIdle();
5673 // Read the server push body.
5674 std::string result2
;
5675 ReadResult(trans2
.get(), &data
, &result2
);
5676 // Read the response body.
5678 ReadResult(trans
, &data
, &result
);
5679 EXPECT_EQ("hello!", result
);
5681 // Verify that we haven't received any push data.
5682 EXPECT_EQ("", result2
);
5684 // Verify the SYN_REPLY.
5685 // Copy the response info, because trans goes away.
5686 HttpResponseInfo response
= *trans
->GetResponseInfo();
5687 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5689 VerifyStreamsClosed(helper
);
5691 // Verify the SYN_REPLY.
5692 EXPECT_TRUE(response
.headers
.get() != NULL
);
5693 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5695 // Read the final EOF (which will close the session).
5698 // Verify that we consumed all test data.
5699 EXPECT_TRUE(data
.at_read_eof());
5700 EXPECT_TRUE(data
.at_write_eof());
5703 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5704 scoped_ptr
<SpdyFrame
> req(
5705 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5706 scoped_ptr
<SpdyFrame
> rst(
5707 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5708 MockWrite writes
[] = {
5709 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5712 scoped_ptr
<SpdyFrame
> stream1_reply(
5713 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5715 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5716 (*late_headers
)["hello"] = "bye";
5717 scoped_ptr
<SpdyFrame
> stream1_headers(
5718 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5725 scoped_ptr
<SpdyFrame
> stream1_body(
5726 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5727 MockRead reads
[] = {
5728 CreateMockRead(*stream1_reply
),
5729 CreateMockRead(*stream1_headers
),
5730 CreateMockRead(*stream1_body
),
5731 MockRead(ASYNC
, 0, 0) // EOF
5734 DelayedSocketData
data(1, reads
, arraysize(reads
),
5735 writes
, arraysize(writes
));
5736 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5737 BoundNetLog(), GetParam(), NULL
);
5738 helper
.RunToCompletion(&data
);
5739 TransactionHelperResult out
= helper
.output();
5740 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5743 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5744 scoped_ptr
<SpdyFrame
> req(
5745 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5746 scoped_ptr
<SpdyFrame
> rst(
5747 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5748 MockWrite writes
[] = {
5749 CreateMockWrite(*req
),
5750 CreateMockWrite(*rst
),
5753 scoped_ptr
<SpdyFrame
> stream1_reply(
5754 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5756 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5757 (*late_headers
)["hello"] = "bye";
5758 scoped_ptr
<SpdyFrame
> stream1_headers(
5759 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5766 scoped_ptr
<SpdyFrame
> stream1_body(
5767 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5768 scoped_ptr
<SpdyFrame
> stream1_body2(
5769 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5770 MockRead reads
[] = {
5771 CreateMockRead(*stream1_reply
),
5772 CreateMockRead(*stream1_body
),
5773 CreateMockRead(*stream1_headers
),
5774 CreateMockRead(*stream1_body2
),
5775 MockRead(ASYNC
, 0, 0) // EOF
5778 DelayedSocketData
data(1, reads
, arraysize(reads
),
5779 writes
, arraysize(writes
));
5780 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5781 BoundNetLog(), GetParam(), NULL
);
5782 helper
.RunToCompletion(&data
);
5783 TransactionHelperResult out
= helper
.output();
5784 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5787 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5788 // In this test we want to verify that we can't accidentally push content
5789 // which can't be pushed by this content server.
5790 // This test assumes that:
5791 // - if we're requesting http://www.foo.com/barbaz
5792 // - the browser has made a connection to "www.foo.com".
5794 // A list of the URL to fetch, followed by the URL being pushed.
5795 static const char* const kTestCases
[] = {
5796 "http://www.google.com/foo.html",
5797 "http://www.google.com:81/foo.js", // Bad port
5799 "http://www.google.com/foo.html",
5800 "https://www.google.com/foo.js", // Bad protocol
5802 "http://www.google.com/foo.html",
5803 "ftp://www.google.com/foo.js", // Invalid Protocol
5805 "http://www.google.com/foo.html",
5806 "http://blat.www.google.com/foo.js", // Cross subdomain
5808 "http://www.google.com/foo.html",
5809 "http://www.foo.com/foo.js", // Cross domain
5812 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5813 const char* url_to_fetch
= kTestCases
[index
];
5814 const char* url_to_push
= kTestCases
[index
+ 1];
5816 scoped_ptr
<SpdyFrame
> stream1_syn(
5817 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5818 scoped_ptr
<SpdyFrame
> stream1_body(
5819 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5820 scoped_ptr
<SpdyFrame
> push_rst(
5821 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5822 MockWrite writes
[] = {
5823 CreateMockWrite(*stream1_syn
, 1),
5824 CreateMockWrite(*push_rst
, 4),
5827 scoped_ptr
<SpdyFrame
>
5828 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5829 scoped_ptr
<SpdyFrame
>
5830 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5835 const char kPushedData
[] = "pushed";
5836 scoped_ptr
<SpdyFrame
> stream2_body(
5837 spdy_util_
.ConstructSpdyBodyFrame(
5838 2, kPushedData
, strlen(kPushedData
), true));
5839 scoped_ptr
<SpdyFrame
> rst(
5840 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5842 MockRead reads
[] = {
5843 CreateMockRead(*stream1_reply
, 2),
5844 CreateMockRead(*stream2_syn
, 3),
5845 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5846 CreateMockRead(*stream2_body
, 6),
5847 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5850 HttpResponseInfo response
;
5851 OrderedSocketData
data(reads
, arraysize(reads
),
5852 writes
, arraysize(writes
));
5854 HttpRequestInfo request
;
5855 request
.method
= "GET";
5856 request
.url
= GURL(url_to_fetch
);
5857 request
.load_flags
= 0;
5859 // Enable cross-origin push. Since we are not using a proxy, this should
5860 // not actually enable cross-origin SPDY push.
5861 scoped_ptr
<SpdySessionDependencies
> session_deps(
5862 CreateSpdySessionDependencies(GetParam()));
5863 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5864 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5865 BoundNetLog(), GetParam(),
5866 session_deps
.release());
5867 helper
.RunPreTestSetup();
5868 helper
.AddData(&data
);
5870 HttpNetworkTransaction
* trans
= helper
.trans();
5872 // Start the transaction with basic parameters.
5873 TestCompletionCallback callback
;
5875 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5877 rv
= callback
.WaitForResult();
5879 // Read the response body.
5881 ReadResult(trans
, &data
, &result
);
5883 // Verify that we consumed all test data.
5884 EXPECT_TRUE(data
.at_read_eof());
5885 EXPECT_TRUE(data
.at_write_eof());
5887 // Verify the SYN_REPLY.
5888 // Copy the response info, because trans goes away.
5889 response
= *trans
->GetResponseInfo();
5891 VerifyStreamsClosed(helper
);
5893 // Verify the SYN_REPLY.
5894 EXPECT_TRUE(response
.headers
.get() != NULL
);
5895 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5899 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5900 // Construct the request.
5901 scoped_ptr
<SpdyFrame
> req(
5902 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5903 scoped_ptr
<SpdyFrame
> req2(
5904 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5905 MockWrite writes
[] = {
5906 CreateMockWrite(*req
, 1),
5907 CreateMockWrite(*req2
, 3),
5910 scoped_ptr
<SpdyFrame
> refused(
5911 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5912 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5913 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5914 MockRead reads
[] = {
5915 CreateMockRead(*refused
, 2),
5916 CreateMockRead(*resp
, 4),
5917 CreateMockRead(*body
, 5),
5918 MockRead(ASYNC
, 0, 6) // EOF
5921 OrderedSocketData
data(reads
, arraysize(reads
),
5922 writes
, arraysize(writes
));
5923 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5924 BoundNetLog(), GetParam(), NULL
);
5926 helper
.RunPreTestSetup();
5927 helper
.AddData(&data
);
5929 HttpNetworkTransaction
* trans
= helper
.trans();
5931 // Start the transaction with basic parameters.
5932 TestCompletionCallback callback
;
5933 int rv
= trans
->Start(
5934 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5935 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5936 rv
= callback
.WaitForResult();
5939 // Verify that we consumed all test data.
5940 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5941 << data
.read_count()
5943 << data
.read_index();
5944 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5945 << data
.write_count()
5947 << data
.write_index();
5949 // Verify the SYN_REPLY.
5950 HttpResponseInfo response
= *trans
->GetResponseInfo();
5951 EXPECT_TRUE(response
.headers
.get() != NULL
);
5952 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5955 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5956 // This first request will start to establish the SpdySession.
5957 // Then we will start the second (MEDIUM priority) and then third
5958 // (HIGHEST priority) request in such a way that the third will actually
5959 // start before the second, causing the second to be numbered differently
5960 // than the order they were created.
5961 scoped_ptr
<SpdyFrame
> req1(
5962 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5963 scoped_ptr
<SpdyFrame
> req2(
5964 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5965 scoped_ptr
<SpdyFrame
> req3(
5966 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5967 MockWrite writes
[] = {
5968 CreateMockWrite(*req1
, 0),
5969 CreateMockWrite(*req2
, 3),
5970 CreateMockWrite(*req3
, 4),
5973 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5974 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5975 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5976 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5977 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5978 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5979 MockRead reads
[] = {
5980 CreateMockRead(*resp1
, 1),
5981 CreateMockRead(*body1
, 2),
5982 CreateMockRead(*resp2
, 5),
5983 CreateMockRead(*body2
, 6),
5984 CreateMockRead(*resp3
, 7),
5985 CreateMockRead(*body3
, 8),
5986 MockRead(ASYNC
, 0, 9) // EOF
5989 DeterministicSocketData
data(reads
, arraysize(reads
),
5990 writes
, arraysize(writes
));
5991 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5992 BoundNetLog(), GetParam(), NULL
);
5993 helper
.SetDeterministic();
5994 helper
.RunPreTestSetup();
5995 helper
.AddDeterministicData(&data
);
5997 // Start the first transaction to set up the SpdySession
5998 HttpNetworkTransaction
* trans
= helper
.trans();
5999 TestCompletionCallback callback
;
6000 HttpRequestInfo info1
= CreateGetRequest();
6001 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
6002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6004 // Run the message loop, but do not allow the write to complete.
6005 // This leaves the SpdySession with a write pending, which prevents
6006 // SpdySession from attempting subsequent writes until this write completes.
6007 base::RunLoop().RunUntilIdle();
6009 // Now, start both new transactions
6010 HttpRequestInfo info2
= CreateGetRequest();
6011 TestCompletionCallback callback2
;
6012 scoped_ptr
<HttpNetworkTransaction
> trans2(
6013 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
6014 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
6015 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6016 base::RunLoop().RunUntilIdle();
6018 HttpRequestInfo info3
= CreateGetRequest();
6019 TestCompletionCallback callback3
;
6020 scoped_ptr
<HttpNetworkTransaction
> trans3(
6021 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
6022 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
6023 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6024 base::RunLoop().RunUntilIdle();
6026 // We now have two SYN_STREAM frames queued up which will be
6027 // dequeued only once the first write completes, which we
6028 // now allow to happen.
6030 EXPECT_EQ(OK
, callback
.WaitForResult());
6032 // And now we can allow everything else to run to completion.
6035 EXPECT_EQ(OK
, callback2
.WaitForResult());
6036 EXPECT_EQ(OK
, callback3
.WaitForResult());
6038 helper
.VerifyDataConsumed();
6041 // The tests below are only for SPDY/3 and above.
6043 // Test that sent data frames and received WINDOW_UPDATE frames change
6044 // the send_window_size_ correctly.
6046 // WINDOW_UPDATE is different than most other frames in that it can arrive
6047 // while the client is still sending the request body. In order to enforce
6048 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
6049 // socket data provider, so that initial read that is done as soon as the
6050 // stream is created, succeeds and schedules another read. This way reads
6051 // and writes are interleaved; after doing a full frame write, SpdyStream
6052 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
6053 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
6054 // since request has not been completely written, therefore we feed
6055 // enough number of WINDOW_UPDATEs to finish the first read and cause a
6056 // write, leading to a complete write of request body; after that we send
6057 // a reply with a body, to cause a graceful shutdown.
6059 // TODO(agayev): develop a socket data provider where both, reads and
6060 // writes are ordered so that writing tests like these are easy and rewrite
6061 // all these tests using it. Right now we are working around the
6062 // limitations as described above and it's not deterministic, tests may
6063 // fail under specific circumstances.
6064 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
6065 static int kFrameCount
= 2;
6066 scoped_ptr
<std::string
> content(
6067 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6068 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6069 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6070 scoped_ptr
<SpdyFrame
> body(
6071 spdy_util_
.ConstructSpdyBodyFrame(
6072 1, content
->c_str(), content
->size(), false));
6073 scoped_ptr
<SpdyFrame
> body_end(
6074 spdy_util_
.ConstructSpdyBodyFrame(
6075 1, content
->c_str(), content
->size(), true));
6077 MockWrite writes
[] = {
6078 CreateMockWrite(*req
, 0),
6079 CreateMockWrite(*body
, 1),
6080 CreateMockWrite(*body_end
, 2),
6083 static const int32 kDeltaWindowSize
= 0xff;
6084 static const int kDeltaCount
= 4;
6085 scoped_ptr
<SpdyFrame
> window_update(
6086 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6087 scoped_ptr
<SpdyFrame
> window_update_dummy(
6088 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
6089 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6090 MockRead reads
[] = {
6091 CreateMockRead(*window_update_dummy
, 3),
6092 CreateMockRead(*window_update_dummy
, 4),
6093 CreateMockRead(*window_update_dummy
, 5),
6094 CreateMockRead(*window_update
, 6), // Four updates, therefore window
6095 CreateMockRead(*window_update
, 7), // size should increase by
6096 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
6097 CreateMockRead(*window_update
, 9),
6098 CreateMockRead(*resp
, 10),
6099 CreateMockRead(*body_end
, 11),
6100 MockRead(ASYNC
, 0, 0, 12) // EOF
6103 DeterministicSocketData
data(reads
, arraysize(reads
),
6104 writes
, arraysize(writes
));
6106 ScopedVector
<UploadElementReader
> element_readers
;
6107 for (int i
= 0; i
< kFrameCount
; ++i
) {
6108 element_readers
.push_back(
6109 new UploadBytesElementReader(content
->c_str(), content
->size()));
6111 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6113 // Setup the request
6114 HttpRequestInfo request
;
6115 request
.method
= "POST";
6116 request
.url
= GURL(kDefaultURL
);
6117 request
.upload_data_stream
= &upload_data_stream
;
6119 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6120 BoundNetLog(), GetParam(), NULL
);
6121 helper
.SetDeterministic();
6122 helper
.AddDeterministicData(&data
);
6123 helper
.RunPreTestSetup();
6125 HttpNetworkTransaction
* trans
= helper
.trans();
6127 TestCompletionCallback callback
;
6128 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6130 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6134 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6135 ASSERT_TRUE(stream
!= NULL
);
6136 ASSERT_TRUE(stream
->stream() != NULL
);
6138 static_cast<int>(SpdySession::GetInitialWindowSize(GetParam().protocol
)) +
6139 kDeltaWindowSize
* kDeltaCount
- kMaxSpdyFrameChunkSize
* kFrameCount
,
6140 stream
->stream()->send_window_size());
6144 rv
= callback
.WaitForResult();
6147 helper
.VerifyDataConsumed();
6150 // Test that received data frames and sent WINDOW_UPDATE frames change
6151 // the recv_window_size_ correctly.
6152 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
6153 const int32 initial_window_size
=
6154 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6155 // Amount of body required to trigger a sent window update.
6156 const size_t kTargetSize
= initial_window_size
/ 2 + 1;
6158 scoped_ptr
<SpdyFrame
> req(
6159 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6160 scoped_ptr
<SpdyFrame
> session_window_update(
6161 spdy_util_
.ConstructSpdyWindowUpdate(0, kTargetSize
));
6162 scoped_ptr
<SpdyFrame
> window_update(
6163 spdy_util_
.ConstructSpdyWindowUpdate(1, kTargetSize
));
6165 std::vector
<MockWrite
> writes
;
6166 writes
.push_back(CreateMockWrite(*req
));
6167 if (GetParam().protocol
>= kProtoSPDY31
)
6168 writes
.push_back(CreateMockWrite(*session_window_update
));
6169 writes
.push_back(CreateMockWrite(*window_update
));
6171 std::vector
<MockRead
> reads
;
6172 scoped_ptr
<SpdyFrame
> resp(
6173 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6174 reads
.push_back(CreateMockRead(*resp
));
6176 ScopedVector
<SpdyFrame
> body_frames
;
6177 const std::string
body_data(4096, 'x');
6178 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
6179 size_t frame_size
= std::min(remaining
, body_data
.size());
6180 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
6181 1, body_data
.data(), frame_size
, false));
6182 reads
.push_back(CreateMockRead(*body_frames
.back()));
6183 remaining
-= frame_size
;
6185 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
6187 DelayedSocketData
data(1, vector_as_array(&reads
), reads
.size(),
6188 vector_as_array(&writes
), writes
.size());
6190 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
6191 BoundNetLog(), GetParam(), NULL
);
6192 helper
.AddData(&data
);
6193 helper
.RunPreTestSetup();
6194 HttpNetworkTransaction
* trans
= helper
.trans();
6196 TestCompletionCallback callback
;
6197 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6199 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6200 rv
= callback
.WaitForResult();
6203 SpdyHttpStream
* stream
=
6204 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6205 ASSERT_TRUE(stream
!= NULL
);
6206 ASSERT_TRUE(stream
->stream() != NULL
);
6208 // All data has been read, but not consumed. The window reflects this.
6209 EXPECT_EQ(static_cast<int>(initial_window_size
- kTargetSize
),
6210 stream
->stream()->recv_window_size());
6212 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6213 ASSERT_TRUE(response
!= NULL
);
6214 ASSERT_TRUE(response
->headers
.get() != NULL
);
6215 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
6216 EXPECT_TRUE(response
->was_fetched_via_spdy
);
6218 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6219 // size increased to default.
6220 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kTargetSize
));
6221 EXPECT_EQ(static_cast<int>(kTargetSize
),
6222 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
6223 EXPECT_EQ(static_cast<int>(initial_window_size
),
6224 stream
->stream()->recv_window_size());
6225 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6227 // Allow scheduled WINDOW_UPDATE frames to write.
6228 base::RunLoop().RunUntilIdle();
6229 helper
.VerifyDataConsumed();
6232 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6233 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6234 // Number of full frames we hope to write (but will not, used to
6235 // set content-length header correctly)
6236 static int kFrameCount
= 3;
6238 scoped_ptr
<std::string
> content(
6239 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6240 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6241 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6242 scoped_ptr
<SpdyFrame
> body(
6243 spdy_util_
.ConstructSpdyBodyFrame(
6244 1, content
->c_str(), content
->size(), false));
6245 scoped_ptr
<SpdyFrame
> rst(
6246 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6248 // We're not going to write a data frame with FIN, we'll receive a bad
6249 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6250 MockWrite writes
[] = {
6251 CreateMockWrite(*req
, 0),
6252 CreateMockWrite(*body
, 2),
6253 CreateMockWrite(*rst
, 3),
6256 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6257 scoped_ptr
<SpdyFrame
> window_update(
6258 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6259 MockRead reads
[] = {
6260 CreateMockRead(*window_update
, 1),
6261 MockRead(ASYNC
, 0, 4) // EOF
6264 DeterministicSocketData
data(reads
, arraysize(reads
),
6265 writes
, arraysize(writes
));
6267 ScopedVector
<UploadElementReader
> element_readers
;
6268 for (int i
= 0; i
< kFrameCount
; ++i
) {
6269 element_readers
.push_back(
6270 new UploadBytesElementReader(content
->c_str(), content
->size()));
6272 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6274 // Setup the request
6275 HttpRequestInfo request
;
6276 request
.method
= "POST";
6277 request
.url
= GURL("http://www.google.com/");
6278 request
.upload_data_stream
= &upload_data_stream
;
6280 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6281 BoundNetLog(), GetParam(), NULL
);
6282 helper
.SetDeterministic();
6283 helper
.RunPreTestSetup();
6284 helper
.AddDeterministicData(&data
);
6285 HttpNetworkTransaction
* trans
= helper
.trans();
6287 TestCompletionCallback callback
;
6288 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6289 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6292 ASSERT_TRUE(callback
.have_result());
6293 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6294 helper
.VerifyDataConsumed();
6297 // Test that after hitting a send window size of 0, the write process
6298 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6300 // This test constructs a POST request followed by enough data frames
6301 // containing 'a' that would make the window size 0, followed by another
6302 // data frame containing default content (which is "hello!") and this frame
6303 // also contains a FIN flag. DelayedSocketData is used to enforce all
6304 // writes go through before a read could happen. However, the last frame
6305 // ("hello!") is not supposed to go through since by the time its turn
6306 // arrives, window size is 0. At this point MessageLoop::Run() called via
6307 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6308 // which returns after performing all possible writes. We use DCHECKS to
6309 // ensure that last data frame is still there and stream has stalled.
6310 // After that, next read is artifically enforced, which causes a
6311 // WINDOW_UPDATE to be read and I/O process resumes.
6312 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6313 const int32 initial_window_size
=
6314 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6315 // Number of frames we need to send to zero out the window size: data
6316 // frames plus SYN_STREAM plus the last data frame; also we need another
6317 // data frame that we will send once the WINDOW_UPDATE is received,
6319 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6321 // Calculate last frame's size; 0 size data frame is legal.
6322 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6324 // Construct content for a data frame of maximum size.
6325 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6327 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6328 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6331 scoped_ptr
<SpdyFrame
> body1(
6332 spdy_util_
.ConstructSpdyBodyFrame(
6333 1, content
.c_str(), content
.size(), false));
6335 // Last frame to zero out the window size.
6336 scoped_ptr
<SpdyFrame
> body2(
6337 spdy_util_
.ConstructSpdyBodyFrame(
6338 1, content
.c_str(), last_frame_size
, false));
6340 // Data frame to be sent once WINDOW_UPDATE frame is received.
6341 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6343 // Fill in mock writes.
6344 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6346 writes
[i
] = CreateMockWrite(*req
);
6347 for (i
= 1; i
< num_writes
- 2; i
++)
6348 writes
[i
] = CreateMockWrite(*body1
);
6349 writes
[i
++] = CreateMockWrite(*body2
);
6350 writes
[i
] = CreateMockWrite(*body3
);
6352 // Construct read frame, give enough space to upload the rest of the
6354 scoped_ptr
<SpdyFrame
> session_window_update(
6355 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6356 scoped_ptr
<SpdyFrame
> window_update(
6357 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6358 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6359 MockRead reads
[] = {
6360 CreateMockRead(*session_window_update
),
6361 CreateMockRead(*session_window_update
),
6362 CreateMockRead(*window_update
),
6363 CreateMockRead(*window_update
),
6364 CreateMockRead(*reply
),
6365 CreateMockRead(*body2
),
6366 CreateMockRead(*body3
),
6367 MockRead(ASYNC
, 0, 0) // EOF
6370 // Skip the session window updates unless we're using SPDY/3.1 and
6372 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6373 size_t num_reads
= arraysize(reads
) - read_offset
;
6375 // Force all writes to happen before any read, last write will not
6376 // actually queue a frame, due to window size being 0.
6377 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6378 writes
.get(), num_writes
);
6380 ScopedVector
<UploadElementReader
> element_readers
;
6381 std::string
upload_data_string(initial_window_size
, 'a');
6382 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6383 element_readers
.push_back(new UploadBytesElementReader(
6384 upload_data_string
.c_str(), upload_data_string
.size()));
6385 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6387 HttpRequestInfo request
;
6388 request
.method
= "POST";
6389 request
.url
= GURL("http://www.google.com/");
6390 request
.upload_data_stream
= &upload_data_stream
;
6391 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6392 BoundNetLog(), GetParam(), NULL
);
6393 helper
.AddData(&data
);
6394 helper
.RunPreTestSetup();
6396 HttpNetworkTransaction
* trans
= helper
.trans();
6398 TestCompletionCallback callback
;
6399 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6402 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6404 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6405 ASSERT_TRUE(stream
!= NULL
);
6406 ASSERT_TRUE(stream
->stream() != NULL
);
6407 EXPECT_EQ(0, stream
->stream()->send_window_size());
6408 // All the body data should have been read.
6409 // TODO(satorux): This is because of the weirdness in reading the request
6410 // body in OnSendBodyComplete(). See crbug.com/113107.
6411 EXPECT_TRUE(upload_data_stream
.IsEOF());
6412 // But the body is not yet fully sent (kUploadData is not yet sent)
6413 // since we're send-stalled.
6414 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6416 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6417 rv
= callback
.WaitForResult();
6418 helper
.VerifyDataConsumed();
6421 // Test we correctly handle the case where the SETTINGS frame results in
6422 // unstalling the send window.
6423 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6424 const int32 initial_window_size
=
6425 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6427 // Number of frames we need to send to zero out the window size: data
6428 // frames plus SYN_STREAM plus the last data frame; also we need another
6429 // data frame that we will send once the SETTING is received, therefore +3.
6430 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6432 // Calculate last frame's size; 0 size data frame is legal.
6433 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6435 // Construct content for a data frame of maximum size.
6436 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6438 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6439 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6442 scoped_ptr
<SpdyFrame
> body1(
6443 spdy_util_
.ConstructSpdyBodyFrame(
6444 1, content
.c_str(), content
.size(), false));
6446 // Last frame to zero out the window size.
6447 scoped_ptr
<SpdyFrame
> body2(
6448 spdy_util_
.ConstructSpdyBodyFrame(
6449 1, content
.c_str(), last_frame_size
, false));
6451 // Data frame to be sent once SETTINGS frame is received.
6452 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6454 // Fill in mock reads/writes.
6455 std::vector
<MockRead
> reads
;
6456 std::vector
<MockWrite
> writes
;
6458 writes
.push_back(CreateMockWrite(*req
, i
++));
6459 while (i
< num_writes
- 2)
6460 writes
.push_back(CreateMockWrite(*body1
, i
++));
6461 writes
.push_back(CreateMockWrite(*body2
, i
++));
6463 // Construct read frame for SETTINGS that gives enough space to upload the
6464 // rest of the data.
6465 SettingsMap settings
;
6466 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6467 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
* 2);
6468 scoped_ptr
<SpdyFrame
> settings_frame_large(
6469 spdy_util_
.ConstructSpdySettings(settings
));
6471 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6473 scoped_ptr
<SpdyFrame
> session_window_update(
6474 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6475 if (GetParam().protocol
>= kProtoSPDY31
)
6476 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6478 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6479 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6481 writes
.push_back(CreateMockWrite(*body3
, i
++));
6483 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6484 reads
.push_back(CreateMockRead(*reply
, i
++));
6485 reads
.push_back(CreateMockRead(*body2
, i
++));
6486 reads
.push_back(CreateMockRead(*body3
, i
++));
6487 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6489 // Force all writes to happen before any read, last write will not
6490 // actually queue a frame, due to window size being 0.
6491 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6492 vector_as_array(&writes
), writes
.size());
6494 ScopedVector
<UploadElementReader
> element_readers
;
6495 std::string
upload_data_string(initial_window_size
, 'a');
6496 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6497 element_readers
.push_back(new UploadBytesElementReader(
6498 upload_data_string
.c_str(), upload_data_string
.size()));
6499 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6501 HttpRequestInfo request
;
6502 request
.method
= "POST";
6503 request
.url
= GURL("http://www.google.com/");
6504 request
.upload_data_stream
= &upload_data_stream
;
6505 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6506 BoundNetLog(), GetParam(), NULL
);
6507 helper
.SetDeterministic();
6508 helper
.RunPreTestSetup();
6509 helper
.AddDeterministicData(&data
);
6511 HttpNetworkTransaction
* trans
= helper
.trans();
6513 TestCompletionCallback callback
;
6514 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6515 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6517 data
.RunFor(num_writes
- 1); // Write as much as we can.
6519 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6520 ASSERT_TRUE(stream
!= NULL
);
6521 ASSERT_TRUE(stream
->stream() != NULL
);
6522 EXPECT_EQ(0, stream
->stream()->send_window_size());
6524 // All the body data should have been read.
6525 // TODO(satorux): This is because of the weirdness in reading the request
6526 // body in OnSendBodyComplete(). See crbug.com/113107.
6527 EXPECT_TRUE(upload_data_stream
.IsEOF());
6528 // But the body is not yet fully sent (kUploadData is not yet sent)
6529 // since we're send-stalled.
6530 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6532 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6533 rv
= callback
.WaitForResult();
6534 helper
.VerifyDataConsumed();
6535 // If stream is NULL, that means it was unstalled and closed.
6536 EXPECT_TRUE(stream
->stream() == NULL
);
6539 // Test we correctly handle the case where the SETTINGS frame results in a
6540 // negative send window size.
6541 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6542 const int32 initial_window_size
=
6543 SpdySession::GetInitialWindowSize(GetParam().protocol
);
6544 // Number of frames we need to send to zero out the window size: data
6545 // frames plus SYN_STREAM plus the last data frame; also we need another
6546 // data frame that we will send once the SETTING is received, therefore +3.
6547 size_t num_writes
= initial_window_size
/ kMaxSpdyFrameChunkSize
+ 3;
6549 // Calculate last frame's size; 0 size data frame is legal.
6550 size_t last_frame_size
= initial_window_size
% kMaxSpdyFrameChunkSize
;
6552 // Construct content for a data frame of maximum size.
6553 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6555 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6556 kRequestUrl
, 1, initial_window_size
+ kUploadDataSize
, LOWEST
, NULL
, 0));
6559 scoped_ptr
<SpdyFrame
> body1(
6560 spdy_util_
.ConstructSpdyBodyFrame(
6561 1, content
.c_str(), content
.size(), false));
6563 // Last frame to zero out the window size.
6564 scoped_ptr
<SpdyFrame
> body2(
6565 spdy_util_
.ConstructSpdyBodyFrame(
6566 1, content
.c_str(), last_frame_size
, false));
6568 // Data frame to be sent once SETTINGS frame is received.
6569 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6571 // Fill in mock reads/writes.
6572 std::vector
<MockRead
> reads
;
6573 std::vector
<MockWrite
> writes
;
6575 writes
.push_back(CreateMockWrite(*req
, i
++));
6576 while (i
< num_writes
- 2)
6577 writes
.push_back(CreateMockWrite(*body1
, i
++));
6578 writes
.push_back(CreateMockWrite(*body2
, i
++));
6580 // Construct read frame for SETTINGS that makes the send_window_size
6582 SettingsMap new_settings
;
6583 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6584 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, initial_window_size
/ 2);
6585 scoped_ptr
<SpdyFrame
> settings_frame_small(
6586 spdy_util_
.ConstructSpdySettings(new_settings
));
6587 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6589 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6590 spdy_util_
.ConstructSpdyWindowUpdate(0, initial_window_size
));
6591 scoped_ptr
<SpdyFrame
> window_update_init_size(
6592 spdy_util_
.ConstructSpdyWindowUpdate(1, initial_window_size
));
6594 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6595 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6596 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6598 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6599 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6601 writes
.push_back(CreateMockWrite(*body3
, i
++));
6603 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6604 reads
.push_back(CreateMockRead(*reply
, i
++));
6605 reads
.push_back(CreateMockRead(*body2
, i
++));
6606 reads
.push_back(CreateMockRead(*body3
, i
++));
6607 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6609 // Force all writes to happen before any read, last write will not
6610 // actually queue a frame, due to window size being 0.
6611 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6612 vector_as_array(&writes
), writes
.size());
6614 ScopedVector
<UploadElementReader
> element_readers
;
6615 std::string
upload_data_string(initial_window_size
, 'a');
6616 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6617 element_readers
.push_back(new UploadBytesElementReader(
6618 upload_data_string
.c_str(), upload_data_string
.size()));
6619 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6621 HttpRequestInfo request
;
6622 request
.method
= "POST";
6623 request
.url
= GURL("http://www.google.com/");
6624 request
.upload_data_stream
= &upload_data_stream
;
6625 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6626 BoundNetLog(), GetParam(), NULL
);
6627 helper
.SetDeterministic();
6628 helper
.RunPreTestSetup();
6629 helper
.AddDeterministicData(&data
);
6631 HttpNetworkTransaction
* trans
= helper
.trans();
6633 TestCompletionCallback callback
;
6634 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6635 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6637 data
.RunFor(num_writes
- 1); // Write as much as we can.
6639 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6640 ASSERT_TRUE(stream
!= NULL
);
6641 ASSERT_TRUE(stream
->stream() != NULL
);
6642 EXPECT_EQ(0, stream
->stream()->send_window_size());
6644 // All the body data should have been read.
6645 // TODO(satorux): This is because of the weirdness in reading the request
6646 // body in OnSendBodyComplete(). See crbug.com/113107.
6647 EXPECT_TRUE(upload_data_stream
.IsEOF());
6648 // But the body is not yet fully sent (kUploadData is not yet sent)
6649 // since we're send-stalled.
6650 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6652 // Read in WINDOW_UPDATE or SETTINGS frame.
6653 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6654 rv
= callback
.WaitForResult();
6655 helper
.VerifyDataConsumed();
6658 TEST_P(SpdyNetworkTransactionTest
, GoAwayOnOddPushStreamId
) {
6659 if (spdy_util_
.spdy_version() < SPDY3
)
6662 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
6663 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6664 push_headers
.get());
6665 scoped_ptr
<SpdyFrame
> push(
6666 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 3, 1));
6667 MockRead reads
[] = {CreateMockRead(*push
, 1)};
6669 scoped_ptr
<SpdyFrame
> req(
6670 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6671 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6672 0, GOAWAY_PROTOCOL_ERROR
, "Odd push stream id."));
6673 MockWrite writes
[] = {
6674 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 2),
6677 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6678 NormalSpdyTransactionHelper
helper(
6679 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6680 helper
.RunToCompletion(&data
);
6681 TransactionHelperResult out
= helper
.output();
6682 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6685 TEST_P(SpdyNetworkTransactionTest
,
6686 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted
) {
6687 if (spdy_util_
.spdy_version() < SPDY3
)
6690 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
6691 NULL
, 0, 4, 1, "http://www.google.com/a.dat"));
6692 scoped_ptr
<SpdyHeaderBlock
> push_b_headers(new SpdyHeaderBlock
);
6693 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6694 push_b_headers
.get());
6695 scoped_ptr
<SpdyFrame
> push_b(
6696 spdy_util_
.ConstructInitialSpdyPushFrame(push_b_headers
.Pass(), 2, 1));
6697 MockRead reads
[] = {
6698 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
6701 scoped_ptr
<SpdyFrame
> req(
6702 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
6703 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
6705 GOAWAY_PROTOCOL_ERROR
,
6706 "New push stream id must be greater than the last accepted."));
6707 MockWrite writes
[] = {
6708 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
6711 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6712 NormalSpdyTransactionHelper
helper(
6713 CreateGetRequest(), DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6714 helper
.RunToCompletion(&data
);
6715 TransactionHelperResult out
= helper
.output();
6716 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6719 class SpdyNetworkTransactionNoTLSUsageCheckTest
6720 : public SpdyNetworkTransactionTest
{
6722 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6723 // Construct the request.
6724 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyGet(
6725 "https://www.google.com/", false, 1, LOWEST
));
6726 MockWrite writes
[] = {CreateMockWrite(*req
)};
6728 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6729 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6730 MockRead reads
[] = {
6731 CreateMockRead(*resp
), CreateMockRead(*body
),
6732 MockRead(ASYNC
, 0, 0) // EOF
6735 DelayedSocketData
data(
6736 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6737 HttpRequestInfo request
;
6738 request
.method
= "GET";
6739 request
.url
= GURL("https://www.google.com/");
6740 NormalSpdyTransactionHelper
helper(
6741 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6742 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6743 TransactionHelperResult out
= helper
.output();
6744 EXPECT_EQ(OK
, out
.rv
);
6745 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6746 EXPECT_EQ("hello!", out
.response_data
);
6750 //-----------------------------------------------------------------------------
6751 // All tests are run with three different connection types: SPDY after NPN
6752 // negotiation, SPDY without SSL, and SPDY with SSL.
6754 // TODO(akalin): Use ::testing::Combine() when we are able to use
6756 INSTANTIATE_TEST_CASE_P(
6758 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6759 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
)));
6761 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6762 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6763 new SSLSocketDataProvider(ASYNC
, OK
));
6764 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6765 &ssl_provider
->connection_status
);
6767 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6770 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6771 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6772 new SSLSocketDataProvider(ASYNC
, OK
));
6773 // Set to TLS_RSA_WITH_NULL_MD5
6774 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6776 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6779 class SpdyNetworkTransactionTLSUsageCheckTest
6780 : public SpdyNetworkTransactionTest
{
6782 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6783 scoped_ptr
<SpdyFrame
> goaway(
6784 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6785 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6787 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6788 HttpRequestInfo request
;
6789 request
.method
= "GET";
6790 request
.url
= GURL("https://www.google.com/");
6791 NormalSpdyTransactionHelper
helper(
6792 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6793 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6794 TransactionHelperResult out
= helper
.output();
6795 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6799 INSTANTIATE_TEST_CASE_P(
6801 SpdyNetworkTransactionTLSUsageCheckTest
,
6802 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4_14
, SPDYNPN
),
6803 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNPN
)));
6805 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6806 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6807 new SSLSocketDataProvider(ASYNC
, OK
));
6808 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6809 &ssl_provider
->connection_status
);
6811 RunTLSUsageCheckTest(ssl_provider
.Pass());
6814 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6815 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6816 new SSLSocketDataProvider(ASYNC
, OK
));
6817 // Set to TLS_RSA_WITH_NULL_MD5
6818 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6820 RunTLSUsageCheckTest(ssl_provider
.Pass());