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/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/net_log_unittest.h"
19 #include "net/base/request_priority.h"
20 #include "net/base/upload_bytes_element_reader.h"
21 #include "net/base/upload_data_stream.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/socket/client_socket_pool_base.h"
28 #include "net/socket/next_proto.h"
29 #include "net/spdy/buffered_spdy_framer.h"
30 #include "net/spdy/spdy_http_stream.h"
31 #include "net/spdy/spdy_http_utils.h"
32 #include "net/spdy/spdy_session.h"
33 #include "net/spdy/spdy_session_pool.h"
34 #include "net/spdy/spdy_test_util_common.h"
35 #include "net/spdy/spdy_test_utils.h"
36 #include "net/ssl/ssl_connection_status_flags.h"
37 #include "net/url_request/url_request_test_util.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/platform_test.h"
41 //-----------------------------------------------------------------------------
50 const char kRequestUrl
[] = "http://www.google.com/";
52 enum SpdyNetworkTransactionTestSSLType
{
58 struct SpdyNetworkTransactionTestParams
{
59 SpdyNetworkTransactionTestParams()
60 : protocol(kProtoSPDY3
),
63 SpdyNetworkTransactionTestParams(
65 SpdyNetworkTransactionTestSSLType ssl_type
)
70 SpdyNetworkTransactionTestSSLType ssl_type
;
73 void UpdateSpdySessionDependencies(
74 SpdyNetworkTransactionTestParams test_params
,
75 SpdySessionDependencies
* session_deps
) {
76 switch (test_params
.ssl_type
) {
78 session_deps
->http_server_properties
.SetAlternateProtocol(
79 HostPortPair("www.google.com", 80), 443,
80 AlternateProtocolFromNextProto(test_params
.protocol
), 1);
81 session_deps
->use_alternate_protocols
= true;
82 session_deps
->next_protos
= SpdyNextProtos();
85 session_deps
->force_spdy_over_ssl
= false;
86 session_deps
->force_spdy_always
= true;
89 session_deps
->force_spdy_over_ssl
= true;
90 session_deps
->force_spdy_always
= true;
97 SpdySessionDependencies
* CreateSpdySessionDependencies(
98 SpdyNetworkTransactionTestParams test_params
) {
99 SpdySessionDependencies
* session_deps
=
100 new SpdySessionDependencies(test_params
.protocol
);
101 UpdateSpdySessionDependencies(test_params
, session_deps
);
105 SpdySessionDependencies
* CreateSpdySessionDependencies(
106 SpdyNetworkTransactionTestParams test_params
,
107 ProxyService
* proxy_service
) {
108 SpdySessionDependencies
* session_deps
=
109 new SpdySessionDependencies(test_params
.protocol
, proxy_service
);
110 UpdateSpdySessionDependencies(test_params
, session_deps
);
116 class SpdyNetworkTransactionTest
117 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestParams
> {
119 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol
) {
122 virtual ~SpdyNetworkTransactionTest() {
123 // UploadDataStream posts deletion tasks back to the message loop on
125 upload_data_stream_
.reset();
126 base::RunLoop().RunUntilIdle();
129 virtual void SetUp() {
130 google_get_request_initialized_
= false;
131 google_post_request_initialized_
= false;
132 google_chunked_post_request_initialized_
= false;
133 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
136 struct TransactionHelperResult
{
138 std::string status_line
;
139 std::string response_data
;
140 HttpResponseInfo response_info
;
143 // A helper class that handles all the initial npn/ssl setup.
144 class NormalSpdyTransactionHelper
{
146 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
147 RequestPriority priority
,
148 const BoundNetLog
& log
,
149 SpdyNetworkTransactionTestParams test_params
,
150 SpdySessionDependencies
* session_deps
)
153 session_deps_(session_deps
== NULL
?
154 CreateSpdySessionDependencies(test_params
) :
156 session_(SpdySessionDependencies::SpdyCreateSession(
157 session_deps_
.get())),
159 test_params_(test_params
),
160 deterministic_(false),
161 spdy_enabled_(true) {
162 switch (test_params_
.ssl_type
) {
175 ~NormalSpdyTransactionHelper() {
176 // Any test which doesn't close the socket by sending it an EOF will
177 // have a valid session left open, which leaks the entire session pool.
178 // This is just fine - in fact, some of our tests intentionally do this
179 // so that we can check consistency of the SpdySessionPool as the test
180 // finishes. If we had put an EOF on the socket, the SpdySession would
181 // have closed and we wouldn't be able to check the consistency.
183 // Forcefully close existing sessions here.
184 session()->spdy_session_pool()->CloseAllSessions();
187 void SetDeterministic() {
188 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
189 session_deps_
.get());
190 deterministic_
= true;
193 void SetSpdyDisabled() {
194 spdy_enabled_
= false;
198 void RunPreTestSetup() {
199 if (!session_deps_
.get())
200 session_deps_
.reset(CreateSpdySessionDependencies(test_params_
));
201 if (!session_
.get()) {
202 session_
= SpdySessionDependencies::SpdyCreateSession(
203 session_deps_
.get());
206 // We're now ready to use SSL-npn SPDY.
207 trans_
.reset(new HttpNetworkTransaction(priority_
, session_
.get()));
210 // Start the transaction, read some data, finish.
211 void RunDefaultTest() {
212 if (!StartDefaultTest())
217 bool StartDefaultTest() {
218 output_
.rv
= trans_
->Start(&request_
, callback_
.callback(), log_
);
220 // We expect an IO Pending or some sort of error.
221 EXPECT_LT(output_
.rv
, 0);
222 return output_
.rv
== ERR_IO_PENDING
;
225 void FinishDefaultTest() {
226 output_
.rv
= callback_
.WaitForResult();
227 if (output_
.rv
!= OK
) {
228 session_
->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED
);
233 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
234 ASSERT_TRUE(response
!= NULL
);
235 ASSERT_TRUE(response
->headers
.get() != NULL
);
236 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
237 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
238 if (HttpStreamFactory::spdy_enabled()) {
240 HttpResponseInfo::ConnectionInfoFromNextProto(
241 test_params_
.protocol
),
242 response
->connection_info
);
244 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
,
245 response
->connection_info
);
247 if (test_params_
.ssl_type
== SPDYNPN
&& spdy_enabled_
) {
248 EXPECT_TRUE(response
->was_npn_negotiated
);
250 EXPECT_TRUE(!response
->was_npn_negotiated
);
252 // If SPDY is not enabled, a HTTP request should not be diverted
253 // over a SSL session.
254 if (!spdy_enabled_
) {
255 EXPECT_EQ(request_
.url
.SchemeIs("https"),
256 response
->was_npn_negotiated
);
258 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
259 EXPECT_EQ(port_
, response
->socket_address
.port());
260 output_
.status_line
= response
->headers
->GetStatusLine();
261 output_
.response_info
= *response
; // Make a copy so we can verify.
262 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
265 // Most tests will want to call this function. In particular, the MockReads
266 // should end with an empty read, and that read needs to be processed to
267 // ensure proper deletion of the spdy_session_pool.
268 void VerifyDataConsumed() {
269 for (DataVector::iterator it
= data_vector_
.begin();
270 it
!= data_vector_
.end(); ++it
) {
271 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
272 << (*it
)->read_count()
274 << (*it
)->read_index();
275 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
276 << (*it
)->write_count()
278 << (*it
)->write_index();
282 // Occasionally a test will expect to error out before certain reads are
283 // processed. In that case we want to explicitly ensure that the reads were
285 void VerifyDataNotConsumed() {
286 for (DataVector::iterator it
= data_vector_
.begin();
287 it
!= data_vector_
.end(); ++it
) {
288 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
289 << (*it
)->read_count()
291 << (*it
)->read_index();
292 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
293 << (*it
)->write_count()
295 << (*it
)->write_index();
299 void RunToCompletion(StaticSocketDataProvider
* data
) {
303 VerifyDataConsumed();
306 void RunToCompletionWithSSLData(
307 StaticSocketDataProvider
* data
,
308 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
310 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
312 VerifyDataConsumed();
315 void AddData(StaticSocketDataProvider
* data
) {
316 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
317 new SSLSocketDataProvider(ASYNC
, OK
));
318 AddDataWithSSLSocketDataProvider(data
, ssl_provider
.Pass());
321 void AddDataWithSSLSocketDataProvider(
322 StaticSocketDataProvider
* data
,
323 scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
324 DCHECK(!deterministic_
);
325 data_vector_
.push_back(data
);
326 if (test_params_
.ssl_type
== SPDYNPN
)
327 ssl_provider
->SetNextProto(test_params_
.protocol
);
329 if (test_params_
.ssl_type
== SPDYNPN
||
330 test_params_
.ssl_type
== SPDYSSL
) {
331 session_deps_
->socket_factory
->AddSSLSocketDataProvider(
334 ssl_vector_
.push_back(ssl_provider
.release());
336 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
337 if (test_params_
.ssl_type
== SPDYNPN
) {
338 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
339 StaticSocketDataProvider
* hanging_non_alternate_protocol_socket
=
340 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
341 hanging_non_alternate_protocol_socket
->set_connect_data(
342 never_finishing_connect
);
343 session_deps_
->socket_factory
->AddSocketDataProvider(
344 hanging_non_alternate_protocol_socket
);
345 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
349 void AddDeterministicData(DeterministicSocketData
* data
) {
350 DCHECK(deterministic_
);
351 data_vector_
.push_back(data
);
352 SSLSocketDataProvider
* ssl_provider
=
353 new SSLSocketDataProvider(ASYNC
, OK
);
354 if (test_params_
.ssl_type
== SPDYNPN
)
355 ssl_provider
->SetNextProto(test_params_
.protocol
);
357 ssl_vector_
.push_back(ssl_provider
);
358 if (test_params_
.ssl_type
== SPDYNPN
||
359 test_params_
.ssl_type
== SPDYSSL
) {
360 session_deps_
->deterministic_socket_factory
->
361 AddSSLSocketDataProvider(ssl_provider
);
363 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
364 if (test_params_
.ssl_type
== SPDYNPN
) {
365 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
366 DeterministicSocketData
* hanging_non_alternate_protocol_socket
=
367 new DeterministicSocketData(NULL
, 0, NULL
, 0);
368 hanging_non_alternate_protocol_socket
->set_connect_data(
369 never_finishing_connect
);
370 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
371 hanging_non_alternate_protocol_socket
);
372 alternate_deterministic_vector_
.push_back(
373 hanging_non_alternate_protocol_socket
);
377 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
380 HttpNetworkTransaction
* trans() { return trans_
.get(); }
381 void ResetTrans() { trans_
.reset(); }
382 TransactionHelperResult
& output() { return output_
; }
383 const HttpRequestInfo
& request() const { return request_
; }
384 const scoped_refptr
<HttpNetworkSession
>& session() const {
387 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
388 return session_deps_
;
390 int port() const { return port_
; }
391 SpdyNetworkTransactionTestParams
test_params() const {
396 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
397 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
398 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
399 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
400 HttpRequestInfo request_
;
401 RequestPriority priority_
;
402 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
403 scoped_refptr
<HttpNetworkSession
> session_
;
404 TransactionHelperResult output_
;
405 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
406 SSLVector ssl_vector_
;
407 TestCompletionCallback callback_
;
408 scoped_ptr
<HttpNetworkTransaction
> trans_
;
409 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
410 DataVector data_vector_
;
411 AlternateVector alternate_vector_
;
412 AlternateDeterministicVector alternate_deterministic_vector_
;
413 const BoundNetLog
& log_
;
414 SpdyNetworkTransactionTestParams test_params_
;
420 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
421 int expected_status
);
423 void ConnectStatusHelper(const MockRead
& status
);
425 const HttpRequestInfo
& CreateGetPushRequest() {
426 google_get_push_request_
.method
= "GET";
427 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
428 google_get_push_request_
.load_flags
= 0;
429 return google_get_push_request_
;
432 const HttpRequestInfo
& CreateGetRequest() {
433 if (!google_get_request_initialized_
) {
434 google_get_request_
.method
= "GET";
435 google_get_request_
.url
= GURL(kDefaultURL
);
436 google_get_request_
.load_flags
= 0;
437 google_get_request_initialized_
= true;
439 return google_get_request_
;
442 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
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_
.extra_headers
.SetHeader("User-Agent", "Chrome");
448 google_get_request_initialized_
= true;
450 return google_get_request_
;
453 const HttpRequestInfo
& CreatePostRequest() {
454 if (!google_post_request_initialized_
) {
455 ScopedVector
<UploadElementReader
> element_readers
;
456 element_readers
.push_back(
457 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
458 upload_data_stream_
.reset(
459 new UploadDataStream(element_readers
.Pass(), 0));
461 google_post_request_
.method
= "POST";
462 google_post_request_
.url
= GURL(kDefaultURL
);
463 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
464 google_post_request_initialized_
= true;
466 return google_post_request_
;
469 const HttpRequestInfo
& CreateFilePostRequest() {
470 if (!google_post_request_initialized_
) {
471 base::FilePath file_path
;
472 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
473 CHECK_EQ(static_cast<int>(kUploadDataSize
),
474 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
476 ScopedVector
<UploadElementReader
> element_readers
;
477 element_readers
.push_back(
478 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
483 upload_data_stream_
.reset(
484 new UploadDataStream(element_readers
.Pass(), 0));
486 google_post_request_
.method
= "POST";
487 google_post_request_
.url
= GURL(kDefaultURL
);
488 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
489 google_post_request_initialized_
= true;
491 return google_post_request_
;
494 const HttpRequestInfo
& CreateUnreadableFilePostRequest() {
495 if (google_post_request_initialized_
)
496 return google_post_request_
;
498 base::FilePath file_path
;
499 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
500 CHECK_EQ(static_cast<int>(kUploadDataSize
),
501 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
502 CHECK(base::MakeFileUnreadable(file_path
));
504 ScopedVector
<UploadElementReader
> element_readers
;
505 element_readers
.push_back(
506 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
511 upload_data_stream_
.reset(
512 new UploadDataStream(element_readers
.Pass(), 0));
514 google_post_request_
.method
= "POST";
515 google_post_request_
.url
= GURL(kDefaultURL
);
516 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
517 google_post_request_initialized_
= true;
518 return google_post_request_
;
521 const HttpRequestInfo
& CreateComplexPostRequest() {
522 if (!google_post_request_initialized_
) {
523 const int kFileRangeOffset
= 1;
524 const int kFileRangeLength
= 3;
525 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
527 base::FilePath file_path
;
528 CHECK(base::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
529 CHECK_EQ(static_cast<int>(kUploadDataSize
),
530 base::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
532 ScopedVector
<UploadElementReader
> element_readers
;
533 element_readers
.push_back(
534 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
535 element_readers
.push_back(
536 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
541 element_readers
.push_back(new UploadBytesElementReader(
542 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
543 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
544 upload_data_stream_
.reset(
545 new UploadDataStream(element_readers
.Pass(), 0));
547 google_post_request_
.method
= "POST";
548 google_post_request_
.url
= GURL(kDefaultURL
);
549 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
550 google_post_request_initialized_
= true;
552 return google_post_request_
;
555 const HttpRequestInfo
& CreateChunkedPostRequest() {
556 if (!google_chunked_post_request_initialized_
) {
557 upload_data_stream_
.reset(
558 new UploadDataStream(UploadDataStream::CHUNKED
, 0));
559 google_chunked_post_request_
.method
= "POST";
560 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
561 google_chunked_post_request_
.upload_data_stream
=
562 upload_data_stream_
.get();
563 google_chunked_post_request_initialized_
= true;
565 return google_chunked_post_request_
;
568 // Read the result of a particular transaction, knowing that we've got
569 // multiple transactions in the read pipeline; so as we read, we may have
570 // to skip over data destined for other transactions while we consume
571 // the data for |trans|.
572 int ReadResult(HttpNetworkTransaction
* trans
,
573 StaticSocketDataProvider
* data
,
574 std::string
* result
) {
575 const int kSize
= 3000;
578 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
579 TestCompletionCallback callback
;
581 int rv
= trans
->Read(buf
.get(), kSize
, callback
.callback());
582 if (rv
== ERR_IO_PENDING
) {
583 // Multiple transactions may be in the data set. Keep pulling off
584 // reads until we complete our callback.
585 while (!callback
.have_result()) {
586 data
->CompleteRead();
587 base::RunLoop().RunUntilIdle();
589 rv
= callback
.WaitForResult();
590 } else if (rv
<= 0) {
593 result
->append(buf
->data(), rv
);
599 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
600 // This lengthy block is reaching into the pool to dig out the active
601 // session. Once we have the session, we verify that the streams are
602 // all closed and not leaked at this point.
603 const GURL
& url
= helper
.request().url
;
604 int port
= helper
.test_params().ssl_type
== SPDYNPN
? 443 : 80;
605 HostPortPair
host_port_pair(url
.host(), port
);
606 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
607 PRIVACY_MODE_DISABLED
);
609 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
610 base::WeakPtr
<SpdySession
> spdy_session
=
611 session
->spdy_session_pool()->FindAvailableSession(key
, log
);
612 ASSERT_TRUE(spdy_session
!= NULL
);
613 EXPECT_EQ(0u, spdy_session
->num_active_streams());
614 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
617 void RunServerPushTest(OrderedSocketData
* data
,
618 HttpResponseInfo
* response
,
619 HttpResponseInfo
* push_response
,
620 const std::string
& expected
) {
621 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
622 BoundNetLog(), GetParam(), NULL
);
623 helper
.RunPreTestSetup();
624 helper
.AddData(data
);
626 HttpNetworkTransaction
* trans
= helper
.trans();
628 // Start the transaction with basic parameters.
629 TestCompletionCallback callback
;
630 int rv
= trans
->Start(
631 &CreateGetRequest(), callback
.callback(), BoundNetLog());
632 EXPECT_EQ(ERR_IO_PENDING
, rv
);
633 rv
= callback
.WaitForResult();
635 // Request the pushed path.
636 scoped_ptr
<HttpNetworkTransaction
> trans2(
637 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
639 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
641 base::RunLoop().RunUntilIdle();
643 // The data for the pushed path may be coming in more than 1 frame. Compile
644 // the results into a single string.
646 // Read the server push body.
648 ReadResult(trans2
.get(), data
, &result2
);
649 // Read the response body.
651 ReadResult(trans
, data
, &result
);
653 // Verify that we consumed all test data.
654 EXPECT_TRUE(data
->at_read_eof());
655 EXPECT_TRUE(data
->at_write_eof());
657 // Verify that the received push data is same as the expected push data.
658 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
660 << "||||| Expected data: "
663 // Verify the SYN_REPLY.
664 // Copy the response info, because trans goes away.
665 *response
= *trans
->GetResponseInfo();
666 *push_response
= *trans2
->GetResponseInfo();
668 VerifyStreamsClosed(helper
);
671 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
673 helper
->ResetTrans();
676 static void StartTransactionCallback(
677 const scoped_refptr
<HttpNetworkSession
>& session
,
679 scoped_ptr
<HttpNetworkTransaction
> trans(
680 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
681 TestCompletionCallback callback
;
682 HttpRequestInfo request
;
683 request
.method
= "GET";
684 request
.url
= GURL("http://www.google.com/");
685 request
.load_flags
= 0;
686 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
688 callback
.WaitForResult();
691 SpdyTestUtil spdy_util_
;
694 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
695 bool google_get_request_initialized_
;
696 bool google_post_request_initialized_
;
697 bool google_chunked_post_request_initialized_
;
698 HttpRequestInfo google_get_request_
;
699 HttpRequestInfo google_post_request_
;
700 HttpRequestInfo google_chunked_post_request_
;
701 HttpRequestInfo google_get_push_request_
;
702 base::ScopedTempDir temp_dir_
;
705 //-----------------------------------------------------------------------------
706 // All tests are run with three different connection types: SPDY after NPN
707 // negotiation, SPDY without SSL, and SPDY with SSL.
709 // TODO(akalin): Use ::testing::Combine() when we are able to use
711 INSTANTIATE_TEST_CASE_P(
713 SpdyNetworkTransactionTest
,
715 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
, SPDYNOSSL
),
716 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
, SPDYSSL
),
717 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
, SPDYNPN
),
718 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNOSSL
),
719 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYSSL
),
720 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNPN
),
721 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNOSSL
),
722 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYSSL
),
723 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
),
724 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNOSSL
),
725 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYSSL
),
726 SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNPN
)));
728 // Verify HttpNetworkTransaction constructor.
729 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
730 scoped_ptr
<SpdySessionDependencies
> session_deps(
731 CreateSpdySessionDependencies(GetParam()));
732 scoped_refptr
<HttpNetworkSession
> session(
733 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
734 scoped_ptr
<HttpTransaction
> trans(
735 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
738 TEST_P(SpdyNetworkTransactionTest
, Get
) {
739 // Construct the request.
740 scoped_ptr
<SpdyFrame
> req(
741 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
742 MockWrite writes
[] = { CreateMockWrite(*req
) };
744 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
745 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
747 CreateMockRead(*resp
),
748 CreateMockRead(*body
),
749 MockRead(ASYNC
, 0, 0) // EOF
752 DelayedSocketData
data(1, reads
, arraysize(reads
),
753 writes
, arraysize(writes
));
754 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
755 BoundNetLog(), GetParam(), NULL
);
756 helper
.RunToCompletion(&data
);
757 TransactionHelperResult out
= helper
.output();
758 EXPECT_EQ(OK
, out
.rv
);
759 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
760 EXPECT_EQ("hello!", out
.response_data
);
763 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
764 for (RequestPriority p
= MINIMUM_PRIORITY
; p
<= MAXIMUM_PRIORITY
;
765 p
= RequestPriority(p
+ 1)) {
766 // Construct the request.
767 scoped_ptr
<SpdyFrame
> req(
768 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
769 MockWrite writes
[] = { CreateMockWrite(*req
) };
771 SpdyPriority spdy_prio
= 0;
772 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
773 // this repeats the RequestPriority-->SpdyPriority mapping from
774 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
775 // sure it's being done right.
776 if (spdy_util_
.spdy_version() < SPDY3
) {
779 EXPECT_EQ(0, spdy_prio
);
782 EXPECT_EQ(1, spdy_prio
);
786 EXPECT_EQ(2, spdy_prio
);
789 EXPECT_EQ(3, spdy_prio
);
797 EXPECT_EQ(0, spdy_prio
);
800 EXPECT_EQ(1, spdy_prio
);
803 EXPECT_EQ(2, spdy_prio
);
806 EXPECT_EQ(3, spdy_prio
);
809 EXPECT_EQ(4, spdy_prio
);
816 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
817 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
819 CreateMockRead(*resp
),
820 CreateMockRead(*body
),
821 MockRead(ASYNC
, 0, 0) // EOF
824 DelayedSocketData
data(1, reads
, arraysize(reads
),
825 writes
, arraysize(writes
));
826 HttpRequestInfo http_req
= CreateGetRequest();
828 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
830 helper
.RunToCompletion(&data
);
831 TransactionHelperResult out
= helper
.output();
832 EXPECT_EQ(OK
, out
.rv
);
833 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
834 EXPECT_EQ("hello!", out
.response_data
);
838 // Start three gets simultaniously; making sure that multiplexed
839 // streams work properly.
841 // This can't use the TransactionHelper method, since it only
842 // handles a single transaction, and finishes them as soon
843 // as it launches them.
845 // TODO(gavinp): create a working generalized TransactionHelper that
846 // can allow multiple streams in flight.
848 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
849 scoped_ptr
<SpdyFrame
> req(
850 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
851 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
852 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
853 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
855 scoped_ptr
<SpdyFrame
> req2(
856 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
857 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
858 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
859 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
861 scoped_ptr
<SpdyFrame
> req3(
862 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
863 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
864 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
865 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
867 MockWrite writes
[] = {
868 CreateMockWrite(*req
),
869 CreateMockWrite(*req2
),
870 CreateMockWrite(*req3
),
873 CreateMockRead(*resp
, 1),
874 CreateMockRead(*body
),
875 CreateMockRead(*resp2
, 4),
876 CreateMockRead(*body2
),
877 CreateMockRead(*resp3
, 7),
878 CreateMockRead(*body3
),
880 CreateMockRead(*fbody
),
881 CreateMockRead(*fbody2
),
882 CreateMockRead(*fbody3
),
884 MockRead(ASYNC
, 0, 0), // EOF
886 OrderedSocketData
data(reads
, arraysize(reads
),
887 writes
, arraysize(writes
));
888 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
891 TransactionHelperResult out
;
892 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
893 BoundNetLog(), GetParam(), NULL
);
894 helper
.RunPreTestSetup();
895 helper
.AddData(&data
);
896 // We require placeholder data because three get requests are sent out, so
897 // there needs to be three sets of SSL connection data.
898 helper
.AddData(&data_placeholder
);
899 helper
.AddData(&data_placeholder
);
900 scoped_ptr
<HttpNetworkTransaction
> trans1(
901 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
902 scoped_ptr
<HttpNetworkTransaction
> trans2(
903 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
904 scoped_ptr
<HttpNetworkTransaction
> trans3(
905 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
907 TestCompletionCallback callback1
;
908 TestCompletionCallback callback2
;
909 TestCompletionCallback callback3
;
911 HttpRequestInfo httpreq1
= CreateGetRequest();
912 HttpRequestInfo httpreq2
= CreateGetRequest();
913 HttpRequestInfo httpreq3
= CreateGetRequest();
915 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
916 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
917 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
918 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
919 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
920 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
922 out
.rv
= callback1
.WaitForResult();
923 ASSERT_EQ(OK
, out
.rv
);
924 out
.rv
= callback3
.WaitForResult();
925 ASSERT_EQ(OK
, out
.rv
);
927 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
928 EXPECT_TRUE(response1
->headers
.get() != NULL
);
929 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
930 out
.status_line
= response1
->headers
->GetStatusLine();
931 out
.response_info
= *response1
;
933 trans2
->GetResponseInfo();
935 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
936 helper
.VerifyDataConsumed();
937 EXPECT_EQ(OK
, out
.rv
);
939 EXPECT_EQ(OK
, out
.rv
);
940 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
941 EXPECT_EQ("hello!hello!", out
.response_data
);
944 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
945 scoped_ptr
<SpdyFrame
> req(
946 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
947 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
948 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
949 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
951 scoped_ptr
<SpdyFrame
> req2(
952 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
953 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
954 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
955 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
957 MockWrite writes
[] = {
958 CreateMockWrite(*req
),
959 CreateMockWrite(*req2
),
962 CreateMockRead(*resp
, 1),
963 CreateMockRead(*body
),
964 CreateMockRead(*resp2
, 4),
965 CreateMockRead(*body2
),
966 CreateMockRead(*fbody
),
967 CreateMockRead(*fbody2
),
968 MockRead(ASYNC
, 0, 0), // EOF
970 OrderedSocketData
data(reads
, arraysize(reads
),
971 writes
, arraysize(writes
));
973 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
975 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
976 data_placeholder
.set_connect_data(never_finishing_connect
);
979 TransactionHelperResult out
;
980 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
981 BoundNetLog(), GetParam(), NULL
);
982 helper
.RunPreTestSetup();
983 helper
.AddData(&data
);
984 // We require placeholder data because two get requests are sent out, so
985 // there needs to be two sets of SSL connection data.
986 helper
.AddData(&data_placeholder
);
987 scoped_ptr
<HttpNetworkTransaction
> trans1(
988 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
989 scoped_ptr
<HttpNetworkTransaction
> trans2(
990 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
992 TestCompletionCallback callback1
;
993 TestCompletionCallback callback2
;
995 HttpRequestInfo httpreq1
= CreateGetRequest();
996 HttpRequestInfo httpreq2
= CreateGetRequest();
998 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
999 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1000 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1001 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1003 out
.rv
= callback1
.WaitForResult();
1004 ASSERT_EQ(OK
, out
.rv
);
1005 out
.rv
= callback2
.WaitForResult();
1006 ASSERT_EQ(OK
, out
.rv
);
1008 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1009 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1010 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1011 out
.status_line
= response1
->headers
->GetStatusLine();
1012 out
.response_info
= *response1
;
1013 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1014 EXPECT_EQ(OK
, out
.rv
);
1015 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1016 EXPECT_EQ("hello!hello!", out
.response_data
);
1018 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1019 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1020 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1021 out
.status_line
= response2
->headers
->GetStatusLine();
1022 out
.response_info
= *response2
;
1023 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1024 EXPECT_EQ(OK
, out
.rv
);
1025 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1026 EXPECT_EQ("hello!hello!", out
.response_data
);
1028 helper
.VerifyDataConsumed();
1031 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
1032 scoped_ptr
<SpdyFrame
> req(
1033 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1034 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1035 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1036 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1038 scoped_ptr
<SpdyFrame
> req2(
1039 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1040 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1041 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1042 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1044 MockWrite writes
[] = {
1045 CreateMockWrite(*req
),
1046 CreateMockWrite(*req2
),
1048 MockRead reads
[] = {
1049 CreateMockRead(*resp
, 1),
1050 CreateMockRead(*body
),
1051 CreateMockRead(*resp2
, 4),
1052 CreateMockRead(*body2
),
1053 CreateMockRead(*fbody
),
1054 CreateMockRead(*fbody2
),
1055 MockRead(ASYNC
, 0, 0), // EOF
1057 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
1058 writes
, arraysize(writes
));
1060 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1062 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1063 data_placeholder
.set_connect_data(never_finishing_connect
);
1066 TransactionHelperResult out
;
1067 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1068 BoundNetLog(), GetParam(), NULL
);
1069 helper
.RunPreTestSetup();
1070 helper
.AddData(&preconnect_data
);
1071 // We require placeholder data because 3 connections are attempted (first is
1072 // the preconnect, 2nd and 3rd are the never finished connections.
1073 helper
.AddData(&data_placeholder
);
1074 helper
.AddData(&data_placeholder
);
1076 scoped_ptr
<HttpNetworkTransaction
> trans1(
1077 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1078 scoped_ptr
<HttpNetworkTransaction
> trans2(
1079 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1081 TestCompletionCallback callback1
;
1082 TestCompletionCallback callback2
;
1084 HttpRequestInfo httpreq
= CreateGetRequest();
1086 // Preconnect the first.
1087 SSLConfig preconnect_ssl_config
;
1088 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1089 HttpStreamFactory
* http_stream_factory
=
1090 helper
.session()->http_stream_factory();
1091 helper
.session()->GetNextProtos(&preconnect_ssl_config
.next_protos
);
1093 http_stream_factory
->PreconnectStreams(
1094 1, httpreq
, DEFAULT_PRIORITY
,
1095 preconnect_ssl_config
, preconnect_ssl_config
);
1097 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1098 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1099 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1100 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1102 out
.rv
= callback1
.WaitForResult();
1103 ASSERT_EQ(OK
, out
.rv
);
1104 out
.rv
= callback2
.WaitForResult();
1105 ASSERT_EQ(OK
, out
.rv
);
1107 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1108 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1109 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1110 out
.status_line
= response1
->headers
->GetStatusLine();
1111 out
.response_info
= *response1
;
1112 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1113 EXPECT_EQ(OK
, out
.rv
);
1114 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1115 EXPECT_EQ("hello!hello!", out
.response_data
);
1117 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1118 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1119 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1120 out
.status_line
= response2
->headers
->GetStatusLine();
1121 out
.response_info
= *response2
;
1122 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1123 EXPECT_EQ(OK
, out
.rv
);
1124 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1125 EXPECT_EQ("hello!hello!", out
.response_data
);
1127 helper
.VerifyDataConsumed();
1130 // Similar to ThreeGets above, however this test adds a SETTINGS
1131 // frame. The SETTINGS frame is read during the IO loop waiting on
1132 // the first transaction completion, and sets a maximum concurrent
1133 // stream limit of 1. This means that our IO loop exists after the
1134 // second transaction completes, so we can assert on read_index().
1135 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1136 // Construct the request.
1137 scoped_ptr
<SpdyFrame
> req(
1138 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1139 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1140 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1141 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1143 scoped_ptr
<SpdyFrame
> req2(
1144 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1145 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1146 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1147 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1149 scoped_ptr
<SpdyFrame
> req3(
1150 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1151 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1152 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1153 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1155 SettingsMap settings
;
1156 const uint32 max_concurrent_streams
= 1;
1157 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1158 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1159 scoped_ptr
<SpdyFrame
> settings_frame(
1160 spdy_util_
.ConstructSpdySettings(settings
));
1161 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1163 MockWrite writes
[] = {
1164 CreateMockWrite(*req
),
1165 CreateMockWrite(*settings_ack
, 2),
1166 CreateMockWrite(*req2
),
1167 CreateMockWrite(*req3
),
1170 MockRead reads
[] = {
1171 CreateMockRead(*settings_frame
, 1),
1172 CreateMockRead(*resp
),
1173 CreateMockRead(*body
),
1174 CreateMockRead(*fbody
),
1175 CreateMockRead(*resp2
, 8),
1176 CreateMockRead(*body2
),
1177 CreateMockRead(*fbody2
),
1178 CreateMockRead(*resp3
, 13),
1179 CreateMockRead(*body3
),
1180 CreateMockRead(*fbody3
),
1182 MockRead(ASYNC
, 0, 0), // EOF
1185 OrderedSocketData
data(reads
, arraysize(reads
),
1186 writes
, arraysize(writes
));
1187 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1190 TransactionHelperResult out
;
1192 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1193 BoundNetLog(), GetParam(), NULL
);
1194 helper
.RunPreTestSetup();
1195 helper
.AddData(&data
);
1196 // We require placeholder data because three get requests are sent out, so
1197 // there needs to be three sets of SSL connection data.
1198 helper
.AddData(&data_placeholder
);
1199 helper
.AddData(&data_placeholder
);
1200 scoped_ptr
<HttpNetworkTransaction
> trans1(
1201 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1202 scoped_ptr
<HttpNetworkTransaction
> trans2(
1203 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1204 scoped_ptr
<HttpNetworkTransaction
> trans3(
1205 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1207 TestCompletionCallback callback1
;
1208 TestCompletionCallback callback2
;
1209 TestCompletionCallback callback3
;
1211 HttpRequestInfo httpreq1
= CreateGetRequest();
1212 HttpRequestInfo httpreq2
= CreateGetRequest();
1213 HttpRequestInfo httpreq3
= CreateGetRequest();
1215 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1216 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1217 // Run transaction 1 through quickly to force a read of our SETTINGS
1219 out
.rv
= callback1
.WaitForResult();
1220 ASSERT_EQ(OK
, out
.rv
);
1222 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1223 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1224 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1225 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1226 out
.rv
= callback2
.WaitForResult();
1227 ASSERT_EQ(OK
, out
.rv
);
1228 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1230 out
.rv
= callback3
.WaitForResult();
1231 ASSERT_EQ(OK
, out
.rv
);
1233 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1234 ASSERT_TRUE(response1
!= NULL
);
1235 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1236 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1237 out
.status_line
= response1
->headers
->GetStatusLine();
1238 out
.response_info
= *response1
;
1239 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1240 EXPECT_EQ(OK
, out
.rv
);
1241 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1242 EXPECT_EQ("hello!hello!", out
.response_data
);
1244 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1245 out
.status_line
= response2
->headers
->GetStatusLine();
1246 out
.response_info
= *response2
;
1247 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1248 EXPECT_EQ(OK
, out
.rv
);
1249 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1250 EXPECT_EQ("hello!hello!", out
.response_data
);
1252 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1253 out
.status_line
= response3
->headers
->GetStatusLine();
1254 out
.response_info
= *response3
;
1255 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1256 EXPECT_EQ(OK
, out
.rv
);
1257 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1258 EXPECT_EQ("hello!hello!", out
.response_data
);
1260 helper
.VerifyDataConsumed();
1262 EXPECT_EQ(OK
, out
.rv
);
1265 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1266 // a fourth transaction. The third and fourth transactions have
1267 // different data ("hello!" vs "hello!hello!") and because of the
1268 // user specified priority, we expect to see them inverted in
1269 // the response from the server.
1270 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1271 // Construct the request.
1272 scoped_ptr
<SpdyFrame
> req(
1273 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1274 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1275 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1276 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1278 scoped_ptr
<SpdyFrame
> req2(
1279 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1280 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1281 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1282 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1284 scoped_ptr
<SpdyFrame
> req4(
1285 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1286 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1287 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1289 scoped_ptr
<SpdyFrame
> req3(
1290 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1291 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1292 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1293 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1295 SettingsMap settings
;
1296 const uint32 max_concurrent_streams
= 1;
1297 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1298 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1299 scoped_ptr
<SpdyFrame
> settings_frame(
1300 spdy_util_
.ConstructSpdySettings(settings
));
1301 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1303 MockWrite writes
[] = { CreateMockWrite(*req
),
1304 CreateMockWrite(*settings_ack
, 2),
1305 CreateMockWrite(*req2
),
1306 CreateMockWrite(*req4
),
1307 CreateMockWrite(*req3
),
1309 MockRead reads
[] = {
1310 CreateMockRead(*settings_frame
, 1),
1311 CreateMockRead(*resp
),
1312 CreateMockRead(*body
),
1313 CreateMockRead(*fbody
),
1314 CreateMockRead(*resp2
, 8),
1315 CreateMockRead(*body2
),
1316 CreateMockRead(*fbody2
),
1317 CreateMockRead(*resp4
, 14),
1318 CreateMockRead(*fbody4
),
1319 CreateMockRead(*resp3
, 17),
1320 CreateMockRead(*body3
),
1321 CreateMockRead(*fbody3
),
1323 MockRead(ASYNC
, 0, 0), // EOF
1326 OrderedSocketData
data(reads
, arraysize(reads
),
1327 writes
, arraysize(writes
));
1328 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1331 TransactionHelperResult out
;
1332 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1333 BoundNetLog(), GetParam(), NULL
);
1334 helper
.RunPreTestSetup();
1335 helper
.AddData(&data
);
1336 // We require placeholder data because four get requests are sent out, so
1337 // there needs to be four sets of SSL connection data.
1338 helper
.AddData(&data_placeholder
);
1339 helper
.AddData(&data_placeholder
);
1340 helper
.AddData(&data_placeholder
);
1341 scoped_ptr
<HttpNetworkTransaction
> trans1(
1342 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1343 scoped_ptr
<HttpNetworkTransaction
> trans2(
1344 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1345 scoped_ptr
<HttpNetworkTransaction
> trans3(
1346 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1347 scoped_ptr
<HttpNetworkTransaction
> trans4(
1348 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1350 TestCompletionCallback callback1
;
1351 TestCompletionCallback callback2
;
1352 TestCompletionCallback callback3
;
1353 TestCompletionCallback callback4
;
1355 HttpRequestInfo httpreq1
= CreateGetRequest();
1356 HttpRequestInfo httpreq2
= CreateGetRequest();
1357 HttpRequestInfo httpreq3
= CreateGetRequest();
1358 HttpRequestInfo httpreq4
= CreateGetRequest();
1360 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1361 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1362 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1363 out
.rv
= callback1
.WaitForResult();
1364 ASSERT_EQ(OK
, out
.rv
);
1366 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1367 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1368 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1369 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1370 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1371 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1373 out
.rv
= callback2
.WaitForResult();
1374 ASSERT_EQ(OK
, out
.rv
);
1375 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1377 out
.rv
= callback3
.WaitForResult();
1378 ASSERT_EQ(OK
, out
.rv
);
1380 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1381 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1382 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1383 out
.status_line
= response1
->headers
->GetStatusLine();
1384 out
.response_info
= *response1
;
1385 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1386 EXPECT_EQ(OK
, out
.rv
);
1387 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1388 EXPECT_EQ("hello!hello!", out
.response_data
);
1390 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1391 out
.status_line
= response2
->headers
->GetStatusLine();
1392 out
.response_info
= *response2
;
1393 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1394 EXPECT_EQ(OK
, out
.rv
);
1395 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1396 EXPECT_EQ("hello!hello!", out
.response_data
);
1398 // notice: response3 gets two hellos, response4 gets one
1399 // hello, so we know dequeuing priority was respected.
1400 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1401 out
.status_line
= response3
->headers
->GetStatusLine();
1402 out
.response_info
= *response3
;
1403 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1404 EXPECT_EQ(OK
, out
.rv
);
1405 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1406 EXPECT_EQ("hello!hello!", out
.response_data
);
1408 out
.rv
= callback4
.WaitForResult();
1409 EXPECT_EQ(OK
, out
.rv
);
1410 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1411 out
.status_line
= response4
->headers
->GetStatusLine();
1412 out
.response_info
= *response4
;
1413 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1414 EXPECT_EQ(OK
, out
.rv
);
1415 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1416 EXPECT_EQ("hello!", out
.response_data
);
1417 helper
.VerifyDataConsumed();
1418 EXPECT_EQ(OK
, out
.rv
);
1421 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1422 // deletes a session in the middle of the transaction to insure
1423 // that we properly remove pendingcreatestream objects from
1425 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1426 // Construct the request.
1427 scoped_ptr
<SpdyFrame
> req(
1428 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1429 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1430 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1431 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1433 scoped_ptr
<SpdyFrame
> req2(
1434 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1435 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1436 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1437 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1439 SettingsMap settings
;
1440 const uint32 max_concurrent_streams
= 1;
1441 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1442 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1443 scoped_ptr
<SpdyFrame
> settings_frame(
1444 spdy_util_
.ConstructSpdySettings(settings
));
1445 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1447 MockWrite writes
[] = {
1448 CreateMockWrite(*req
),
1449 CreateMockWrite(*settings_ack
, 2),
1450 CreateMockWrite(*req2
),
1452 MockRead reads
[] = {
1453 CreateMockRead(*settings_frame
, 1),
1454 CreateMockRead(*resp
),
1455 CreateMockRead(*body
),
1456 CreateMockRead(*fbody
),
1457 CreateMockRead(*resp2
, 8),
1458 CreateMockRead(*body2
),
1459 CreateMockRead(*fbody2
),
1460 MockRead(ASYNC
, 0, 0), // EOF
1463 OrderedSocketData
data(reads
, arraysize(reads
),
1464 writes
, arraysize(writes
));
1465 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1468 TransactionHelperResult out
;
1469 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1470 BoundNetLog(), GetParam(), NULL
);
1471 helper
.RunPreTestSetup();
1472 helper
.AddData(&data
);
1473 // We require placeholder data because three get requests are sent out, so
1474 // there needs to be three sets of SSL connection data.
1475 helper
.AddData(&data_placeholder
);
1476 helper
.AddData(&data_placeholder
);
1477 scoped_ptr
<HttpNetworkTransaction
> trans1(
1478 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1479 scoped_ptr
<HttpNetworkTransaction
> trans2(
1480 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1481 scoped_ptr
<HttpNetworkTransaction
> trans3(
1482 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1484 TestCompletionCallback callback1
;
1485 TestCompletionCallback callback2
;
1486 TestCompletionCallback callback3
;
1488 HttpRequestInfo httpreq1
= CreateGetRequest();
1489 HttpRequestInfo httpreq2
= CreateGetRequest();
1490 HttpRequestInfo httpreq3
= CreateGetRequest();
1492 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1493 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1494 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1495 out
.rv
= callback1
.WaitForResult();
1496 ASSERT_EQ(OK
, out
.rv
);
1498 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1499 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1500 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1501 delete trans3
.release();
1502 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1503 out
.rv
= callback2
.WaitForResult();
1504 ASSERT_EQ(OK
, out
.rv
);
1506 EXPECT_EQ(8U, data
.read_index());
1508 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1509 ASSERT_TRUE(response1
!= NULL
);
1510 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1511 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1512 out
.status_line
= response1
->headers
->GetStatusLine();
1513 out
.response_info
= *response1
;
1514 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1515 EXPECT_EQ(OK
, out
.rv
);
1516 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1517 EXPECT_EQ("hello!hello!", out
.response_data
);
1519 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1520 ASSERT_TRUE(response2
!= NULL
);
1521 out
.status_line
= response2
->headers
->GetStatusLine();
1522 out
.response_info
= *response2
;
1523 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1524 EXPECT_EQ(OK
, out
.rv
);
1525 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1526 EXPECT_EQ("hello!hello!", out
.response_data
);
1527 helper
.VerifyDataConsumed();
1528 EXPECT_EQ(OK
, out
.rv
);
1533 // The KillerCallback will delete the transaction on error as part of the
1535 class KillerCallback
: public TestCompletionCallbackBase
{
1537 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1538 : transaction_(transaction
),
1539 callback_(base::Bind(&KillerCallback::OnComplete
,
1540 base::Unretained(this))) {
1543 virtual ~KillerCallback() {}
1545 const CompletionCallback
& callback() const { return callback_
; }
1548 void OnComplete(int result
) {
1550 delete transaction_
;
1555 HttpNetworkTransaction
* transaction_
;
1556 CompletionCallback callback_
;
1561 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1562 // closes the socket while we have a pending transaction waiting for
1563 // a pending stream creation. http://crbug.com/52901
1564 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1565 // Construct the request.
1566 scoped_ptr
<SpdyFrame
> req(
1567 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1568 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1569 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1570 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1572 scoped_ptr
<SpdyFrame
> req2(
1573 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1574 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1576 SettingsMap settings
;
1577 const uint32 max_concurrent_streams
= 1;
1578 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1579 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1580 scoped_ptr
<SpdyFrame
> settings_frame(
1581 spdy_util_
.ConstructSpdySettings(settings
));
1582 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1584 MockWrite writes
[] = {
1585 CreateMockWrite(*req
),
1586 CreateMockWrite(*settings_ack
, 2),
1587 CreateMockWrite(*req2
),
1589 MockRead reads
[] = {
1590 CreateMockRead(*settings_frame
, 1),
1591 CreateMockRead(*resp
),
1592 CreateMockRead(*body
),
1593 CreateMockRead(*fin_body
),
1594 CreateMockRead(*resp2
, 8),
1595 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1598 OrderedSocketData
data(reads
, arraysize(reads
),
1599 writes
, arraysize(writes
));
1600 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1603 TransactionHelperResult out
;
1604 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1605 BoundNetLog(), GetParam(), NULL
);
1606 helper
.RunPreTestSetup();
1607 helper
.AddData(&data
);
1608 // We require placeholder data because three get requests are sent out, so
1609 // there needs to be three sets of SSL connection data.
1610 helper
.AddData(&data_placeholder
);
1611 helper
.AddData(&data_placeholder
);
1612 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1613 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1614 HttpNetworkTransaction
* trans3(
1615 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1617 TestCompletionCallback callback1
;
1618 TestCompletionCallback callback2
;
1619 KillerCallback
callback3(trans3
);
1621 HttpRequestInfo httpreq1
= CreateGetRequest();
1622 HttpRequestInfo httpreq2
= CreateGetRequest();
1623 HttpRequestInfo httpreq3
= CreateGetRequest();
1625 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1626 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1627 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1628 out
.rv
= callback1
.WaitForResult();
1629 ASSERT_EQ(OK
, out
.rv
);
1631 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1632 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1633 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1634 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1635 out
.rv
= callback3
.WaitForResult();
1636 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1638 EXPECT_EQ(6U, data
.read_index());
1640 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1641 ASSERT_TRUE(response1
!= NULL
);
1642 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1643 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1644 out
.status_line
= response1
->headers
->GetStatusLine();
1645 out
.response_info
= *response1
;
1646 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1647 EXPECT_EQ(OK
, out
.rv
);
1649 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1650 ASSERT_TRUE(response2
!= NULL
);
1651 out
.status_line
= response2
->headers
->GetStatusLine();
1652 out
.response_info
= *response2
;
1653 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1654 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1656 helper
.VerifyDataConsumed();
1659 // Test that a simple PUT request works.
1660 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1661 // Setup the request
1662 HttpRequestInfo request
;
1663 request
.method
= "PUT";
1664 request
.url
= GURL("http://www.google.com/");
1666 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1667 spdy_util_
.ConstructPutHeaderBlock("http://www.google.com", 0));
1668 scoped_ptr
<SpdyFrame
> req(
1669 spdy_util_
.ConstructSpdySyn(1, *put_headers
, LOWEST
, false, true));
1670 MockWrite writes
[] = {
1671 CreateMockWrite(*req
),
1674 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1675 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1676 MockRead reads
[] = {
1677 CreateMockRead(*resp
),
1678 CreateMockRead(*body
),
1679 MockRead(ASYNC
, 0, 0) // EOF
1682 DelayedSocketData
data(1, reads
, arraysize(reads
),
1683 writes
, arraysize(writes
));
1684 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1685 BoundNetLog(), GetParam(), NULL
);
1686 helper
.RunToCompletion(&data
);
1687 TransactionHelperResult out
= helper
.output();
1689 EXPECT_EQ(OK
, out
.rv
);
1690 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1693 // Test that a simple HEAD request works.
1694 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1695 // Setup the request
1696 HttpRequestInfo request
;
1697 request
.method
= "HEAD";
1698 request
.url
= GURL("http://www.google.com/");
1700 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1701 spdy_util_
.ConstructHeadHeaderBlock("http://www.google.com", 0));
1702 scoped_ptr
<SpdyFrame
> req(
1703 spdy_util_
.ConstructSpdySyn(1, *head_headers
, LOWEST
, false, true));
1704 MockWrite writes
[] = {
1705 CreateMockWrite(*req
),
1708 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1709 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1710 MockRead reads
[] = {
1711 CreateMockRead(*resp
),
1712 CreateMockRead(*body
),
1713 MockRead(ASYNC
, 0, 0) // EOF
1716 DelayedSocketData
data(1, reads
, arraysize(reads
),
1717 writes
, arraysize(writes
));
1718 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1719 BoundNetLog(), GetParam(), NULL
);
1720 helper
.RunToCompletion(&data
);
1721 TransactionHelperResult out
= helper
.output();
1723 EXPECT_EQ(OK
, out
.rv
);
1724 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1727 // Test that a simple POST works.
1728 TEST_P(SpdyNetworkTransactionTest
, Post
) {
1729 scoped_ptr
<SpdyFrame
> req(
1730 spdy_util_
.ConstructSpdyPost(
1731 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1732 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1733 MockWrite writes
[] = {
1734 CreateMockWrite(*req
),
1735 CreateMockWrite(*body
), // POST upload frame
1738 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1739 MockRead reads
[] = {
1740 CreateMockRead(*resp
),
1741 CreateMockRead(*body
),
1742 MockRead(ASYNC
, 0, 0) // EOF
1745 DelayedSocketData
data(2, reads
, arraysize(reads
),
1746 writes
, arraysize(writes
));
1747 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
1748 BoundNetLog(), GetParam(), NULL
);
1749 helper
.RunToCompletion(&data
);
1750 TransactionHelperResult out
= helper
.output();
1751 EXPECT_EQ(OK
, out
.rv
);
1752 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1753 EXPECT_EQ("hello!", out
.response_data
);
1756 // Test that a POST with a file works.
1757 TEST_P(SpdyNetworkTransactionTest
, FilePost
) {
1758 scoped_ptr
<SpdyFrame
> req(
1759 spdy_util_
.ConstructSpdyPost(
1760 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1761 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1762 MockWrite writes
[] = {
1763 CreateMockWrite(*req
),
1764 CreateMockWrite(*body
), // POST upload frame
1767 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1768 MockRead reads
[] = {
1769 CreateMockRead(*resp
),
1770 CreateMockRead(*body
),
1771 MockRead(ASYNC
, 0, 0) // EOF
1774 DelayedSocketData
data(2, reads
, arraysize(reads
),
1775 writes
, arraysize(writes
));
1776 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(), DEFAULT_PRIORITY
,
1777 BoundNetLog(), GetParam(), NULL
);
1778 helper
.RunToCompletion(&data
);
1779 TransactionHelperResult out
= helper
.output();
1780 EXPECT_EQ(OK
, out
.rv
);
1781 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1782 EXPECT_EQ("hello!", out
.response_data
);
1785 // Test that a POST with a unreadable file fails.
1786 TEST_P(SpdyNetworkTransactionTest
, UnreadableFilePost
) {
1787 MockWrite writes
[] = {
1788 MockWrite(ASYNC
, 0, 0) // EOF
1790 MockRead reads
[] = {
1791 MockRead(ASYNC
, 0, 0) // EOF
1794 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1795 NormalSpdyTransactionHelper
helper(CreateUnreadableFilePostRequest(),
1797 BoundNetLog(), GetParam(), NULL
);
1798 helper
.RunPreTestSetup();
1799 helper
.AddData(&data
);
1800 helper
.RunDefaultTest();
1802 base::RunLoop().RunUntilIdle();
1803 helper
.VerifyDataNotConsumed();
1804 EXPECT_EQ(ERR_ACCESS_DENIED
, helper
.output().rv
);
1807 // Test that a complex POST works.
1808 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1809 scoped_ptr
<SpdyFrame
> req(
1810 spdy_util_
.ConstructSpdyPost(
1811 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1812 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1813 MockWrite writes
[] = {
1814 CreateMockWrite(*req
),
1815 CreateMockWrite(*body
), // POST upload frame
1818 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1819 MockRead reads
[] = {
1820 CreateMockRead(*resp
),
1821 CreateMockRead(*body
),
1822 MockRead(ASYNC
, 0, 0) // EOF
1825 DelayedSocketData
data(2, reads
, arraysize(reads
),
1826 writes
, arraysize(writes
));
1827 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1829 BoundNetLog(), GetParam(), NULL
);
1830 helper
.RunToCompletion(&data
);
1831 TransactionHelperResult out
= helper
.output();
1832 EXPECT_EQ(OK
, out
.rv
);
1833 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1834 EXPECT_EQ("hello!", out
.response_data
);
1837 // Test that a chunked POST works.
1838 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1839 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1840 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1841 MockWrite writes
[] = {
1842 CreateMockWrite(*req
),
1843 CreateMockWrite(*body
),
1846 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1847 MockRead reads
[] = {
1848 CreateMockRead(*resp
),
1849 CreateMockRead(*body
),
1850 MockRead(ASYNC
, 0, 0) // EOF
1853 DelayedSocketData
data(2, reads
, arraysize(reads
),
1854 writes
, arraysize(writes
));
1855 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1857 BoundNetLog(), GetParam(), NULL
);
1859 // These chunks get merged into a single frame when being sent.
1860 const int kFirstChunkSize
= kUploadDataSize
/2;
1861 helper
.request().upload_data_stream
->AppendChunk(
1862 kUploadData
, kFirstChunkSize
, false);
1863 helper
.request().upload_data_stream
->AppendChunk(
1864 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1866 helper
.RunToCompletion(&data
);
1867 TransactionHelperResult out
= helper
.output();
1868 EXPECT_EQ(OK
, out
.rv
);
1869 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1870 EXPECT_EQ(kUploadData
, out
.response_data
);
1873 // Test that a chunked POST works with chunks appended after transaction starts.
1874 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1875 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1876 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1877 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1878 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1879 MockWrite writes
[] = {
1880 CreateMockWrite(*req
),
1881 CreateMockWrite(*chunk1
),
1882 CreateMockWrite(*chunk2
),
1883 CreateMockWrite(*chunk3
),
1886 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1887 MockRead reads
[] = {
1888 CreateMockRead(*resp
),
1889 CreateMockRead(*chunk1
),
1890 CreateMockRead(*chunk2
),
1891 CreateMockRead(*chunk3
),
1892 MockRead(ASYNC
, 0, 0) // EOF
1895 DelayedSocketData
data(4, reads
, arraysize(reads
),
1896 writes
, arraysize(writes
));
1897 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1899 BoundNetLog(), GetParam(), NULL
);
1901 helper
.request().upload_data_stream
->AppendChunk(
1902 kUploadData
, kUploadDataSize
, false);
1904 helper
.RunPreTestSetup();
1905 helper
.AddData(&data
);
1906 ASSERT_TRUE(helper
.StartDefaultTest());
1908 base::RunLoop().RunUntilIdle();
1909 helper
.request().upload_data_stream
->AppendChunk(
1910 kUploadData
, kUploadDataSize
, false);
1911 base::RunLoop().RunUntilIdle();
1912 helper
.request().upload_data_stream
->AppendChunk(
1913 kUploadData
, kUploadDataSize
, true);
1915 helper
.FinishDefaultTest();
1916 helper
.VerifyDataConsumed();
1918 std::string expected_response
;
1919 expected_response
+= kUploadData
;
1920 expected_response
+= kUploadData
;
1921 expected_response
+= kUploadData
;
1923 TransactionHelperResult out
= helper
.output();
1924 EXPECT_EQ(OK
, out
.rv
);
1925 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1926 EXPECT_EQ(expected_response
, out
.response_data
);
1929 // Test that a POST without any post data works.
1930 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1931 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1932 // Setup the request
1933 HttpRequestInfo request
;
1934 request
.method
= "POST";
1935 request
.url
= GURL(kRequestUrl
);
1936 // Create an empty UploadData.
1937 request
.upload_data_stream
= NULL
;
1939 // When request.upload_data_stream is NULL for post, content-length is
1940 // expected to be 0.
1941 scoped_ptr
<SpdyHeaderBlock
> req_block(
1942 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, 0));
1943 scoped_ptr
<SpdyFrame
> req(
1944 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1946 MockWrite writes
[] = {
1947 CreateMockWrite(*req
),
1950 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1951 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1952 MockRead reads
[] = {
1953 CreateMockRead(*resp
),
1954 CreateMockRead(*body
),
1955 MockRead(ASYNC
, 0, 0) // EOF
1958 DelayedSocketData
data(1, reads
, arraysize(reads
),
1959 writes
, arraysize(writes
));
1961 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1962 BoundNetLog(), GetParam(), NULL
);
1963 helper
.RunToCompletion(&data
);
1964 TransactionHelperResult out
= helper
.output();
1965 EXPECT_EQ(OK
, out
.rv
);
1966 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1967 EXPECT_EQ("hello!", out
.response_data
);
1970 // Test that a simple POST works.
1971 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1972 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
1973 // Create an empty UploadDataStream.
1974 ScopedVector
<UploadElementReader
> element_readers
;
1975 UploadDataStream
stream(element_readers
.Pass(), 0);
1977 // Setup the request
1978 HttpRequestInfo request
;
1979 request
.method
= "POST";
1980 request
.url
= GURL(kRequestUrl
);
1981 request
.upload_data_stream
= &stream
;
1983 const uint64 kContentLength
= 0;
1985 scoped_ptr
<SpdyHeaderBlock
> req_block(
1986 spdy_util_
.ConstructPostHeaderBlock(kRequestUrl
, kContentLength
));
1987 scoped_ptr
<SpdyFrame
> req(
1988 spdy_util_
.ConstructSpdySyn(1, *req_block
, LOWEST
, false, true));
1990 MockWrite writes
[] = {
1991 CreateMockWrite(*req
),
1994 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1995 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1996 MockRead reads
[] = {
1997 CreateMockRead(*resp
),
1998 CreateMockRead(*body
),
1999 MockRead(ASYNC
, 0, 0) // EOF
2002 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
2004 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
2005 BoundNetLog(), GetParam(), NULL
);
2006 helper
.RunToCompletion(&data
);
2007 TransactionHelperResult out
= helper
.output();
2008 EXPECT_EQ(OK
, out
.rv
);
2009 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2010 EXPECT_EQ("hello!", out
.response_data
);
2013 // While we're doing a post, the server sends the reply before upload completes.
2014 TEST_P(SpdyNetworkTransactionTest
, ResponseBeforePostCompletes
) {
2015 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
2016 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2017 MockWrite writes
[] = {
2018 CreateMockWrite(*req
, 0),
2019 CreateMockWrite(*body
, 3),
2021 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2022 MockRead reads
[] = {
2023 CreateMockRead(*resp
, 1),
2024 CreateMockRead(*body
, 2),
2025 MockRead(ASYNC
, 0, 4) // EOF
2028 // Write the request headers, and read the complete response
2029 // while still waiting for chunked request data.
2030 DeterministicSocketData
data(reads
, arraysize(reads
),
2031 writes
, arraysize(writes
));
2032 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
2034 BoundNetLog(), GetParam(), NULL
);
2035 helper
.SetDeterministic();
2036 helper
.RunPreTestSetup();
2037 helper
.AddDeterministicData(&data
);
2039 ASSERT_TRUE(helper
.StartDefaultTest());
2041 // Process the request headers, SYN_REPLY, and response body.
2042 // The request body is still in flight.
2045 const HttpResponseInfo
* response
= helper
.trans()->GetResponseInfo();
2046 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2048 // Finish sending the request body.
2049 helper
.request().upload_data_stream
->AppendChunk(
2050 kUploadData
, kUploadDataSize
, true);
2053 std::string response_body
;
2054 EXPECT_EQ(OK
, ReadTransaction(helper
.trans(), &response_body
));
2055 EXPECT_EQ(kUploadData
, response_body
);
2056 helper
.VerifyDataConsumed();
2059 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2060 // socket causes the TCP write to return zero. This test checks that the client
2061 // tries to queue up the RST_STREAM frame again.
2062 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2063 scoped_ptr
<SpdyFrame
> req(
2064 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2065 scoped_ptr
<SpdyFrame
> rst(
2066 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2067 MockWrite writes
[] = {
2068 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2069 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2070 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2073 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2074 MockRead reads
[] = {
2075 CreateMockRead(*resp
.get(), 1, ASYNC
),
2076 MockRead(ASYNC
, 0, 0, 4) // EOF
2079 DeterministicSocketData
data(reads
, arraysize(reads
),
2080 writes
, arraysize(writes
));
2081 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2082 BoundNetLog(), GetParam(), NULL
);
2083 helper
.SetDeterministic();
2084 helper
.RunPreTestSetup();
2085 helper
.AddDeterministicData(&data
);
2086 HttpNetworkTransaction
* trans
= helper
.trans();
2088 TestCompletionCallback callback
;
2089 int rv
= trans
->Start(
2090 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2091 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2095 helper
.ResetTrans();
2099 helper
.VerifyDataConsumed();
2102 // Test that the transaction doesn't crash when we don't have a reply.
2103 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2104 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2105 MockRead reads
[] = {
2106 CreateMockRead(*body
),
2107 MockRead(ASYNC
, 0, 0) // EOF
2110 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2111 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2112 BoundNetLog(), GetParam(), NULL
);
2113 helper
.RunToCompletion(&data
);
2114 TransactionHelperResult out
= helper
.output();
2115 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2118 // Test that the transaction doesn't crash when we get two replies on the same
2119 // stream ID. See http://crbug.com/45639.
2120 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2121 scoped_ptr
<SpdyFrame
> req(
2122 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2123 scoped_ptr
<SpdyFrame
> rst(
2124 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2125 MockWrite writes
[] = {
2126 CreateMockWrite(*req
),
2127 CreateMockWrite(*rst
),
2130 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2131 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2132 MockRead reads
[] = {
2133 CreateMockRead(*resp
),
2134 CreateMockRead(*resp
),
2135 CreateMockRead(*body
),
2136 MockRead(ASYNC
, 0, 0) // EOF
2139 DelayedSocketData
data(1, reads
, arraysize(reads
),
2140 writes
, arraysize(writes
));
2142 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2143 BoundNetLog(), GetParam(), NULL
);
2144 helper
.RunPreTestSetup();
2145 helper
.AddData(&data
);
2147 HttpNetworkTransaction
* trans
= helper
.trans();
2149 TestCompletionCallback callback
;
2150 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2151 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2152 rv
= callback
.WaitForResult();
2155 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2156 ASSERT_TRUE(response
!= NULL
);
2157 EXPECT_TRUE(response
->headers
.get() != NULL
);
2158 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2159 std::string response_data
;
2160 rv
= ReadTransaction(trans
, &response_data
);
2161 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2163 helper
.VerifyDataConsumed();
2166 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2167 // Construct the request.
2168 scoped_ptr
<SpdyFrame
> req(
2169 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2170 scoped_ptr
<SpdyFrame
> rst(
2171 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2172 MockWrite writes
[] = {
2173 CreateMockWrite(*req
),
2174 CreateMockWrite(*rst
),
2177 const char* const headers
[] = {
2178 "transfer-encoding", "chunked"
2180 scoped_ptr
<SpdyFrame
> resp(
2181 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2182 scoped_ptr
<SpdyFrame
> body(
2183 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2184 MockRead reads
[] = {
2185 CreateMockRead(*resp
),
2186 CreateMockRead(*body
),
2187 MockRead(ASYNC
, 0, 0) // EOF
2190 DelayedSocketData
data(1, reads
, arraysize(reads
),
2191 writes
, arraysize(writes
));
2192 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2193 BoundNetLog(), GetParam(), NULL
);
2194 helper
.RunToCompletion(&data
);
2195 TransactionHelperResult out
= helper
.output();
2196 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2198 helper
.session()->spdy_session_pool()->CloseAllSessions();
2199 helper
.VerifyDataConsumed();
2202 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2203 // Construct the request.
2204 scoped_ptr
<SpdyFrame
> req(
2205 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2206 scoped_ptr
<SpdyFrame
> rst(
2207 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2208 MockWrite writes
[] = {
2209 CreateMockWrite(*req
),
2210 CreateMockWrite(*rst
),
2213 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2214 const char* const headers
[] = {
2215 "transfer-encoding", "chunked"
2217 scoped_ptr
<SpdyFrame
> push(
2218 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2219 2, 1, "http://www.google.com/1"));
2220 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2221 MockRead reads
[] = {
2222 CreateMockRead(*resp
),
2223 CreateMockRead(*push
),
2224 CreateMockRead(*body
),
2225 MockRead(ASYNC
, 0, 0) // EOF
2228 DelayedSocketData
data(1, reads
, arraysize(reads
),
2229 writes
, arraysize(writes
));
2230 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2231 BoundNetLog(), GetParam(), NULL
);
2232 helper
.RunToCompletion(&data
);
2233 TransactionHelperResult out
= helper
.output();
2234 EXPECT_EQ(OK
, out
.rv
);
2235 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2236 EXPECT_EQ("hello!", out
.response_data
);
2238 helper
.session()->spdy_session_pool()->CloseAllSessions();
2239 helper
.VerifyDataConsumed();
2242 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2243 // Construct the request.
2244 scoped_ptr
<SpdyFrame
> req(
2245 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2246 MockWrite writes
[] = {
2247 CreateMockWrite(*req
),
2250 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2251 MockRead reads
[] = {
2252 CreateMockRead(*resp
),
2253 // This following read isn't used by the test, except during the
2254 // RunUntilIdle() call at the end since the SpdySession survives the
2255 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2256 // MockRead will do here.
2257 MockRead(ASYNC
, 0, 0) // EOF
2260 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2261 writes
, arraysize(writes
));
2263 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2264 BoundNetLog(), GetParam(), NULL
);
2265 helper
.RunPreTestSetup();
2266 helper
.AddData(&data
);
2267 HttpNetworkTransaction
* trans
= helper
.trans();
2269 TestCompletionCallback callback
;
2270 int rv
= trans
->Start(
2271 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2273 helper
.ResetTrans(); // Cancel the transaction.
2275 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2276 // MockClientSocketFactory) are still alive.
2277 base::RunLoop().RunUntilIdle();
2278 helper
.VerifyDataNotConsumed();
2281 // Verify that the client sends a Rst Frame upon cancelling the stream.
2282 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2283 scoped_ptr
<SpdyFrame
> req(
2284 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2285 scoped_ptr
<SpdyFrame
> rst(
2286 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2287 MockWrite writes
[] = {
2288 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2289 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2292 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2293 MockRead reads
[] = {
2294 CreateMockRead(*resp
, 1, ASYNC
),
2295 MockRead(ASYNC
, 0, 0, 3) // EOF
2298 DeterministicSocketData
data(reads
, arraysize(reads
),
2299 writes
, arraysize(writes
));
2301 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2304 helper
.SetDeterministic();
2305 helper
.RunPreTestSetup();
2306 helper
.AddDeterministicData(&data
);
2307 HttpNetworkTransaction
* trans
= helper
.trans();
2309 TestCompletionCallback callback
;
2311 int rv
= trans
->Start(
2312 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2313 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2317 helper
.ResetTrans();
2321 helper
.VerifyDataConsumed();
2324 // Verify that the client can correctly deal with the user callback attempting
2325 // to start another transaction on a session that is closing down. See
2326 // http://crbug.com/47455
2327 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2328 scoped_ptr
<SpdyFrame
> req(
2329 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2330 MockWrite writes
[] = { CreateMockWrite(*req
) };
2331 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2333 // The indicated length of this frame is longer than its actual length. When
2334 // the session receives an empty frame after this one, it shuts down the
2335 // session, and calls the read callback with the incomplete data.
2336 const uint8 kGetBodyFrame2
[] = {
2337 0x00, 0x00, 0x00, 0x01,
2338 0x01, 0x00, 0x00, 0x07,
2339 'h', 'e', 'l', 'l', 'o', '!',
2342 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2343 MockRead reads
[] = {
2344 CreateMockRead(*resp
, 2),
2345 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2346 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2347 arraysize(kGetBodyFrame2
), 4),
2348 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2349 MockRead(ASYNC
, 0, 0, 6), // EOF
2351 MockRead reads2
[] = {
2352 CreateMockRead(*resp
, 2),
2353 MockRead(ASYNC
, 0, 0, 3), // EOF
2356 OrderedSocketData
data(reads
, arraysize(reads
),
2357 writes
, arraysize(writes
));
2358 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2359 writes2
, arraysize(writes2
));
2361 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2362 BoundNetLog(), GetParam(), NULL
);
2363 helper
.RunPreTestSetup();
2364 helper
.AddData(&data
);
2365 helper
.AddData(&data2
);
2366 HttpNetworkTransaction
* trans
= helper
.trans();
2368 // Start the transaction with basic parameters.
2369 TestCompletionCallback callback
;
2370 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2371 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2372 rv
= callback
.WaitForResult();
2374 const int kSize
= 3000;
2375 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2379 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2381 // This forces an err_IO_pending, which sets the callback.
2382 data
.CompleteRead();
2383 // This finishes the read.
2384 data
.CompleteRead();
2385 helper
.VerifyDataConsumed();
2388 // Verify that the client can correctly deal with the user callback deleting the
2389 // transaction. Failures will usually be valgrind errors. See
2390 // http://crbug.com/46925
2391 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2392 scoped_ptr
<SpdyFrame
> req(
2393 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2394 MockWrite writes
[] = { CreateMockWrite(*req
) };
2396 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2397 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2398 MockRead reads
[] = {
2399 CreateMockRead(*resp
.get(), 2),
2400 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2401 CreateMockRead(*body
.get(), 4),
2402 MockRead(ASYNC
, 0, 0, 5), // EOF
2405 OrderedSocketData
data(reads
, arraysize(reads
),
2406 writes
, arraysize(writes
));
2408 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2409 BoundNetLog(), GetParam(), NULL
);
2410 helper
.RunPreTestSetup();
2411 helper
.AddData(&data
);
2412 HttpNetworkTransaction
* trans
= helper
.trans();
2414 // Start the transaction with basic parameters.
2415 TestCompletionCallback callback
;
2416 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2417 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2418 rv
= callback
.WaitForResult();
2420 // Setup a user callback which will delete the session, and clear out the
2421 // memory holding the stream object. Note that the callback deletes trans.
2422 const int kSize
= 3000;
2423 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2427 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2428 base::Unretained(&helper
)));
2429 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2430 data
.CompleteRead();
2432 // Finish running rest of tasks.
2433 base::RunLoop().RunUntilIdle();
2434 helper
.VerifyDataConsumed();
2437 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2438 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2439 scoped_ptr
<SpdyHeaderBlock
> headers(
2440 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2441 (*headers
)["user-agent"] = "";
2442 (*headers
)["accept-encoding"] = "gzip,deflate";
2443 scoped_ptr
<SpdyHeaderBlock
> headers2(
2444 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2445 (*headers2
)["user-agent"] = "";
2446 (*headers2
)["accept-encoding"] = "gzip,deflate";
2448 // Setup writes/reads to www.google.com
2449 scoped_ptr
<SpdyFrame
> req(
2450 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2451 scoped_ptr
<SpdyFrame
> req2(
2452 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2453 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2454 MockWrite writes
[] = {
2455 CreateMockWrite(*req
, 1),
2457 MockRead reads
[] = {
2458 CreateMockRead(*resp
, 2),
2459 MockRead(ASYNC
, 0, 0, 3) // EOF
2462 // Setup writes/reads to www.foo.com
2463 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2464 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2465 MockWrite writes2
[] = {
2466 CreateMockWrite(*req2
, 1),
2468 MockRead reads2
[] = {
2469 CreateMockRead(*resp2
, 2),
2470 CreateMockRead(*body2
, 3),
2471 MockRead(ASYNC
, 0, 0, 4) // EOF
2473 OrderedSocketData
data(reads
, arraysize(reads
),
2474 writes
, arraysize(writes
));
2475 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2476 writes2
, arraysize(writes2
));
2478 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2481 SpdyURLRequestContext
spdy_url_request_context(
2482 GetParam().protocol
,
2483 false /* force_spdy_over_ssl*/,
2484 true /* force_spdy_always */);
2485 net::URLRequest
r(GURL("http://www.google.com/"),
2488 &spdy_url_request_context
);
2489 spdy_url_request_context
.socket_factory().
2490 AddSocketDataProvider(&data
);
2491 spdy_url_request_context
.socket_factory().
2492 AddSocketDataProvider(&data2
);
2494 d
.set_quit_on_redirect(true);
2496 base::RunLoop().Run();
2498 EXPECT_EQ(1, d
.received_redirect_count());
2500 r
.FollowDeferredRedirect();
2501 base::RunLoop().Run();
2502 EXPECT_EQ(1, d
.response_started_count());
2503 EXPECT_FALSE(d
.received_data_before_response());
2504 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
.status().status());
2505 std::string
contents("hello!");
2506 EXPECT_EQ(contents
, d
.data_received());
2508 EXPECT_TRUE(data
.at_read_eof());
2509 EXPECT_TRUE(data
.at_write_eof());
2510 EXPECT_TRUE(data2
.at_read_eof());
2511 EXPECT_TRUE(data2
.at_write_eof());
2514 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2516 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2517 scoped_ptr
<SpdyHeaderBlock
> headers(
2518 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2519 (*headers
)["user-agent"] = "";
2520 (*headers
)["accept-encoding"] = "gzip,deflate";
2522 // Setup writes/reads to www.google.com
2523 scoped_ptr
<SpdyFrame
> req(
2524 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
2525 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2526 scoped_ptr
<SpdyFrame
> rep(
2527 spdy_util_
.ConstructSpdyPush(NULL
,
2531 "http://www.google.com/foo.dat",
2532 "301 Moved Permanently",
2533 "http://www.foo.com/index.php"));
2534 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2535 scoped_ptr
<SpdyFrame
> rst(
2536 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
2537 MockWrite writes
[] = {
2538 CreateMockWrite(*req
, 1),
2539 CreateMockWrite(*rst
, 6),
2541 MockRead reads
[] = {
2542 CreateMockRead(*resp
, 2),
2543 CreateMockRead(*rep
, 3),
2544 CreateMockRead(*body
, 4),
2545 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2546 MockRead(ASYNC
, 0, 0, 7) // EOF
2549 // Setup writes/reads to www.foo.com
2550 scoped_ptr
<SpdyHeaderBlock
> headers2(
2551 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2552 (*headers2
)["user-agent"] = "";
2553 (*headers2
)["accept-encoding"] = "gzip,deflate";
2554 scoped_ptr
<SpdyFrame
> req2(
2555 spdy_util_
.ConstructSpdySyn(1, *headers2
, LOWEST
, false, true));
2556 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2557 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2558 MockWrite writes2
[] = {
2559 CreateMockWrite(*req2
, 1),
2561 MockRead reads2
[] = {
2562 CreateMockRead(*resp2
, 2),
2563 CreateMockRead(*body2
, 3),
2564 MockRead(ASYNC
, 0, 0, 5) // EOF
2566 OrderedSocketData
data(reads
, arraysize(reads
),
2567 writes
, arraysize(writes
));
2568 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2569 writes2
, arraysize(writes2
));
2571 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2574 SpdyURLRequestContext
spdy_url_request_context(
2575 GetParam().protocol
,
2576 false /* force_spdy_over_ssl*/,
2577 true /* force_spdy_always */);
2579 net::URLRequest
r(GURL("http://www.google.com/"),
2582 &spdy_url_request_context
);
2583 spdy_url_request_context
.socket_factory().
2584 AddSocketDataProvider(&data
);
2587 base::RunLoop().Run();
2589 EXPECT_EQ(0, d
.received_redirect_count());
2590 std::string
contents("hello!");
2591 EXPECT_EQ(contents
, d
.data_received());
2593 net::URLRequest
r2(GURL("http://www.google.com/foo.dat"),
2596 &spdy_url_request_context
);
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(net::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_UNSAFE(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_UNSAFE(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_UNSAFE(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_UNSAFE(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
< kProtoSPDY4
) {
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 net::CapturingNetLog::CapturedEntryList entries
;
3751 log
.GetEntries(&entries
);
3753 EXPECT_LT(0u, entries
.size());
3755 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3756 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3757 net::NetLog::PHASE_BEGIN
);
3758 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3759 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3760 net::NetLog::PHASE_END
);
3761 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3762 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3763 net::NetLog::PHASE_BEGIN
);
3764 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3765 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3766 net::NetLog::PHASE_END
);
3767 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3768 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3769 net::NetLog::PHASE_BEGIN
);
3770 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3771 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3772 net::NetLog::PHASE_END
);
3774 // Check that we logged all the headers correctly
3775 pos
= net::ExpectLogContainsSomewhere(
3777 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3778 net::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
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3873 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3874 if (rv
== net::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
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3966 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3967 if (rv
== net::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
<net::IOBuffer
> buf(new net::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
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4145 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4146 if (rv
== net::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
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4223 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4224 ASSERT_EQ(net::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
- kSpdySessionInitialWindowSize
));
4420 // Construct the persisted SETTINGS frame.
4421 const SettingsMap
& settings
=
4422 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4424 scoped_ptr
<SpdyFrame
> settings_frame(
4425 spdy_util_
.ConstructSpdySettings(settings
));
4427 // Construct the request.
4428 scoped_ptr
<SpdyFrame
> req(
4429 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4431 std::vector
<MockWrite
> writes
;
4432 if (GetParam().protocol
== kProtoSPDY4
) {
4435 kHttp2ConnectionHeaderPrefix
,
4436 kHttp2ConnectionHeaderPrefixSize
));
4438 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4439 if (GetParam().protocol
>= kProtoSPDY31
) {
4440 writes
.push_back(CreateMockWrite(*initial_window_update
));
4442 writes
.push_back(CreateMockWrite(*settings_frame
));
4443 writes
.push_back(CreateMockWrite(*req
));
4445 // Construct the reply.
4446 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4447 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4448 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4449 scoped_ptr
<SpdyFrame
> reply(
4450 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4452 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4453 MockRead reads
[] = {
4454 CreateMockRead(*reply
),
4455 CreateMockRead(*body
),
4456 MockRead(ASYNC
, 0, 0) // EOF
4459 DelayedSocketData
data(2, reads
, arraysize(reads
),
4460 vector_as_array(&writes
), writes
.size());
4461 helper
.AddData(&data
);
4462 helper
.RunDefaultTest();
4463 helper
.VerifyDataConsumed();
4464 TransactionHelperResult out
= helper
.output();
4465 EXPECT_EQ(OK
, out
.rv
);
4466 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4467 EXPECT_EQ("hello!", out
.response_data
);
4470 // Verify we had two persisted settings.
4471 const SettingsMap
& settings_map
=
4472 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4474 ASSERT_EQ(2u, settings_map
.size());
4476 // Verify the first persisted setting.
4477 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4478 EXPECT_TRUE(it1
!= settings_map
.end());
4479 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4480 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4481 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4483 // Verify the second persisted setting.
4484 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4485 EXPECT_TRUE(it2
!= settings_map
.end());
4486 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4487 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4488 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4492 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4493 scoped_ptr
<SpdyFrame
> req(
4494 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4495 MockWrite writes
[] = { CreateMockWrite(*req
) };
4497 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4498 MockRead reads
[] = {
4499 CreateMockRead(*go_away
),
4502 DelayedSocketData
data(1, reads
, arraysize(reads
),
4503 writes
, arraysize(writes
));
4504 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4505 BoundNetLog(), GetParam(), NULL
);
4506 helper
.AddData(&data
);
4507 helper
.RunToCompletion(&data
);
4508 TransactionHelperResult out
= helper
.output();
4509 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4512 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4513 scoped_ptr
<SpdyFrame
> req(
4514 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4515 MockWrite writes
[] = { CreateMockWrite(*req
) };
4517 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4518 MockRead reads
[] = {
4519 CreateMockRead(*resp
),
4520 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4523 DelayedSocketData
data(1, reads
, arraysize(reads
),
4524 writes
, arraysize(writes
));
4526 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4527 log
, GetParam(), NULL
);
4528 helper
.RunPreTestSetup();
4529 helper
.AddData(&data
);
4530 HttpNetworkTransaction
* trans
= helper
.trans();
4532 TestCompletionCallback callback
;
4533 TransactionHelperResult out
;
4534 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4536 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4537 out
.rv
= callback
.WaitForResult();
4538 EXPECT_EQ(out
.rv
, OK
);
4540 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4541 EXPECT_TRUE(response
->headers
.get() != NULL
);
4542 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4543 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4544 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4546 // Verify that we consumed all test data.
4547 helper
.VerifyDataConsumed();
4550 // Test to make sure we can correctly connect through a proxy.
4551 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4552 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4553 BoundNetLog(), GetParam(), NULL
);
4554 helper
.session_deps().reset(CreateSpdySessionDependencies(
4556 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4557 helper
.SetSession(make_scoped_refptr(
4558 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4559 helper
.RunPreTestSetup();
4560 HttpNetworkTransaction
* trans
= helper
.trans();
4562 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4563 "Host: www.google.com\r\n"
4564 "Proxy-Connection: keep-alive\r\n\r\n"};
4565 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4566 "Host: www.google.com\r\n"
4567 "Proxy-Connection: keep-alive\r\n\r\n"};
4568 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4569 scoped_ptr
<SpdyFrame
> req(
4570 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4571 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4572 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4574 MockWrite writes_SPDYNPN
[] = {
4575 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4576 CreateMockWrite(*req
, 2),
4578 MockRead reads_SPDYNPN
[] = {
4579 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4580 CreateMockRead(*resp
, 3),
4581 CreateMockRead(*body
.get(), 4),
4582 MockRead(ASYNC
, 0, 0, 5),
4585 MockWrite writes_SPDYSSL
[] = {
4586 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4587 CreateMockWrite(*req
, 2),
4589 MockRead reads_SPDYSSL
[] = {
4590 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4591 CreateMockRead(*resp
, 3),
4592 CreateMockRead(*body
.get(), 4),
4593 MockRead(ASYNC
, 0, 0, 5),
4596 MockWrite writes_SPDYNOSSL
[] = {
4597 CreateMockWrite(*req
, 0),
4600 MockRead reads_SPDYNOSSL
[] = {
4601 CreateMockRead(*resp
, 1),
4602 CreateMockRead(*body
.get(), 2),
4603 MockRead(ASYNC
, 0, 0, 3),
4606 scoped_ptr
<OrderedSocketData
> data
;
4607 switch(GetParam().ssl_type
) {
4609 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4610 arraysize(reads_SPDYNOSSL
),
4612 arraysize(writes_SPDYNOSSL
)));
4615 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4616 arraysize(reads_SPDYSSL
),
4618 arraysize(writes_SPDYSSL
)));
4621 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4622 arraysize(reads_SPDYNPN
),
4624 arraysize(writes_SPDYNPN
)));
4630 helper
.AddData(data
.get());
4631 TestCompletionCallback callback
;
4633 int rv
= trans
->Start(
4634 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4635 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4637 rv
= callback
.WaitForResult();
4640 // Verify the SYN_REPLY.
4641 HttpResponseInfo response
= *trans
->GetResponseInfo();
4642 EXPECT_TRUE(response
.headers
.get() != NULL
);
4643 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4645 std::string response_data
;
4646 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4647 EXPECT_EQ("hello!", response_data
);
4648 helper
.VerifyDataConsumed();
4651 // Test to make sure we can correctly connect through a proxy to www.google.com,
4652 // if there already exists a direct spdy connection to www.google.com. See
4653 // http://crbug.com/49874
4654 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4655 // When setting up the first transaction, we store the SpdySessionPool so that
4656 // we can use the same pool in the second transaction.
4657 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4658 BoundNetLog(), GetParam(), NULL
);
4660 // Use a proxy service which returns a proxy fallback list from DIRECT to
4661 // myproxy:70. For this test there will be no fallback, so it is equivalent
4662 // to simply DIRECT. The reason for appending the second proxy is to verify
4663 // that the session pool key used does is just "DIRECT".
4664 helper
.session_deps().reset(CreateSpdySessionDependencies(
4666 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4667 helper
.SetSession(make_scoped_refptr(
4668 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4670 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4671 helper
.RunPreTestSetup();
4673 // Construct and send a simple GET request.
4674 scoped_ptr
<SpdyFrame
> req(
4675 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4676 MockWrite writes
[] = {
4677 CreateMockWrite(*req
, 1),
4680 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4681 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4682 MockRead reads
[] = {
4683 CreateMockRead(*resp
, 2),
4684 CreateMockRead(*body
, 3),
4685 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4686 MockRead(ASYNC
, 0, 5) // EOF
4688 OrderedSocketData
data(reads
, arraysize(reads
),
4689 writes
, arraysize(writes
));
4690 helper
.AddData(&data
);
4691 HttpNetworkTransaction
* trans
= helper
.trans();
4693 TestCompletionCallback callback
;
4694 TransactionHelperResult out
;
4695 out
.rv
= trans
->Start(
4696 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4698 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4699 out
.rv
= callback
.WaitForResult();
4700 EXPECT_EQ(out
.rv
, OK
);
4702 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4703 EXPECT_TRUE(response
->headers
.get() != NULL
);
4704 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4705 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4706 EXPECT_EQ(OK
, out
.rv
);
4707 out
.status_line
= response
->headers
->GetStatusLine();
4708 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4709 EXPECT_EQ("hello!", out
.response_data
);
4711 // Check that the SpdySession is still in the SpdySessionPool.
4712 HostPortPair
host_port_pair("www.google.com", helper
.port());
4713 SpdySessionKey
session_pool_key_direct(
4714 host_port_pair
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
4715 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4716 SpdySessionKey
session_pool_key_proxy(
4718 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4719 PRIVACY_MODE_DISABLED
);
4720 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4722 // Set up data for the proxy connection.
4723 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4724 "Host: www.google.com\r\n"
4725 "Proxy-Connection: keep-alive\r\n\r\n"};
4726 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4727 "Host: www.google.com\r\n"
4728 "Proxy-Connection: keep-alive\r\n\r\n"};
4729 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4730 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4731 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4732 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4733 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4735 MockWrite writes_SPDYNPN
[] = {
4736 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4737 CreateMockWrite(*req2
, 2),
4739 MockRead reads_SPDYNPN
[] = {
4740 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4741 CreateMockRead(*resp2
, 3),
4742 CreateMockRead(*body2
, 4),
4743 MockRead(ASYNC
, 0, 5) // EOF
4746 MockWrite writes_SPDYNOSSL
[] = {
4747 CreateMockWrite(*req2
, 0),
4749 MockRead reads_SPDYNOSSL
[] = {
4750 CreateMockRead(*resp2
, 1),
4751 CreateMockRead(*body2
, 2),
4752 MockRead(ASYNC
, 0, 3) // EOF
4755 MockWrite writes_SPDYSSL
[] = {
4756 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4757 CreateMockWrite(*req2
, 2),
4759 MockRead reads_SPDYSSL
[] = {
4760 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4761 CreateMockRead(*resp2
, 3),
4762 CreateMockRead(*body2
, 4),
4763 MockRead(ASYNC
, 0, 0, 5),
4766 scoped_ptr
<OrderedSocketData
> data_proxy
;
4767 switch(GetParam().ssl_type
) {
4769 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
4770 arraysize(reads_SPDYNPN
),
4772 arraysize(writes_SPDYNPN
)));
4775 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4776 arraysize(reads_SPDYNOSSL
),
4778 arraysize(writes_SPDYNOSSL
)));
4781 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
4782 arraysize(reads_SPDYSSL
),
4784 arraysize(writes_SPDYSSL
)));
4790 // Create another request to www.google.com, but this time through a proxy.
4791 HttpRequestInfo request_proxy
;
4792 request_proxy
.method
= "GET";
4793 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
4794 request_proxy
.load_flags
= 0;
4795 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
4796 CreateSpdySessionDependencies(GetParam()));
4797 // Ensure that this transaction uses the same SpdySessionPool.
4798 scoped_refptr
<HttpNetworkSession
> session_proxy(
4799 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4800 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
4801 BoundNetLog(), GetParam(), NULL
);
4802 HttpNetworkSessionPeer
session_peer(session_proxy
);
4803 scoped_ptr
<net::ProxyService
> proxy_service(
4804 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4805 session_peer
.SetProxyService(proxy_service
.get());
4806 helper_proxy
.session_deps().swap(ssd_proxy
);
4807 helper_proxy
.SetSession(session_proxy
);
4808 helper_proxy
.RunPreTestSetup();
4809 helper_proxy
.AddData(data_proxy
.get());
4811 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4812 TestCompletionCallback callback_proxy
;
4813 int rv
= trans_proxy
->Start(
4814 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
4815 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4816 rv
= callback_proxy
.WaitForResult();
4819 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4820 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
4821 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4823 std::string response_data
;
4824 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4825 EXPECT_EQ("hello!", response_data
);
4827 data
.CompleteRead();
4828 helper_proxy
.VerifyDataConsumed();
4831 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4832 // on a new connection, if the connection was previously known to be good.
4833 // This can happen when a server reboots without saying goodbye, or when
4834 // we're behind a NAT that masked the RST.
4835 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4836 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4837 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4838 MockRead reads
[] = {
4839 CreateMockRead(*resp
),
4840 CreateMockRead(*body
),
4841 MockRead(ASYNC
, ERR_IO_PENDING
),
4842 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
4845 MockRead reads2
[] = {
4846 CreateMockRead(*resp
),
4847 CreateMockRead(*body
),
4848 MockRead(ASYNC
, 0, 0) // EOF
4851 // This test has a couple of variants.
4853 // Induce the RST while waiting for our transaction to send.
4854 VARIANT_RST_DURING_SEND_COMPLETION
,
4855 // Induce the RST while waiting for our transaction to read.
4856 // In this case, the send completed - everything copied into the SNDBUF.
4857 VARIANT_RST_DURING_READ_COMPLETION
4860 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4861 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4863 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
4865 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
4867 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4868 BoundNetLog(), GetParam(), NULL
);
4869 helper
.AddData(&data1
);
4870 helper
.AddData(&data2
);
4871 helper
.RunPreTestSetup();
4873 for (int i
= 0; i
< 2; ++i
) {
4874 scoped_ptr
<HttpNetworkTransaction
> trans(
4875 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
4877 TestCompletionCallback callback
;
4878 int rv
= trans
->Start(
4879 &helper
.request(), callback
.callback(), BoundNetLog());
4880 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4881 // On the second transaction, we trigger the RST.
4883 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4884 // Writes to the socket complete asynchronously on SPDY by running
4885 // through the message loop. Complete the write here.
4886 base::RunLoop().RunUntilIdle();
4889 // Now schedule the ERR_CONNECTION_RESET.
4890 EXPECT_EQ(3u, data1
.read_index());
4891 data1
.CompleteRead();
4892 EXPECT_EQ(4u, data1
.read_index());
4894 rv
= callback
.WaitForResult();
4897 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4898 ASSERT_TRUE(response
!= NULL
);
4899 EXPECT_TRUE(response
->headers
.get() != NULL
);
4900 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4901 std::string response_data
;
4902 rv
= ReadTransaction(trans
.get(), &response_data
);
4904 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4905 EXPECT_EQ("hello!", response_data
);
4908 helper
.VerifyDataConsumed();
4912 // Test that turning SPDY on and off works properly.
4913 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4914 HttpStreamFactory::set_spdy_enabled(true);
4915 scoped_ptr
<SpdyFrame
> req(
4916 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4917 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4919 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4920 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4921 MockRead spdy_reads
[] = {
4922 CreateMockRead(*resp
),
4923 CreateMockRead(*body
),
4924 MockRead(ASYNC
, 0, 0) // EOF
4927 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
4928 spdy_writes
, arraysize(spdy_writes
));
4929 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4930 BoundNetLog(), GetParam(), NULL
);
4931 helper
.RunToCompletion(&data
);
4932 TransactionHelperResult out
= helper
.output();
4933 EXPECT_EQ(OK
, out
.rv
);
4934 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4935 EXPECT_EQ("hello!", out
.response_data
);
4937 net::HttpStreamFactory::set_spdy_enabled(false);
4938 MockRead http_reads
[] = {
4939 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4940 MockRead("hello from http"),
4941 MockRead(SYNCHRONOUS
, OK
),
4943 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
4944 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
4945 BoundNetLog(), GetParam(), NULL
);
4946 helper2
.SetSpdyDisabled();
4947 helper2
.RunToCompletion(&data2
);
4948 TransactionHelperResult out2
= helper2
.output();
4949 EXPECT_EQ(OK
, out2
.rv
);
4950 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
4951 EXPECT_EQ("hello from http", out2
.response_data
);
4953 net::HttpStreamFactory::set_spdy_enabled(true);
4956 // Tests that Basic authentication works over SPDY
4957 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
4958 net::HttpStreamFactory::set_spdy_enabled(true);
4960 // The first request will be a bare GET, the second request will be a
4961 // GET with an Authorization header.
4962 scoped_ptr
<SpdyFrame
> req_get(
4963 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4964 const char* const kExtraAuthorizationHeaders
[] = {
4965 "authorization", "Basic Zm9vOmJhcg=="
4967 scoped_ptr
<SpdyFrame
> req_get_authorization(
4968 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
4969 arraysize(kExtraAuthorizationHeaders
) / 2,
4970 false, 3, LOWEST
, true));
4971 MockWrite spdy_writes
[] = {
4972 CreateMockWrite(*req_get
, 1),
4973 CreateMockWrite(*req_get_authorization
, 4),
4976 // The first response is a 401 authentication challenge, and the second
4977 // response will be a 200 response since the second request includes a valid
4978 // Authorization header.
4979 const char* const kExtraAuthenticationHeaders
[] = {
4981 "Basic realm=\"MyRealm\""
4983 scoped_ptr
<SpdyFrame
> resp_authentication(
4984 spdy_util_
.ConstructSpdySynReplyError(
4985 "401 Authentication Required",
4986 kExtraAuthenticationHeaders
,
4987 arraysize(kExtraAuthenticationHeaders
) / 2,
4989 scoped_ptr
<SpdyFrame
> body_authentication(
4990 spdy_util_
.ConstructSpdyBodyFrame(1, true));
4991 scoped_ptr
<SpdyFrame
> resp_data(
4992 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4993 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
4994 MockRead spdy_reads
[] = {
4995 CreateMockRead(*resp_authentication
, 2),
4996 CreateMockRead(*body_authentication
, 3),
4997 CreateMockRead(*resp_data
, 5),
4998 CreateMockRead(*body_data
, 6),
4999 MockRead(ASYNC
, 0, 7),
5002 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5003 spdy_writes
, arraysize(spdy_writes
));
5004 HttpRequestInfo
request(CreateGetRequest());
5005 BoundNetLog net_log
;
5006 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5007 net_log
, GetParam(), NULL
);
5009 helper
.RunPreTestSetup();
5010 helper
.AddData(&data
);
5011 HttpNetworkTransaction
* trans
= helper
.trans();
5012 TestCompletionCallback callback
;
5013 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5014 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5015 const int rv_start_complete
= callback
.WaitForResult();
5016 EXPECT_EQ(OK
, rv_start_complete
);
5018 // Make sure the response has an auth challenge.
5019 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5020 ASSERT_TRUE(response_start
!= NULL
);
5021 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
5022 EXPECT_EQ(401, response_start
->headers
->response_code());
5023 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5024 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5025 ASSERT_TRUE(auth_challenge
!= NULL
);
5026 EXPECT_FALSE(auth_challenge
->is_proxy
);
5027 EXPECT_EQ("basic", auth_challenge
->scheme
);
5028 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5030 // Restart with a username/password.
5031 AuthCredentials
credentials(base::ASCIIToUTF16("foo"),
5032 base::ASCIIToUTF16("bar"));
5033 TestCompletionCallback callback_restart
;
5034 const int rv_restart
= trans
->RestartWithAuth(
5035 credentials
, callback_restart
.callback());
5036 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5037 const int rv_restart_complete
= callback_restart
.WaitForResult();
5038 EXPECT_EQ(OK
, rv_restart_complete
);
5039 // TODO(cbentzel): This is actually the same response object as before, but
5040 // data has changed.
5041 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5042 ASSERT_TRUE(response_restart
!= NULL
);
5043 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
5044 EXPECT_EQ(200, response_restart
->headers
->response_code());
5045 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5048 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
5049 scoped_ptr
<SpdyFrame
> stream1_syn(
5050 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5051 scoped_ptr
<SpdyFrame
> stream1_body(
5052 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5053 MockWrite writes
[] = {
5054 CreateMockWrite(*stream1_syn
, 1),
5057 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5058 spdy_util_
.AddUrlToHeaderBlock(
5059 "http://www.google.com/foo.dat", initial_headers
.get());
5060 scoped_ptr
<SpdyFrame
> stream2_syn(
5061 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5063 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5064 (*late_headers
)["hello"] = "bye";
5065 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5066 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5067 scoped_ptr
<SpdyFrame
> stream2_headers(
5068 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5076 scoped_ptr
<SpdyFrame
>
5077 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5078 const char kPushedData
[] = "pushed";
5079 scoped_ptr
<SpdyFrame
> stream2_body(
5080 spdy_util_
.ConstructSpdyBodyFrame(
5081 2, kPushedData
, strlen(kPushedData
), true));
5082 MockRead reads
[] = {
5083 CreateMockRead(*stream1_reply
, 2),
5084 CreateMockRead(*stream2_syn
, 3),
5085 CreateMockRead(*stream2_headers
, 4),
5086 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5087 CreateMockRead(*stream2_body
, 5),
5088 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5091 HttpResponseInfo response
;
5092 HttpResponseInfo response2
;
5093 std::string
expected_push_result("pushed");
5094 OrderedSocketData
data(reads
, arraysize(reads
),
5095 writes
, arraysize(writes
));
5096 RunServerPushTest(&data
,
5099 expected_push_result
);
5101 // Verify the SYN_REPLY.
5102 EXPECT_TRUE(response
.headers
.get() != NULL
);
5103 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5105 // Verify the pushed stream.
5106 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5107 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5110 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5111 // We push a stream and attempt to claim it before the headers come down.
5112 scoped_ptr
<SpdyFrame
> stream1_syn(
5113 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5114 scoped_ptr
<SpdyFrame
> stream1_body(
5115 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5116 MockWrite writes
[] = {
5117 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5120 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5121 spdy_util_
.AddUrlToHeaderBlock(
5122 "http://www.google.com/foo.dat", initial_headers
.get());
5123 scoped_ptr
<SpdyFrame
> stream2_syn(
5124 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5126 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5127 (*late_headers
)["hello"] = "bye";
5128 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5129 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5130 scoped_ptr
<SpdyFrame
> stream2_headers(
5131 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5139 scoped_ptr
<SpdyFrame
>
5140 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5141 const char kPushedData
[] = "pushed";
5142 scoped_ptr
<SpdyFrame
> stream2_body(
5143 spdy_util_
.ConstructSpdyBodyFrame(
5144 2, kPushedData
, strlen(kPushedData
), true));
5145 MockRead reads
[] = {
5146 CreateMockRead(*stream1_reply
, 1),
5147 CreateMockRead(*stream2_syn
, 2),
5148 CreateMockRead(*stream1_body
, 3),
5149 CreateMockRead(*stream2_headers
, 4),
5150 CreateMockRead(*stream2_body
, 5),
5151 MockRead(ASYNC
, 0, 6), // EOF
5154 HttpResponseInfo response
;
5155 HttpResponseInfo response2
;
5156 std::string
expected_push_result("pushed");
5157 DeterministicSocketData
data(reads
, arraysize(reads
),
5158 writes
, arraysize(writes
));
5160 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5161 BoundNetLog(), GetParam(), NULL
);
5162 helper
.SetDeterministic();
5163 helper
.AddDeterministicData(&data
);
5164 helper
.RunPreTestSetup();
5166 HttpNetworkTransaction
* trans
= helper
.trans();
5168 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5169 // and the body of the primary stream, but before we've received the HEADERS
5170 // for the pushed stream.
5173 // Start the transaction.
5174 TestCompletionCallback callback
;
5175 int rv
= trans
->Start(
5176 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5177 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5179 rv
= callback
.WaitForResult();
5182 // Request the pushed path. At this point, we've received the push, but the
5183 // headers are not yet complete.
5184 scoped_ptr
<HttpNetworkTransaction
> trans2(
5185 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5187 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5188 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5190 base::RunLoop().RunUntilIdle();
5192 // Read the server push body.
5193 std::string result2
;
5194 ReadResult(trans2
.get(), &data
, &result2
);
5195 // Read the response body.
5197 ReadResult(trans
, &data
, &result
);
5199 // Verify that the received push data is same as the expected push data.
5200 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5201 << "Received data: "
5203 << "||||| Expected data: "
5204 << expected_push_result
;
5206 // Verify the SYN_REPLY.
5207 // Copy the response info, because trans goes away.
5208 response
= *trans
->GetResponseInfo();
5209 response2
= *trans2
->GetResponseInfo();
5211 VerifyStreamsClosed(helper
);
5213 // Verify the SYN_REPLY.
5214 EXPECT_TRUE(response
.headers
.get() != NULL
);
5215 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5217 // Verify the pushed stream.
5218 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5219 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5221 // Read the final EOF (which will close the session)
5224 // Verify that we consumed all test data.
5225 EXPECT_TRUE(data
.at_read_eof());
5226 EXPECT_TRUE(data
.at_write_eof());
5229 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5230 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5231 // We push a stream and attempt to claim it before the headers come down.
5232 scoped_ptr
<SpdyFrame
> stream1_syn(
5233 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5234 scoped_ptr
<SpdyFrame
> stream1_body(
5235 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5236 MockWrite writes
[] = {
5237 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5240 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5241 if (spdy_util_
.spdy_version() < SPDY4
) {
5242 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5243 (*initial_headers
)["alpha"] = "beta";
5245 spdy_util_
.AddUrlToHeaderBlock(
5246 "http://www.google.com/foo.dat", initial_headers
.get());
5247 scoped_ptr
<SpdyFrame
> stream2_syn(
5248 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5250 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5251 (*middle_headers
)["hello"] = "bye";
5252 scoped_ptr
<SpdyFrame
> stream2_headers1(
5253 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5261 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5262 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5263 if (spdy_util_
.spdy_version() < SPDY4
) {
5264 // SPDY4/HTTP2 eliminates use of the :version header.
5265 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5267 scoped_ptr
<SpdyFrame
> stream2_headers2(
5268 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5276 scoped_ptr
<SpdyFrame
>
5277 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5278 const char kPushedData
[] = "pushed";
5279 scoped_ptr
<SpdyFrame
> stream2_body(
5280 spdy_util_
.ConstructSpdyBodyFrame(
5281 2, kPushedData
, strlen(kPushedData
), true));
5282 MockRead reads
[] = {
5283 CreateMockRead(*stream1_reply
, 1),
5284 CreateMockRead(*stream2_syn
, 2),
5285 CreateMockRead(*stream1_body
, 3),
5286 CreateMockRead(*stream2_headers1
, 4),
5287 CreateMockRead(*stream2_headers2
, 5),
5288 CreateMockRead(*stream2_body
, 6),
5289 MockRead(ASYNC
, 0, 7), // EOF
5292 HttpResponseInfo response
;
5293 HttpResponseInfo response2
;
5294 std::string
expected_push_result("pushed");
5295 DeterministicSocketData
data(reads
, arraysize(reads
),
5296 writes
, arraysize(writes
));
5298 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5299 BoundNetLog(), GetParam(), NULL
);
5300 helper
.SetDeterministic();
5301 helper
.AddDeterministicData(&data
);
5302 helper
.RunPreTestSetup();
5304 HttpNetworkTransaction
* trans
= helper
.trans();
5306 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5307 // the first HEADERS frame, and the body of the primary stream, but before
5308 // we've received the final HEADERS for the pushed stream.
5311 // Start the transaction.
5312 TestCompletionCallback callback
;
5313 int rv
= trans
->Start(
5314 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5315 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5317 rv
= callback
.WaitForResult();
5320 // Request the pushed path. At this point, we've received the push, but the
5321 // headers are not yet complete.
5322 scoped_ptr
<HttpNetworkTransaction
> trans2(
5323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5325 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5326 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5328 base::RunLoop().RunUntilIdle();
5330 // Read the server push body.
5331 std::string result2
;
5332 ReadResult(trans2
.get(), &data
, &result2
);
5333 // Read the response body.
5335 ReadResult(trans
, &data
, &result
);
5337 // Verify that the received push data is same as the expected push data.
5338 EXPECT_EQ(expected_push_result
, result2
);
5340 // Verify the SYN_REPLY.
5341 // Copy the response info, because trans goes away.
5342 response
= *trans
->GetResponseInfo();
5343 response2
= *trans2
->GetResponseInfo();
5345 VerifyStreamsClosed(helper
);
5347 // Verify the SYN_REPLY.
5348 EXPECT_TRUE(response
.headers
.get() != NULL
);
5349 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5351 // Verify the pushed stream.
5352 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5353 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5355 // Verify we got all the headers from all header blocks.
5356 if (spdy_util_
.spdy_version() < SPDY4
)
5357 EXPECT_TRUE(response2
.headers
->HasHeaderValue("alpha", "beta"));
5358 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5359 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5361 // Read the final EOF (which will close the session)
5364 // Verify that we consumed all test data.
5365 EXPECT_TRUE(data
.at_read_eof());
5366 EXPECT_TRUE(data
.at_write_eof());
5369 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5370 // We push a stream and attempt to claim it before the headers come down.
5371 scoped_ptr
<SpdyFrame
> stream1_syn(
5372 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5373 scoped_ptr
<SpdyFrame
> stream1_body(
5374 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5375 MockWrite writes
[] = {
5376 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5379 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5380 spdy_util_
.AddUrlToHeaderBlock(
5381 "http://www.google.com/foo.dat", initial_headers
.get());
5382 scoped_ptr
<SpdyFrame
> stream2_syn(
5383 spdy_util_
.ConstructInitialSpdyPushFrame(initial_headers
.Pass(), 2, 1));
5385 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5386 (*middle_headers
)["hello"] = "bye";
5387 scoped_ptr
<SpdyFrame
> stream2_headers1(
5388 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5396 scoped_ptr
<SpdyFrame
>
5397 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5398 const char kPushedData
[] = "pushed";
5399 scoped_ptr
<SpdyFrame
> stream2_body(
5400 spdy_util_
.ConstructSpdyBodyFrame(
5401 2, kPushedData
, strlen(kPushedData
), true));
5402 MockRead reads
[] = {
5403 CreateMockRead(*stream1_reply
, 1),
5404 CreateMockRead(*stream2_syn
, 2),
5405 CreateMockRead(*stream1_body
, 3),
5406 CreateMockRead(*stream2_headers1
, 4),
5407 CreateMockRead(*stream2_body
, 5),
5408 MockRead(ASYNC
, 0, 6), // EOF
5411 DeterministicSocketData
data(reads
, arraysize(reads
),
5412 writes
, arraysize(writes
));
5414 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5415 BoundNetLog(), GetParam(), NULL
);
5416 helper
.SetDeterministic();
5417 helper
.AddDeterministicData(&data
);
5418 helper
.RunPreTestSetup();
5420 HttpNetworkTransaction
* trans
= helper
.trans();
5422 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5423 // the first HEADERS frame, and the body of the primary stream, but before
5424 // we've received the final HEADERS for the pushed stream.
5427 // Start the transaction.
5428 TestCompletionCallback callback
;
5429 int rv
= trans
->Start(
5430 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5431 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5433 rv
= callback
.WaitForResult();
5436 // Request the pushed path. At this point, we've received the push, but the
5437 // headers are not yet complete.
5438 scoped_ptr
<HttpNetworkTransaction
> trans2(
5439 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5441 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5442 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5444 base::RunLoop().RunUntilIdle();
5446 // Read the server push body.
5447 std::string result2
;
5448 ReadResult(trans2
.get(), &data
, &result2
);
5449 // Read the response body.
5451 ReadResult(trans
, &data
, &result
);
5452 EXPECT_EQ("hello!", result
);
5454 // Verify that we haven't received any push data.
5455 EXPECT_EQ("", result2
);
5457 // Verify the SYN_REPLY.
5458 // Copy the response info, because trans goes away.
5459 HttpResponseInfo response
= *trans
->GetResponseInfo();
5460 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5462 VerifyStreamsClosed(helper
);
5464 // Verify the SYN_REPLY.
5465 EXPECT_TRUE(response
.headers
.get() != NULL
);
5466 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5468 // Read the final EOF (which will close the session).
5471 // Verify that we consumed all test data.
5472 EXPECT_TRUE(data
.at_read_eof());
5473 EXPECT_TRUE(data
.at_write_eof());
5476 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5477 scoped_ptr
<SpdyFrame
> req(
5478 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5479 scoped_ptr
<SpdyFrame
> rst(
5480 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5481 MockWrite writes
[] = {
5482 CreateMockWrite(*req
), CreateMockWrite(*rst
),
5485 scoped_ptr
<SpdyFrame
> stream1_reply(
5486 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5488 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5489 (*late_headers
)["hello"] = "bye";
5490 scoped_ptr
<SpdyFrame
> stream1_headers(
5491 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5498 scoped_ptr
<SpdyFrame
> stream1_body(
5499 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5500 MockRead reads
[] = {
5501 CreateMockRead(*stream1_reply
),
5502 CreateMockRead(*stream1_headers
),
5503 CreateMockRead(*stream1_body
),
5504 MockRead(ASYNC
, 0, 0) // EOF
5507 DelayedSocketData
data(1, reads
, arraysize(reads
),
5508 writes
, arraysize(writes
));
5509 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5510 BoundNetLog(), GetParam(), NULL
);
5511 helper
.RunToCompletion(&data
);
5512 TransactionHelperResult out
= helper
.output();
5513 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5516 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5517 scoped_ptr
<SpdyFrame
> req(
5518 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5519 scoped_ptr
<SpdyFrame
> rst(
5520 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5521 MockWrite writes
[] = {
5522 CreateMockWrite(*req
),
5523 CreateMockWrite(*rst
),
5526 scoped_ptr
<SpdyFrame
> stream1_reply(
5527 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5529 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5530 (*late_headers
)["hello"] = "bye";
5531 scoped_ptr
<SpdyFrame
> stream1_headers(
5532 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5539 scoped_ptr
<SpdyFrame
> stream1_body(
5540 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5541 scoped_ptr
<SpdyFrame
> stream1_body2(
5542 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5543 MockRead reads
[] = {
5544 CreateMockRead(*stream1_reply
),
5545 CreateMockRead(*stream1_body
),
5546 CreateMockRead(*stream1_headers
),
5547 CreateMockRead(*stream1_body2
),
5548 MockRead(ASYNC
, 0, 0) // EOF
5551 DelayedSocketData
data(1, reads
, arraysize(reads
),
5552 writes
, arraysize(writes
));
5553 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5554 BoundNetLog(), GetParam(), NULL
);
5555 helper
.RunToCompletion(&data
);
5556 TransactionHelperResult out
= helper
.output();
5557 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5560 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5561 // In this test we want to verify that we can't accidentally push content
5562 // which can't be pushed by this content server.
5563 // This test assumes that:
5564 // - if we're requesting http://www.foo.com/barbaz
5565 // - the browser has made a connection to "www.foo.com".
5567 // A list of the URL to fetch, followed by the URL being pushed.
5568 static const char* const kTestCases
[] = {
5569 "http://www.google.com/foo.html",
5570 "http://www.google.com:81/foo.js", // Bad port
5572 "http://www.google.com/foo.html",
5573 "https://www.google.com/foo.js", // Bad protocol
5575 "http://www.google.com/foo.html",
5576 "ftp://www.google.com/foo.js", // Invalid Protocol
5578 "http://www.google.com/foo.html",
5579 "http://blat.www.google.com/foo.js", // Cross subdomain
5581 "http://www.google.com/foo.html",
5582 "http://www.foo.com/foo.js", // Cross domain
5585 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5586 const char* url_to_fetch
= kTestCases
[index
];
5587 const char* url_to_push
= kTestCases
[index
+ 1];
5589 scoped_ptr
<SpdyFrame
> stream1_syn(
5590 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5591 scoped_ptr
<SpdyFrame
> stream1_body(
5592 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5593 scoped_ptr
<SpdyFrame
> push_rst(
5594 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5595 MockWrite writes
[] = {
5596 CreateMockWrite(*stream1_syn
, 1),
5597 CreateMockWrite(*push_rst
, 4),
5600 scoped_ptr
<SpdyFrame
>
5601 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5602 scoped_ptr
<SpdyFrame
>
5603 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5608 const char kPushedData
[] = "pushed";
5609 scoped_ptr
<SpdyFrame
> stream2_body(
5610 spdy_util_
.ConstructSpdyBodyFrame(
5611 2, kPushedData
, strlen(kPushedData
), true));
5612 scoped_ptr
<SpdyFrame
> rst(
5613 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5615 MockRead reads
[] = {
5616 CreateMockRead(*stream1_reply
, 2),
5617 CreateMockRead(*stream2_syn
, 3),
5618 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5619 CreateMockRead(*stream2_body
, 6),
5620 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5623 HttpResponseInfo response
;
5624 OrderedSocketData
data(reads
, arraysize(reads
),
5625 writes
, arraysize(writes
));
5627 HttpRequestInfo request
;
5628 request
.method
= "GET";
5629 request
.url
= GURL(url_to_fetch
);
5630 request
.load_flags
= 0;
5632 // Enable cross-origin push. Since we are not using a proxy, this should
5633 // not actually enable cross-origin SPDY push.
5634 scoped_ptr
<SpdySessionDependencies
> session_deps(
5635 CreateSpdySessionDependencies(GetParam()));
5636 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5637 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5638 BoundNetLog(), GetParam(),
5639 session_deps
.release());
5640 helper
.RunPreTestSetup();
5641 helper
.AddData(&data
);
5643 HttpNetworkTransaction
* trans
= helper
.trans();
5645 // Start the transaction with basic parameters.
5646 TestCompletionCallback callback
;
5648 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5649 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5650 rv
= callback
.WaitForResult();
5652 // Read the response body.
5654 ReadResult(trans
, &data
, &result
);
5656 // Verify that we consumed all test data.
5657 EXPECT_TRUE(data
.at_read_eof());
5658 EXPECT_TRUE(data
.at_write_eof());
5660 // Verify the SYN_REPLY.
5661 // Copy the response info, because trans goes away.
5662 response
= *trans
->GetResponseInfo();
5664 VerifyStreamsClosed(helper
);
5666 // Verify the SYN_REPLY.
5667 EXPECT_TRUE(response
.headers
.get() != NULL
);
5668 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5672 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5673 // Construct the request.
5674 scoped_ptr
<SpdyFrame
> req(
5675 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5676 scoped_ptr
<SpdyFrame
> req2(
5677 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5678 MockWrite writes
[] = {
5679 CreateMockWrite(*req
, 1),
5680 CreateMockWrite(*req2
, 3),
5683 scoped_ptr
<SpdyFrame
> refused(
5684 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5685 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5686 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5687 MockRead reads
[] = {
5688 CreateMockRead(*refused
, 2),
5689 CreateMockRead(*resp
, 4),
5690 CreateMockRead(*body
, 5),
5691 MockRead(ASYNC
, 0, 6) // EOF
5694 OrderedSocketData
data(reads
, arraysize(reads
),
5695 writes
, arraysize(writes
));
5696 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5697 BoundNetLog(), GetParam(), NULL
);
5699 helper
.RunPreTestSetup();
5700 helper
.AddData(&data
);
5702 HttpNetworkTransaction
* trans
= helper
.trans();
5704 // Start the transaction with basic parameters.
5705 TestCompletionCallback callback
;
5706 int rv
= trans
->Start(
5707 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5708 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5709 rv
= callback
.WaitForResult();
5712 // Verify that we consumed all test data.
5713 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5714 << data
.read_count()
5716 << data
.read_index();
5717 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5718 << data
.write_count()
5720 << data
.write_index();
5722 // Verify the SYN_REPLY.
5723 HttpResponseInfo response
= *trans
->GetResponseInfo();
5724 EXPECT_TRUE(response
.headers
.get() != NULL
);
5725 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5728 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5729 // This first request will start to establish the SpdySession.
5730 // Then we will start the second (MEDIUM priority) and then third
5731 // (HIGHEST priority) request in such a way that the third will actually
5732 // start before the second, causing the second to be numbered differently
5733 // than the order they were created.
5734 scoped_ptr
<SpdyFrame
> req1(
5735 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5736 scoped_ptr
<SpdyFrame
> req2(
5737 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5738 scoped_ptr
<SpdyFrame
> req3(
5739 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5740 MockWrite writes
[] = {
5741 CreateMockWrite(*req1
, 0),
5742 CreateMockWrite(*req2
, 3),
5743 CreateMockWrite(*req3
, 4),
5746 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5747 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5748 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5749 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5750 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5751 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5752 MockRead reads
[] = {
5753 CreateMockRead(*resp1
, 1),
5754 CreateMockRead(*body1
, 2),
5755 CreateMockRead(*resp2
, 5),
5756 CreateMockRead(*body2
, 6),
5757 CreateMockRead(*resp3
, 7),
5758 CreateMockRead(*body3
, 8),
5759 MockRead(ASYNC
, 0, 9) // EOF
5762 DeterministicSocketData
data(reads
, arraysize(reads
),
5763 writes
, arraysize(writes
));
5764 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5765 BoundNetLog(), GetParam(), NULL
);
5766 helper
.SetDeterministic();
5767 helper
.RunPreTestSetup();
5768 helper
.AddDeterministicData(&data
);
5770 // Start the first transaction to set up the SpdySession
5771 HttpNetworkTransaction
* trans
= helper
.trans();
5772 TestCompletionCallback callback
;
5773 HttpRequestInfo info1
= CreateGetRequest();
5774 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
5775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5777 // Run the message loop, but do not allow the write to complete.
5778 // This leaves the SpdySession with a write pending, which prevents
5779 // SpdySession from attempting subsequent writes until this write completes.
5780 base::RunLoop().RunUntilIdle();
5782 // Now, start both new transactions
5783 HttpRequestInfo info2
= CreateGetRequest();
5784 TestCompletionCallback callback2
;
5785 scoped_ptr
<HttpNetworkTransaction
> trans2(
5786 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
5787 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
5788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5789 base::RunLoop().RunUntilIdle();
5791 HttpRequestInfo info3
= CreateGetRequest();
5792 TestCompletionCallback callback3
;
5793 scoped_ptr
<HttpNetworkTransaction
> trans3(
5794 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
5795 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
5796 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5797 base::RunLoop().RunUntilIdle();
5799 // We now have two SYN_STREAM frames queued up which will be
5800 // dequeued only once the first write completes, which we
5801 // now allow to happen.
5803 EXPECT_EQ(OK
, callback
.WaitForResult());
5805 // And now we can allow everything else to run to completion.
5808 EXPECT_EQ(OK
, callback2
.WaitForResult());
5809 EXPECT_EQ(OK
, callback3
.WaitForResult());
5811 helper
.VerifyDataConsumed();
5814 // The tests below are only for SPDY/3 and above.
5816 // Test that sent data frames and received WINDOW_UPDATE frames change
5817 // the send_window_size_ correctly.
5819 // WINDOW_UPDATE is different than most other frames in that it can arrive
5820 // while the client is still sending the request body. In order to enforce
5821 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5822 // socket data provider, so that initial read that is done as soon as the
5823 // stream is created, succeeds and schedules another read. This way reads
5824 // and writes are interleaved; after doing a full frame write, SpdyStream
5825 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5826 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5827 // since request has not been completely written, therefore we feed
5828 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5829 // write, leading to a complete write of request body; after that we send
5830 // a reply with a body, to cause a graceful shutdown.
5832 // TODO(agayev): develop a socket data provider where both, reads and
5833 // writes are ordered so that writing tests like these are easy and rewrite
5834 // all these tests using it. Right now we are working around the
5835 // limitations as described above and it's not deterministic, tests may
5836 // fail under specific circumstances.
5837 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
5838 if (GetParam().protocol
< kProtoSPDY3
)
5841 static int kFrameCount
= 2;
5842 scoped_ptr
<std::string
> content(
5843 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
5844 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
5845 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
5846 scoped_ptr
<SpdyFrame
> body(
5847 spdy_util_
.ConstructSpdyBodyFrame(
5848 1, content
->c_str(), content
->size(), false));
5849 scoped_ptr
<SpdyFrame
> body_end(
5850 spdy_util_
.ConstructSpdyBodyFrame(
5851 1, content
->c_str(), content
->size(), true));
5853 MockWrite writes
[] = {
5854 CreateMockWrite(*req
, 0),
5855 CreateMockWrite(*body
, 1),
5856 CreateMockWrite(*body_end
, 2),
5859 static const int32 kDeltaWindowSize
= 0xff;
5860 static const int kDeltaCount
= 4;
5861 scoped_ptr
<SpdyFrame
> window_update(
5862 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
5863 scoped_ptr
<SpdyFrame
> window_update_dummy(
5864 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
5865 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
5866 MockRead reads
[] = {
5867 CreateMockRead(*window_update_dummy
, 3),
5868 CreateMockRead(*window_update_dummy
, 4),
5869 CreateMockRead(*window_update_dummy
, 5),
5870 CreateMockRead(*window_update
, 6), // Four updates, therefore window
5871 CreateMockRead(*window_update
, 7), // size should increase by
5872 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
5873 CreateMockRead(*window_update
, 9),
5874 CreateMockRead(*resp
, 10),
5875 CreateMockRead(*body_end
, 11),
5876 MockRead(ASYNC
, 0, 0, 12) // EOF
5879 DeterministicSocketData
data(reads
, arraysize(reads
),
5880 writes
, arraysize(writes
));
5882 ScopedVector
<UploadElementReader
> element_readers
;
5883 for (int i
= 0; i
< kFrameCount
; ++i
) {
5884 element_readers
.push_back(
5885 new UploadBytesElementReader(content
->c_str(), content
->size()));
5887 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5889 // Setup the request
5890 HttpRequestInfo request
;
5891 request
.method
= "POST";
5892 request
.url
= GURL(kDefaultURL
);
5893 request
.upload_data_stream
= &upload_data_stream
;
5895 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5896 BoundNetLog(), GetParam(), NULL
);
5897 helper
.SetDeterministic();
5898 helper
.AddDeterministicData(&data
);
5899 helper
.RunPreTestSetup();
5901 HttpNetworkTransaction
* trans
= helper
.trans();
5903 TestCompletionCallback callback
;
5904 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5906 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5910 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5911 ASSERT_TRUE(stream
!= NULL
);
5912 ASSERT_TRUE(stream
->stream() != NULL
);
5913 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
) +
5914 kDeltaWindowSize
* kDeltaCount
-
5915 kMaxSpdyFrameChunkSize
* kFrameCount
,
5916 stream
->stream()->send_window_size());
5920 rv
= callback
.WaitForResult();
5923 helper
.VerifyDataConsumed();
5926 // Test that received data frames and sent WINDOW_UPDATE frames change
5927 // the recv_window_size_ correctly.
5928 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
5929 if (GetParam().protocol
< kProtoSPDY3
)
5932 // Amount of body required to trigger a sent window update.
5933 const size_t kTargetSize
= kSpdyStreamInitialWindowSize
/ 2 + 1;
5935 scoped_ptr
<SpdyFrame
> req(
5936 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5937 scoped_ptr
<SpdyFrame
> session_window_update(
5938 spdy_util_
.ConstructSpdyWindowUpdate(0, kTargetSize
));
5939 scoped_ptr
<SpdyFrame
> window_update(
5940 spdy_util_
.ConstructSpdyWindowUpdate(1, kTargetSize
));
5942 std::vector
<MockWrite
> writes
;
5943 writes
.push_back(CreateMockWrite(*req
));
5944 if (GetParam().protocol
>= kProtoSPDY31
)
5945 writes
.push_back(CreateMockWrite(*session_window_update
));
5946 writes
.push_back(CreateMockWrite(*window_update
));
5948 std::vector
<MockRead
> reads
;
5949 scoped_ptr
<SpdyFrame
> resp(
5950 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5951 reads
.push_back(CreateMockRead(*resp
));
5953 ScopedVector
<SpdyFrame
> body_frames
;
5954 const std::string
body_data(4096, 'x');
5955 for (size_t remaining
= kTargetSize
; remaining
!= 0;) {
5956 size_t frame_size
= std::min(remaining
, body_data
.size());
5957 body_frames
.push_back(spdy_util_
.ConstructSpdyBodyFrame(
5958 1, body_data
.data(), frame_size
, false));
5959 reads
.push_back(CreateMockRead(*body_frames
.back()));
5960 remaining
-= frame_size
;
5962 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 0)); // Yield.
5964 DelayedSocketData
data(1, vector_as_array(&reads
), reads
.size(),
5965 vector_as_array(&writes
), writes
.size());
5967 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5968 BoundNetLog(), GetParam(), NULL
);
5969 helper
.AddData(&data
);
5970 helper
.RunPreTestSetup();
5971 HttpNetworkTransaction
* trans
= helper
.trans();
5973 TestCompletionCallback callback
;
5974 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5977 rv
= callback
.WaitForResult();
5980 SpdyHttpStream
* stream
=
5981 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5982 ASSERT_TRUE(stream
!= NULL
);
5983 ASSERT_TRUE(stream
->stream() != NULL
);
5985 // All data has been read, but not consumed. The window reflects this.
5986 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
- kTargetSize
),
5987 stream
->stream()->recv_window_size());
5989 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5990 ASSERT_TRUE(response
!= NULL
);
5991 ASSERT_TRUE(response
->headers
.get() != NULL
);
5992 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5993 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5995 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5996 // size increased to default.
5997 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kTargetSize
));
5998 EXPECT_EQ(static_cast<int>(kTargetSize
),
5999 trans
->Read(buf
.get(), kTargetSize
, CompletionCallback()));
6000 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
),
6001 stream
->stream()->recv_window_size());
6002 EXPECT_THAT(base::StringPiece(buf
->data(), kTargetSize
), Each(Eq('x')));
6004 // Allow scheduled WINDOW_UPDATE frames to write.
6005 base::RunLoop().RunUntilIdle();
6006 helper
.VerifyDataConsumed();
6009 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6010 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
6011 if (GetParam().protocol
< kProtoSPDY3
)
6014 // Number of full frames we hope to write (but will not, used to
6015 // set content-length header correctly)
6016 static int kFrameCount
= 3;
6018 scoped_ptr
<std::string
> content(
6019 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
6020 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6021 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
6022 scoped_ptr
<SpdyFrame
> body(
6023 spdy_util_
.ConstructSpdyBodyFrame(
6024 1, content
->c_str(), content
->size(), false));
6025 scoped_ptr
<SpdyFrame
> rst(
6026 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
6028 // We're not going to write a data frame with FIN, we'll receive a bad
6029 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6030 MockWrite writes
[] = {
6031 CreateMockWrite(*req
, 0),
6032 CreateMockWrite(*body
, 2),
6033 CreateMockWrite(*rst
, 3),
6036 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
6037 scoped_ptr
<SpdyFrame
> window_update(
6038 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
6039 MockRead reads
[] = {
6040 CreateMockRead(*window_update
, 1),
6041 MockRead(ASYNC
, 0, 4) // EOF
6044 DeterministicSocketData
data(reads
, arraysize(reads
),
6045 writes
, arraysize(writes
));
6047 ScopedVector
<UploadElementReader
> element_readers
;
6048 for (int i
= 0; i
< kFrameCount
; ++i
) {
6049 element_readers
.push_back(
6050 new UploadBytesElementReader(content
->c_str(), content
->size()));
6052 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6054 // Setup the request
6055 HttpRequestInfo request
;
6056 request
.method
= "POST";
6057 request
.url
= GURL("http://www.google.com/");
6058 request
.upload_data_stream
= &upload_data_stream
;
6060 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6061 BoundNetLog(), GetParam(), NULL
);
6062 helper
.SetDeterministic();
6063 helper
.RunPreTestSetup();
6064 helper
.AddDeterministicData(&data
);
6065 HttpNetworkTransaction
* trans
= helper
.trans();
6067 TestCompletionCallback callback
;
6068 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6069 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6072 ASSERT_TRUE(callback
.have_result());
6073 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6074 helper
.VerifyDataConsumed();
6077 // Test that after hitting a send window size of 0, the write process
6078 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6080 // This test constructs a POST request followed by enough data frames
6081 // containing 'a' that would make the window size 0, followed by another
6082 // data frame containing default content (which is "hello!") and this frame
6083 // also contains a FIN flag. DelayedSocketData is used to enforce all
6084 // writes go through before a read could happen. However, the last frame
6085 // ("hello!") is not supposed to go through since by the time its turn
6086 // arrives, window size is 0. At this point MessageLoop::Run() called via
6087 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6088 // which returns after performing all possible writes. We use DCHECKS to
6089 // ensure that last data frame is still there and stream has stalled.
6090 // After that, next read is artifically enforced, which causes a
6091 // WINDOW_UPDATE to be read and I/O process resumes.
6092 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6093 if (GetParam().protocol
< kProtoSPDY3
)
6096 // Number of frames we need to send to zero out the window size: data
6097 // frames plus SYN_STREAM plus the last data frame; also we need another
6098 // data frame that we will send once the WINDOW_UPDATE is received,
6100 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6102 // Calculate last frame's size; 0 size data frame is legal.
6103 size_t last_frame_size
=
6104 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6106 // Construct content for a data frame of maximum size.
6107 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6109 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6110 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6114 scoped_ptr
<SpdyFrame
> body1(
6115 spdy_util_
.ConstructSpdyBodyFrame(
6116 1, content
.c_str(), content
.size(), false));
6118 // Last frame to zero out the window size.
6119 scoped_ptr
<SpdyFrame
> body2(
6120 spdy_util_
.ConstructSpdyBodyFrame(
6121 1, content
.c_str(), last_frame_size
, false));
6123 // Data frame to be sent once WINDOW_UPDATE frame is received.
6124 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6126 // Fill in mock writes.
6127 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6129 writes
[i
] = CreateMockWrite(*req
);
6130 for (i
= 1; i
< num_writes
- 2; i
++)
6131 writes
[i
] = CreateMockWrite(*body1
);
6132 writes
[i
++] = CreateMockWrite(*body2
);
6133 writes
[i
] = CreateMockWrite(*body3
);
6135 // Construct read frame, give enough space to upload the rest of the
6137 scoped_ptr
<SpdyFrame
> session_window_update(
6138 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6139 scoped_ptr
<SpdyFrame
> window_update(
6140 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6141 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6142 MockRead reads
[] = {
6143 CreateMockRead(*session_window_update
),
6144 CreateMockRead(*session_window_update
),
6145 CreateMockRead(*window_update
),
6146 CreateMockRead(*window_update
),
6147 CreateMockRead(*reply
),
6148 CreateMockRead(*body2
),
6149 CreateMockRead(*body3
),
6150 MockRead(ASYNC
, 0, 0) // EOF
6153 // Skip the session window updates unless we're using SPDY/3.1 and
6155 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6156 size_t num_reads
= arraysize(reads
) - read_offset
;
6158 // Force all writes to happen before any read, last write will not
6159 // actually queue a frame, due to window size being 0.
6160 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6161 writes
.get(), num_writes
);
6163 ScopedVector
<UploadElementReader
> element_readers
;
6164 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6165 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6166 element_readers
.push_back(new UploadBytesElementReader(
6167 upload_data_string
.c_str(), upload_data_string
.size()));
6168 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6170 HttpRequestInfo request
;
6171 request
.method
= "POST";
6172 request
.url
= GURL("http://www.google.com/");
6173 request
.upload_data_stream
= &upload_data_stream
;
6174 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6175 BoundNetLog(), GetParam(), NULL
);
6176 helper
.AddData(&data
);
6177 helper
.RunPreTestSetup();
6179 HttpNetworkTransaction
* trans
= helper
.trans();
6181 TestCompletionCallback callback
;
6182 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6185 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6187 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6188 ASSERT_TRUE(stream
!= NULL
);
6189 ASSERT_TRUE(stream
->stream() != NULL
);
6190 EXPECT_EQ(0, stream
->stream()->send_window_size());
6191 // All the body data should have been read.
6192 // TODO(satorux): This is because of the weirdness in reading the request
6193 // body in OnSendBodyComplete(). See crbug.com/113107.
6194 EXPECT_TRUE(upload_data_stream
.IsEOF());
6195 // But the body is not yet fully sent (kUploadData is not yet sent)
6196 // since we're send-stalled.
6197 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6199 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6200 rv
= callback
.WaitForResult();
6201 helper
.VerifyDataConsumed();
6204 // Test we correctly handle the case where the SETTINGS frame results in
6205 // unstalling the send window.
6206 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6207 if (GetParam().protocol
< kProtoSPDY3
)
6210 // Number of frames we need to send to zero out the window size: data
6211 // frames plus SYN_STREAM plus the last data frame; also we need another
6212 // data frame that we will send once the SETTING is received, therefore +3.
6213 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6215 // Calculate last frame's size; 0 size data frame is legal.
6216 size_t last_frame_size
=
6217 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6219 // Construct content for a data frame of maximum size.
6220 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6222 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6223 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6227 scoped_ptr
<SpdyFrame
> body1(
6228 spdy_util_
.ConstructSpdyBodyFrame(
6229 1, content
.c_str(), content
.size(), false));
6231 // Last frame to zero out the window size.
6232 scoped_ptr
<SpdyFrame
> body2(
6233 spdy_util_
.ConstructSpdyBodyFrame(
6234 1, content
.c_str(), last_frame_size
, false));
6236 // Data frame to be sent once SETTINGS frame is received.
6237 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6239 // Fill in mock reads/writes.
6240 std::vector
<MockRead
> reads
;
6241 std::vector
<MockWrite
> writes
;
6243 writes
.push_back(CreateMockWrite(*req
, i
++));
6244 while (i
< num_writes
- 2)
6245 writes
.push_back(CreateMockWrite(*body1
, i
++));
6246 writes
.push_back(CreateMockWrite(*body2
, i
++));
6248 // Construct read frame for SETTINGS that gives enough space to upload the
6249 // rest of the data.
6250 SettingsMap settings
;
6251 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6252 SettingsFlagsAndValue(
6253 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
* 2);
6254 scoped_ptr
<SpdyFrame
> settings_frame_large(
6255 spdy_util_
.ConstructSpdySettings(settings
));
6257 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6259 scoped_ptr
<SpdyFrame
> session_window_update(
6260 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6261 if (GetParam().protocol
>= kProtoSPDY31
)
6262 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6264 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6265 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6267 writes
.push_back(CreateMockWrite(*body3
, i
++));
6269 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6270 reads
.push_back(CreateMockRead(*reply
, i
++));
6271 reads
.push_back(CreateMockRead(*body2
, i
++));
6272 reads
.push_back(CreateMockRead(*body3
, i
++));
6273 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6275 // Force all writes to happen before any read, last write will not
6276 // actually queue a frame, due to window size being 0.
6277 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6278 vector_as_array(&writes
), writes
.size());
6280 ScopedVector
<UploadElementReader
> element_readers
;
6281 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6282 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6283 element_readers
.push_back(new UploadBytesElementReader(
6284 upload_data_string
.c_str(), upload_data_string
.size()));
6285 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6287 HttpRequestInfo request
;
6288 request
.method
= "POST";
6289 request
.url
= GURL("http://www.google.com/");
6290 request
.upload_data_stream
= &upload_data_stream
;
6291 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6292 BoundNetLog(), GetParam(), NULL
);
6293 helper
.SetDeterministic();
6294 helper
.RunPreTestSetup();
6295 helper
.AddDeterministicData(&data
);
6297 HttpNetworkTransaction
* trans
= helper
.trans();
6299 TestCompletionCallback callback
;
6300 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6301 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6303 data
.RunFor(num_writes
- 1); // Write as much as we can.
6305 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6306 ASSERT_TRUE(stream
!= NULL
);
6307 ASSERT_TRUE(stream
->stream() != NULL
);
6308 EXPECT_EQ(0, stream
->stream()->send_window_size());
6310 // All the body data should have been read.
6311 // TODO(satorux): This is because of the weirdness in reading the request
6312 // body in OnSendBodyComplete(). See crbug.com/113107.
6313 EXPECT_TRUE(upload_data_stream
.IsEOF());
6314 // But the body is not yet fully sent (kUploadData is not yet sent)
6315 // since we're send-stalled.
6316 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6318 data
.RunFor(7); // Read in SETTINGS frame to unstall.
6319 rv
= callback
.WaitForResult();
6320 helper
.VerifyDataConsumed();
6321 // If stream is NULL, that means it was unstalled and closed.
6322 EXPECT_TRUE(stream
->stream() == NULL
);
6325 // Test we correctly handle the case where the SETTINGS frame results in a
6326 // negative send window size.
6327 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6328 if (GetParam().protocol
< kProtoSPDY3
)
6331 // Number of frames we need to send to zero out the window size: data
6332 // frames plus SYN_STREAM plus the last data frame; also we need another
6333 // data frame that we will send once the SETTING is received, therefore +3.
6334 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6336 // Calculate last frame's size; 0 size data frame is legal.
6337 size_t last_frame_size
=
6338 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6340 // Construct content for a data frame of maximum size.
6341 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6343 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6344 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6348 scoped_ptr
<SpdyFrame
> body1(
6349 spdy_util_
.ConstructSpdyBodyFrame(
6350 1, content
.c_str(), content
.size(), false));
6352 // Last frame to zero out the window size.
6353 scoped_ptr
<SpdyFrame
> body2(
6354 spdy_util_
.ConstructSpdyBodyFrame(
6355 1, content
.c_str(), last_frame_size
, false));
6357 // Data frame to be sent once SETTINGS frame is received.
6358 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6360 // Fill in mock reads/writes.
6361 std::vector
<MockRead
> reads
;
6362 std::vector
<MockWrite
> writes
;
6364 writes
.push_back(CreateMockWrite(*req
, i
++));
6365 while (i
< num_writes
- 2)
6366 writes
.push_back(CreateMockWrite(*body1
, i
++));
6367 writes
.push_back(CreateMockWrite(*body2
, i
++));
6369 // Construct read frame for SETTINGS that makes the send_window_size
6371 SettingsMap new_settings
;
6372 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6373 SettingsFlagsAndValue(
6374 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
/ 2);
6375 scoped_ptr
<SpdyFrame
> settings_frame_small(
6376 spdy_util_
.ConstructSpdySettings(new_settings
));
6377 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6379 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6380 spdy_util_
.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize
));
6381 scoped_ptr
<SpdyFrame
> window_update_init_size(
6382 spdy_util_
.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize
));
6384 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6386 if (GetParam().protocol
>= kProtoSPDY3
)
6387 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6389 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6391 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
6392 writes
.push_back(CreateMockWrite(*settings_ack
, i
++));
6394 writes
.push_back(CreateMockWrite(*body3
, i
++));
6396 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6397 reads
.push_back(CreateMockRead(*reply
, i
++));
6398 reads
.push_back(CreateMockRead(*body2
, i
++));
6399 reads
.push_back(CreateMockRead(*body3
, i
++));
6400 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6402 // Force all writes to happen before any read, last write will not
6403 // actually queue a frame, due to window size being 0.
6404 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6405 vector_as_array(&writes
), writes
.size());
6407 ScopedVector
<UploadElementReader
> element_readers
;
6408 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6409 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6410 element_readers
.push_back(new UploadBytesElementReader(
6411 upload_data_string
.c_str(), upload_data_string
.size()));
6412 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
6414 HttpRequestInfo request
;
6415 request
.method
= "POST";
6416 request
.url
= GURL("http://www.google.com/");
6417 request
.upload_data_stream
= &upload_data_stream
;
6418 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6419 BoundNetLog(), GetParam(), NULL
);
6420 helper
.SetDeterministic();
6421 helper
.RunPreTestSetup();
6422 helper
.AddDeterministicData(&data
);
6424 HttpNetworkTransaction
* trans
= helper
.trans();
6426 TestCompletionCallback callback
;
6427 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6428 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6430 data
.RunFor(num_writes
- 1); // Write as much as we can.
6432 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6433 ASSERT_TRUE(stream
!= NULL
);
6434 ASSERT_TRUE(stream
->stream() != NULL
);
6435 EXPECT_EQ(0, stream
->stream()->send_window_size());
6437 // All the body data should have been read.
6438 // TODO(satorux): This is because of the weirdness in reading the request
6439 // body in OnSendBodyComplete(). See crbug.com/113107.
6440 EXPECT_TRUE(upload_data_stream
.IsEOF());
6441 // But the body is not yet fully sent (kUploadData is not yet sent)
6442 // since we're send-stalled.
6443 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6445 // Read in WINDOW_UPDATE or SETTINGS frame.
6446 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 9 : 8);
6447 rv
= callback
.WaitForResult();
6448 helper
.VerifyDataConsumed();
6451 class SpdyNetworkTransactionNoTLSUsageCheckTest
6452 : public SpdyNetworkTransactionTest
{
6454 void RunNoTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6455 // Construct the request.
6456 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyGet(
6457 "https://www.google.com/", false, 1, LOWEST
));
6458 MockWrite writes
[] = {CreateMockWrite(*req
)};
6460 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6461 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6462 MockRead reads
[] = {
6463 CreateMockRead(*resp
), CreateMockRead(*body
),
6464 MockRead(ASYNC
, 0, 0) // EOF
6467 DelayedSocketData
data(
6468 1, reads
, arraysize(reads
), writes
, arraysize(writes
));
6469 HttpRequestInfo request
;
6470 request
.method
= "GET";
6471 request
.url
= GURL("https://www.google.com/");
6472 NormalSpdyTransactionHelper
helper(
6473 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6474 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6475 TransactionHelperResult out
= helper
.output();
6476 EXPECT_EQ(OK
, out
.rv
);
6477 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6478 EXPECT_EQ("hello!", out
.response_data
);
6482 //-----------------------------------------------------------------------------
6483 // All tests are run with three different connection types: SPDY after NPN
6484 // negotiation, SPDY without SSL, and SPDY with SSL.
6486 // TODO(akalin): Use ::testing::Combine() when we are able to use
6488 INSTANTIATE_TEST_CASE_P(
6490 SpdyNetworkTransactionNoTLSUsageCheckTest
,
6491 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2
,
6493 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNPN
),
6494 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
)));
6496 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSVersionTooOld
) {
6497 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6498 new SSLSocketDataProvider(ASYNC
, OK
));
6499 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6500 &ssl_provider
->connection_status
);
6502 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6505 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6506 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6507 new SSLSocketDataProvider(ASYNC
, OK
));
6508 // Set to TLS_RSA_WITH_NULL_MD5
6509 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6511 RunNoTLSUsageCheckTest(ssl_provider
.Pass());
6514 class SpdyNetworkTransactionTLSUsageCheckTest
6515 : public SpdyNetworkTransactionTest
{
6517 void RunTLSUsageCheckTest(scoped_ptr
<SSLSocketDataProvider
> ssl_provider
) {
6518 scoped_ptr
<SpdyFrame
> goaway(
6519 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY
, ""));
6520 MockWrite writes
[] = {CreateMockWrite(*goaway
)};
6522 DelayedSocketData
data(1, NULL
, 0, writes
, arraysize(writes
));
6523 HttpRequestInfo request
;
6524 request
.method
= "GET";
6525 request
.url
= GURL("https://www.google.com/");
6526 NormalSpdyTransactionHelper
helper(
6527 request
, DEFAULT_PRIORITY
, BoundNetLog(), GetParam(), NULL
);
6528 helper
.RunToCompletionWithSSLData(&data
, ssl_provider
.Pass());
6529 TransactionHelperResult out
= helper
.output();
6530 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
, out
.rv
);
6534 INSTANTIATE_TEST_CASE_P(
6536 SpdyNetworkTransactionTLSUsageCheckTest
,
6537 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4
, SPDYNPN
)));
6539 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSVersionTooOld
) {
6540 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6541 new SSLSocketDataProvider(ASYNC
, OK
));
6542 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3
,
6543 &ssl_provider
->connection_status
);
6545 RunTLSUsageCheckTest(ssl_provider
.Pass());
6548 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest
, TLSCipherSuiteSucky
) {
6549 scoped_ptr
<SSLSocketDataProvider
> ssl_provider(
6550 new SSLSocketDataProvider(ASYNC
, OK
));
6551 // Set to TLS_RSA_WITH_NULL_MD5
6552 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider
->connection_status
);
6554 RunTLSUsageCheckTest(ssl_provider
.Pass());