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 "net/base/auth.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/request_priority.h"
18 #include "net/base/upload_bytes_element_reader.h"
19 #include "net/base/upload_data_stream.h"
20 #include "net/base/upload_file_element_reader.h"
21 #include "net/http/http_network_session_peer.h"
22 #include "net/http/http_network_transaction.h"
23 #include "net/http/http_server_properties.h"
24 #include "net/http/http_transaction_unittest.h"
25 #include "net/socket/client_socket_pool_base.h"
26 #include "net/socket/next_proto.h"
27 #include "net/spdy/buffered_spdy_framer.h"
28 #include "net/spdy/spdy_http_stream.h"
29 #include "net/spdy/spdy_http_utils.h"
30 #include "net/spdy/spdy_session.h"
31 #include "net/spdy/spdy_session_pool.h"
32 #include "net/spdy/spdy_test_util_common.h"
33 #include "net/spdy/spdy_test_utils.h"
34 #include "net/url_request/url_request_test_util.h"
35 #include "testing/platform_test.h"
37 //-----------------------------------------------------------------------------
42 const char kRequestUrl
[] = "http://www.google.com/";
44 enum SpdyNetworkTransactionTestSSLType
{
50 struct SpdyNetworkTransactionTestParams
{
51 SpdyNetworkTransactionTestParams()
52 : protocol(kProtoSPDY2
),
55 SpdyNetworkTransactionTestParams(
57 SpdyNetworkTransactionTestSSLType ssl_type
)
62 SpdyNetworkTransactionTestSSLType ssl_type
;
65 SpdySessionDependencies
* CreateSpdySessionDependencies(
66 SpdyNetworkTransactionTestParams test_params
) {
67 return new SpdySessionDependencies(test_params
.protocol
);
70 SpdySessionDependencies
* CreateSpdySessionDependencies(
71 SpdyNetworkTransactionTestParams test_params
,
72 ProxyService
* proxy_service
) {
73 return new SpdySessionDependencies(test_params
.protocol
, proxy_service
);
78 class SpdyNetworkTransactionTest
79 : public ::testing::TestWithParam
<SpdyNetworkTransactionTestParams
> {
81 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol
) {
84 virtual ~SpdyNetworkTransactionTest() {
85 // UploadDataStream posts deletion tasks back to the message loop on
87 upload_data_stream_
.reset();
88 base::RunLoop().RunUntilIdle();
91 virtual void SetUp() {
92 google_get_request_initialized_
= false;
93 google_post_request_initialized_
= false;
94 google_chunked_post_request_initialized_
= false;
95 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
98 struct TransactionHelperResult
{
100 std::string status_line
;
101 std::string response_data
;
102 HttpResponseInfo response_info
;
105 // A helper class that handles all the initial npn/ssl setup.
106 class NormalSpdyTransactionHelper
{
108 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
109 RequestPriority priority
,
110 const BoundNetLog
& log
,
111 SpdyNetworkTransactionTestParams test_params
,
112 SpdySessionDependencies
* session_deps
)
115 session_deps_(session_deps
== NULL
?
116 CreateSpdySessionDependencies(test_params
) :
118 session_(SpdySessionDependencies::SpdyCreateSession(
119 session_deps_
.get())),
121 test_params_(test_params
),
122 deterministic_(false),
123 spdy_enabled_(true) {
124 switch (test_params_
.ssl_type
) {
137 ~NormalSpdyTransactionHelper() {
138 // Any test which doesn't close the socket by sending it an EOF will
139 // have a valid session left open, which leaks the entire session pool.
140 // This is just fine - in fact, some of our tests intentionally do this
141 // so that we can check consistency of the SpdySessionPool as the test
142 // finishes. If we had put an EOF on the socket, the SpdySession would
143 // have closed and we wouldn't be able to check the consistency.
145 // Forcefully close existing sessions here.
146 session()->spdy_session_pool()->CloseAllSessions();
149 void SetDeterministic() {
150 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
151 session_deps_
.get());
152 deterministic_
= true;
155 void SetSpdyDisabled() {
156 spdy_enabled_
= false;
160 void RunPreTestSetup() {
161 if (!session_deps_
.get())
162 session_deps_
.reset(CreateSpdySessionDependencies(test_params_
));
164 session_
= SpdySessionDependencies::SpdyCreateSession(
165 session_deps_
.get());
166 HttpStreamFactory::set_use_alternate_protocols(false);
167 HttpStreamFactory::set_force_spdy_over_ssl(false);
168 HttpStreamFactory::set_force_spdy_always(false);
170 std::vector
<NextProto
> next_protos
= SpdyNextProtos();
172 switch (test_params_
.ssl_type
) {
174 session_
->http_server_properties()->SetAlternateProtocol(
175 HostPortPair("www.google.com", 80), 443,
176 AlternateProtocolFromNextProto(test_params_
.protocol
));
177 HttpStreamFactory::set_use_alternate_protocols(true);
178 HttpStreamFactory::SetNextProtos(next_protos
);
181 HttpStreamFactory::set_force_spdy_over_ssl(false);
182 HttpStreamFactory::set_force_spdy_always(true);
185 HttpStreamFactory::set_force_spdy_over_ssl(true);
186 HttpStreamFactory::set_force_spdy_always(true);
192 // We're now ready to use SSL-npn SPDY.
193 trans_
.reset(new HttpNetworkTransaction(priority_
, session_
.get()));
196 // Start the transaction, read some data, finish.
197 void RunDefaultTest() {
198 if (!StartDefaultTest())
203 bool StartDefaultTest() {
204 output_
.rv
= trans_
->Start(&request_
, callback
.callback(), log_
);
206 // We expect an IO Pending or some sort of error.
207 EXPECT_LT(output_
.rv
, 0);
208 return output_
.rv
== ERR_IO_PENDING
;
211 void FinishDefaultTest() {
212 output_
.rv
= callback
.WaitForResult();
213 if (output_
.rv
!= OK
) {
214 session_
->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED
);
219 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
220 ASSERT_TRUE(response
!= NULL
);
221 ASSERT_TRUE(response
->headers
.get() != NULL
);
222 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
223 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
224 if (HttpStreamFactory::spdy_enabled()) {
226 HttpResponseInfo::ConnectionInfoFromNextProto(
227 test_params_
.protocol
),
228 response
->connection_info
);
230 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1
,
231 response
->connection_info
);
233 if (test_params_
.ssl_type
== SPDYNPN
&& spdy_enabled_
) {
234 EXPECT_TRUE(response
->was_npn_negotiated
);
236 EXPECT_TRUE(!response
->was_npn_negotiated
);
238 // If SPDY is not enabled, a HTTP request should not be diverted
239 // over a SSL session.
240 if (!spdy_enabled_
) {
241 EXPECT_EQ(request_
.url
.SchemeIs("https"),
242 response
->was_npn_negotiated
);
244 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
245 EXPECT_EQ(port_
, response
->socket_address
.port());
246 output_
.status_line
= response
->headers
->GetStatusLine();
247 output_
.response_info
= *response
; // Make a copy so we can verify.
248 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
251 // Most tests will want to call this function. In particular, the MockReads
252 // should end with an empty read, and that read needs to be processed to
253 // ensure proper deletion of the spdy_session_pool.
254 void VerifyDataConsumed() {
255 for (DataVector::iterator it
= data_vector_
.begin();
256 it
!= data_vector_
.end(); ++it
) {
257 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
258 << (*it
)->read_count()
260 << (*it
)->read_index();
261 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
262 << (*it
)->write_count()
264 << (*it
)->write_index();
268 // Occasionally a test will expect to error out before certain reads are
269 // processed. In that case we want to explicitly ensure that the reads were
271 void VerifyDataNotConsumed() {
272 for (DataVector::iterator it
= data_vector_
.begin();
273 it
!= data_vector_
.end(); ++it
) {
274 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
275 << (*it
)->read_count()
277 << (*it
)->read_index();
278 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
279 << (*it
)->write_count()
281 << (*it
)->write_index();
285 void RunToCompletion(StaticSocketDataProvider
* data
) {
289 VerifyDataConsumed();
292 void AddData(StaticSocketDataProvider
* data
) {
293 DCHECK(!deterministic_
);
294 data_vector_
.push_back(data
);
295 SSLSocketDataProvider
* ssl_provider
=
296 new SSLSocketDataProvider(ASYNC
, OK
);
297 if (test_params_
.ssl_type
== SPDYNPN
)
298 ssl_provider
->SetNextProto(test_params_
.protocol
);
300 ssl_vector_
.push_back(ssl_provider
);
301 if (test_params_
.ssl_type
== SPDYNPN
|| test_params_
.ssl_type
== SPDYSSL
)
302 session_deps_
->socket_factory
->AddSSLSocketDataProvider(ssl_provider
);
304 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
305 if (test_params_
.ssl_type
== SPDYNPN
) {
306 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
307 StaticSocketDataProvider
* hanging_non_alternate_protocol_socket
=
308 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
309 hanging_non_alternate_protocol_socket
->set_connect_data(
310 never_finishing_connect
);
311 session_deps_
->socket_factory
->AddSocketDataProvider(
312 hanging_non_alternate_protocol_socket
);
313 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
317 void AddDeterministicData(DeterministicSocketData
* data
) {
318 DCHECK(deterministic_
);
319 data_vector_
.push_back(data
);
320 SSLSocketDataProvider
* ssl_provider
=
321 new SSLSocketDataProvider(ASYNC
, OK
);
322 if (test_params_
.ssl_type
== SPDYNPN
)
323 ssl_provider
->SetNextProto(test_params_
.protocol
);
325 ssl_vector_
.push_back(ssl_provider
);
326 if (test_params_
.ssl_type
== SPDYNPN
||
327 test_params_
.ssl_type
== SPDYSSL
) {
328 session_deps_
->deterministic_socket_factory
->
329 AddSSLSocketDataProvider(ssl_provider
);
331 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
332 if (test_params_
.ssl_type
== SPDYNPN
) {
333 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
334 DeterministicSocketData
* hanging_non_alternate_protocol_socket
=
335 new DeterministicSocketData(NULL
, 0, NULL
, 0);
336 hanging_non_alternate_protocol_socket
->set_connect_data(
337 never_finishing_connect
);
338 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
339 hanging_non_alternate_protocol_socket
);
340 alternate_deterministic_vector_
.push_back(
341 hanging_non_alternate_protocol_socket
);
345 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
348 HttpNetworkTransaction
* trans() { return trans_
.get(); }
349 void ResetTrans() { trans_
.reset(); }
350 TransactionHelperResult
& output() { return output_
; }
351 const HttpRequestInfo
& request() const { return request_
; }
352 const scoped_refptr
<HttpNetworkSession
>& session() const {
355 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
356 return session_deps_
;
358 int port() const { return port_
; }
359 SpdyNetworkTransactionTestParams
test_params() const {
364 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
365 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
366 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
367 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
368 HttpRequestInfo request_
;
369 RequestPriority priority_
;
370 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
371 scoped_refptr
<HttpNetworkSession
> session_
;
372 TransactionHelperResult output_
;
373 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
374 SSLVector ssl_vector_
;
375 TestCompletionCallback callback
;
376 scoped_ptr
<HttpNetworkTransaction
> trans_
;
377 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
378 DataVector data_vector_
;
379 AlternateVector alternate_vector_
;
380 AlternateDeterministicVector alternate_deterministic_vector_
;
381 const BoundNetLog
& log_
;
382 SpdyNetworkTransactionTestParams test_params_
;
388 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
389 int expected_status
);
391 void ConnectStatusHelper(const MockRead
& status
);
393 const HttpRequestInfo
& CreateGetPushRequest() {
394 google_get_push_request_
.method
= "GET";
395 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
396 google_get_push_request_
.load_flags
= 0;
397 return google_get_push_request_
;
400 const HttpRequestInfo
& CreateGetRequest() {
401 if (!google_get_request_initialized_
) {
402 google_get_request_
.method
= "GET";
403 google_get_request_
.url
= GURL(kDefaultURL
);
404 google_get_request_
.load_flags
= 0;
405 google_get_request_initialized_
= true;
407 return google_get_request_
;
410 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
411 if (!google_get_request_initialized_
) {
412 google_get_request_
.method
= "GET";
413 google_get_request_
.url
= GURL(kDefaultURL
);
414 google_get_request_
.load_flags
= 0;
415 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
416 google_get_request_initialized_
= true;
418 return google_get_request_
;
421 const HttpRequestInfo
& CreatePostRequest() {
422 if (!google_post_request_initialized_
) {
423 ScopedVector
<UploadElementReader
> element_readers
;
424 element_readers
.push_back(
425 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
426 upload_data_stream_
.reset(new UploadDataStream(&element_readers
, 0));
428 google_post_request_
.method
= "POST";
429 google_post_request_
.url
= GURL(kDefaultURL
);
430 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
431 google_post_request_initialized_
= true;
433 return google_post_request_
;
436 const HttpRequestInfo
& CreateFilePostRequest() {
437 if (!google_post_request_initialized_
) {
438 base::FilePath file_path
;
439 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
440 CHECK_EQ(static_cast<int>(kUploadDataSize
),
441 file_util::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
443 ScopedVector
<UploadElementReader
> element_readers
;
444 element_readers
.push_back(
445 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
450 upload_data_stream_
.reset(new UploadDataStream(&element_readers
, 0));
452 google_post_request_
.method
= "POST";
453 google_post_request_
.url
= GURL(kDefaultURL
);
454 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
455 google_post_request_initialized_
= true;
457 return google_post_request_
;
460 const HttpRequestInfo
& CreateComplexPostRequest() {
461 if (!google_post_request_initialized_
) {
462 const int kFileRangeOffset
= 1;
463 const int kFileRangeLength
= 3;
464 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
466 base::FilePath file_path
;
467 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
468 CHECK_EQ(static_cast<int>(kUploadDataSize
),
469 file_util::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
471 ScopedVector
<UploadElementReader
> element_readers
;
472 element_readers
.push_back(
473 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
474 element_readers
.push_back(
475 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
480 element_readers
.push_back(new UploadBytesElementReader(
481 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
482 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
483 upload_data_stream_
.reset(new UploadDataStream(&element_readers
, 0));
485 google_post_request_
.method
= "POST";
486 google_post_request_
.url
= GURL(kDefaultURL
);
487 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
488 google_post_request_initialized_
= true;
490 return google_post_request_
;
493 const HttpRequestInfo
& CreateChunkedPostRequest() {
494 if (!google_chunked_post_request_initialized_
) {
495 upload_data_stream_
.reset(
496 new UploadDataStream(UploadDataStream::CHUNKED
, 0));
497 google_chunked_post_request_
.method
= "POST";
498 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
499 google_chunked_post_request_
.upload_data_stream
=
500 upload_data_stream_
.get();
501 google_chunked_post_request_initialized_
= true;
503 return google_chunked_post_request_
;
506 // Read the result of a particular transaction, knowing that we've got
507 // multiple transactions in the read pipeline; so as we read, we may have
508 // to skip over data destined for other transactions while we consume
509 // the data for |trans|.
510 int ReadResult(HttpNetworkTransaction
* trans
,
511 StaticSocketDataProvider
* data
,
512 std::string
* result
) {
513 const int kSize
= 3000;
516 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
517 TestCompletionCallback callback
;
519 int rv
= trans
->Read(buf
.get(), kSize
, callback
.callback());
520 if (rv
== ERR_IO_PENDING
) {
521 // Multiple transactions may be in the data set. Keep pulling off
522 // reads until we complete our callback.
523 while (!callback
.have_result()) {
524 data
->CompleteRead();
525 base::RunLoop().RunUntilIdle();
527 rv
= callback
.WaitForResult();
528 } else if (rv
<= 0) {
531 result
->append(buf
->data(), rv
);
537 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
538 // This lengthy block is reaching into the pool to dig out the active
539 // session. Once we have the session, we verify that the streams are
540 // all closed and not leaked at this point.
541 const GURL
& url
= helper
.request().url
;
542 int port
= helper
.test_params().ssl_type
== SPDYNPN
? 443 : 80;
543 HostPortPair
host_port_pair(url
.host(), port
);
544 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
545 kPrivacyModeDisabled
);
547 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
548 base::WeakPtr
<SpdySession
> spdy_session
=
549 session
->spdy_session_pool()->FindAvailableSession(key
, log
);
550 ASSERT_TRUE(spdy_session
!= NULL
);
551 EXPECT_EQ(0u, spdy_session
->num_active_streams());
552 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
555 void RunServerPushTest(OrderedSocketData
* data
,
556 HttpResponseInfo
* response
,
557 HttpResponseInfo
* push_response
,
558 const std::string
& expected
) {
559 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
560 BoundNetLog(), GetParam(), NULL
);
561 helper
.RunPreTestSetup();
562 helper
.AddData(data
);
564 HttpNetworkTransaction
* trans
= helper
.trans();
566 // Start the transaction with basic parameters.
567 TestCompletionCallback callback
;
568 int rv
= trans
->Start(
569 &CreateGetRequest(), callback
.callback(), BoundNetLog());
570 EXPECT_EQ(ERR_IO_PENDING
, rv
);
571 rv
= callback
.WaitForResult();
573 // Request the pushed path.
574 scoped_ptr
<HttpNetworkTransaction
> trans2(
575 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
577 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
578 EXPECT_EQ(ERR_IO_PENDING
, rv
);
579 base::RunLoop().RunUntilIdle();
581 // The data for the pushed path may be coming in more than 1 frame. Compile
582 // the results into a single string.
584 // Read the server push body.
586 ReadResult(trans2
.get(), data
, &result2
);
587 // Read the response body.
589 ReadResult(trans
, data
, &result
);
591 // Verify that we consumed all test data.
592 EXPECT_TRUE(data
->at_read_eof());
593 EXPECT_TRUE(data
->at_write_eof());
595 // Verify that the received push data is same as the expected push data.
596 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
598 << "||||| Expected data: "
601 // Verify the SYN_REPLY.
602 // Copy the response info, because trans goes away.
603 *response
= *trans
->GetResponseInfo();
604 *push_response
= *trans2
->GetResponseInfo();
606 VerifyStreamsClosed(helper
);
609 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
611 helper
->ResetTrans();
614 static void StartTransactionCallback(
615 const scoped_refptr
<HttpNetworkSession
>& session
,
617 scoped_ptr
<HttpNetworkTransaction
> trans(
618 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
619 TestCompletionCallback callback
;
620 HttpRequestInfo request
;
621 request
.method
= "GET";
622 request
.url
= GURL("http://www.google.com/");
623 request
.load_flags
= 0;
624 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
625 EXPECT_EQ(ERR_IO_PENDING
, rv
);
626 callback
.WaitForResult();
629 SpdyTestUtil spdy_util_
;
632 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
633 bool google_get_request_initialized_
;
634 bool google_post_request_initialized_
;
635 bool google_chunked_post_request_initialized_
;
636 HttpRequestInfo google_get_request_
;
637 HttpRequestInfo google_post_request_
;
638 HttpRequestInfo google_chunked_post_request_
;
639 HttpRequestInfo google_get_push_request_
;
640 base::ScopedTempDir temp_dir_
;
643 //-----------------------------------------------------------------------------
644 // All tests are run with three different connection types: SPDY after NPN
645 // negotiation, SPDY without SSL, and SPDY with SSL.
647 // TODO(akalin): Use ::testing::Combine() when we are able to use
649 INSTANTIATE_TEST_CASE_P(
651 SpdyNetworkTransactionTest
,
653 SpdyNetworkTransactionTestParams(kProtoSPDY2
, SPDYNOSSL
),
654 SpdyNetworkTransactionTestParams(kProtoSPDY2
, SPDYSSL
),
655 SpdyNetworkTransactionTestParams(kProtoSPDY2
, SPDYNPN
),
656 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNOSSL
),
657 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYSSL
),
658 SpdyNetworkTransactionTestParams(kProtoSPDY3
, SPDYNPN
),
659 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNOSSL
),
660 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYSSL
),
661 SpdyNetworkTransactionTestParams(kProtoSPDY31
, SPDYNPN
),
662 SpdyNetworkTransactionTestParams(kProtoSPDY4a2
, SPDYNOSSL
),
663 SpdyNetworkTransactionTestParams(kProtoSPDY4a2
, SPDYSSL
),
664 SpdyNetworkTransactionTestParams(kProtoSPDY4a2
, SPDYNPN
),
665 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04
, SPDYNOSSL
),
666 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04
, SPDYSSL
),
667 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04
, SPDYNPN
)));
669 // Verify HttpNetworkTransaction constructor.
670 TEST_P(SpdyNetworkTransactionTest
, Constructor
) {
671 scoped_ptr
<SpdySessionDependencies
> session_deps(
672 CreateSpdySessionDependencies(GetParam()));
673 scoped_refptr
<HttpNetworkSession
> session(
674 SpdySessionDependencies::SpdyCreateSession(session_deps
.get()));
675 scoped_ptr
<HttpTransaction
> trans(
676 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
679 TEST_P(SpdyNetworkTransactionTest
, Get
) {
680 // Construct the request.
681 scoped_ptr
<SpdyFrame
> req(
682 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
683 MockWrite writes
[] = { CreateMockWrite(*req
) };
685 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
686 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
688 CreateMockRead(*resp
),
689 CreateMockRead(*body
),
690 MockRead(ASYNC
, 0, 0) // EOF
693 DelayedSocketData
data(1, reads
, arraysize(reads
),
694 writes
, arraysize(writes
));
695 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
696 BoundNetLog(), GetParam(), NULL
);
697 helper
.RunToCompletion(&data
);
698 TransactionHelperResult out
= helper
.output();
699 EXPECT_EQ(OK
, out
.rv
);
700 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
701 EXPECT_EQ("hello!", out
.response_data
);
704 TEST_P(SpdyNetworkTransactionTest
, GetAtEachPriority
) {
705 for (RequestPriority p
= MINIMUM_PRIORITY
; p
< NUM_PRIORITIES
;
706 p
= RequestPriority(p
+ 1)) {
707 // Construct the request.
708 scoped_ptr
<SpdyFrame
> req(
709 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, p
, true));
710 MockWrite writes
[] = { CreateMockWrite(*req
) };
712 SpdyPriority spdy_prio
= 0;
713 EXPECT_TRUE(GetSpdyPriority(spdy_util_
.spdy_version(), *req
, &spdy_prio
));
714 // this repeats the RequestPriority-->SpdyPriority mapping from
715 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
716 // sure it's being done right.
717 if (spdy_util_
.spdy_version() < SPDY3
) {
720 EXPECT_EQ(0, spdy_prio
);
723 EXPECT_EQ(1, spdy_prio
);
727 EXPECT_EQ(2, spdy_prio
);
730 EXPECT_EQ(3, spdy_prio
);
738 EXPECT_EQ(0, spdy_prio
);
741 EXPECT_EQ(1, spdy_prio
);
744 EXPECT_EQ(2, spdy_prio
);
747 EXPECT_EQ(3, spdy_prio
);
750 EXPECT_EQ(4, spdy_prio
);
757 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
758 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
760 CreateMockRead(*resp
),
761 CreateMockRead(*body
),
762 MockRead(ASYNC
, 0, 0) // EOF
765 DelayedSocketData
data(1, reads
, arraysize(reads
),
766 writes
, arraysize(writes
));
767 HttpRequestInfo http_req
= CreateGetRequest();
769 NormalSpdyTransactionHelper
helper(http_req
, p
, BoundNetLog(),
771 helper
.RunToCompletion(&data
);
772 TransactionHelperResult out
= helper
.output();
773 EXPECT_EQ(OK
, out
.rv
);
774 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
775 EXPECT_EQ("hello!", out
.response_data
);
779 // Start three gets simultaniously; making sure that multiplexed
780 // streams work properly.
782 // This can't use the TransactionHelper method, since it only
783 // handles a single transaction, and finishes them as soon
784 // as it launches them.
786 // TODO(gavinp): create a working generalized TransactionHelper that
787 // can allow multiple streams in flight.
789 TEST_P(SpdyNetworkTransactionTest
, ThreeGets
) {
790 scoped_ptr
<SpdyFrame
> req(
791 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
792 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
793 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
794 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
796 scoped_ptr
<SpdyFrame
> req2(
797 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
798 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
799 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
800 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
802 scoped_ptr
<SpdyFrame
> req3(
803 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
804 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
805 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
806 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
808 MockWrite writes
[] = {
809 CreateMockWrite(*req
),
810 CreateMockWrite(*req2
),
811 CreateMockWrite(*req3
),
814 CreateMockRead(*resp
, 1),
815 CreateMockRead(*body
),
816 CreateMockRead(*resp2
, 4),
817 CreateMockRead(*body2
),
818 CreateMockRead(*resp3
, 7),
819 CreateMockRead(*body3
),
821 CreateMockRead(*fbody
),
822 CreateMockRead(*fbody2
),
823 CreateMockRead(*fbody3
),
825 MockRead(ASYNC
, 0, 0), // EOF
827 OrderedSocketData
data(reads
, arraysize(reads
),
828 writes
, arraysize(writes
));
829 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
832 TransactionHelperResult out
;
833 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
834 BoundNetLog(), GetParam(), NULL
);
835 helper
.RunPreTestSetup();
836 helper
.AddData(&data
);
837 // We require placeholder data because three get requests are sent out, so
838 // there needs to be three sets of SSL connection data.
839 helper
.AddData(&data_placeholder
);
840 helper
.AddData(&data_placeholder
);
841 scoped_ptr
<HttpNetworkTransaction
> trans1(
842 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
843 scoped_ptr
<HttpNetworkTransaction
> trans2(
844 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
845 scoped_ptr
<HttpNetworkTransaction
> trans3(
846 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
848 TestCompletionCallback callback1
;
849 TestCompletionCallback callback2
;
850 TestCompletionCallback callback3
;
852 HttpRequestInfo httpreq1
= CreateGetRequest();
853 HttpRequestInfo httpreq2
= CreateGetRequest();
854 HttpRequestInfo httpreq3
= CreateGetRequest();
856 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
857 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
858 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
859 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
860 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
861 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
863 out
.rv
= callback1
.WaitForResult();
864 ASSERT_EQ(OK
, out
.rv
);
865 out
.rv
= callback3
.WaitForResult();
866 ASSERT_EQ(OK
, out
.rv
);
868 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
869 EXPECT_TRUE(response1
->headers
.get() != NULL
);
870 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
871 out
.status_line
= response1
->headers
->GetStatusLine();
872 out
.response_info
= *response1
;
874 trans2
->GetResponseInfo();
876 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
877 helper
.VerifyDataConsumed();
878 EXPECT_EQ(OK
, out
.rv
);
880 EXPECT_EQ(OK
, out
.rv
);
881 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
882 EXPECT_EQ("hello!hello!", out
.response_data
);
885 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBinding
) {
886 scoped_ptr
<SpdyFrame
> req(
887 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
888 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
889 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
890 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
892 scoped_ptr
<SpdyFrame
> req2(
893 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
894 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
895 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
896 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
898 MockWrite writes
[] = {
899 CreateMockWrite(*req
),
900 CreateMockWrite(*req2
),
903 CreateMockRead(*resp
, 1),
904 CreateMockRead(*body
),
905 CreateMockRead(*resp2
, 4),
906 CreateMockRead(*body2
),
907 CreateMockRead(*fbody
),
908 CreateMockRead(*fbody2
),
909 MockRead(ASYNC
, 0, 0), // EOF
911 OrderedSocketData
data(reads
, arraysize(reads
),
912 writes
, arraysize(writes
));
914 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
916 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
917 data_placeholder
.set_connect_data(never_finishing_connect
);
920 TransactionHelperResult out
;
921 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
922 BoundNetLog(), GetParam(), NULL
);
923 helper
.RunPreTestSetup();
924 helper
.AddData(&data
);
925 // We require placeholder data because two get requests are sent out, so
926 // there needs to be two sets of SSL connection data.
927 helper
.AddData(&data_placeholder
);
928 scoped_ptr
<HttpNetworkTransaction
> trans1(
929 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
930 scoped_ptr
<HttpNetworkTransaction
> trans2(
931 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
933 TestCompletionCallback callback1
;
934 TestCompletionCallback callback2
;
936 HttpRequestInfo httpreq1
= CreateGetRequest();
937 HttpRequestInfo httpreq2
= CreateGetRequest();
939 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
940 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
941 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
942 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
944 out
.rv
= callback1
.WaitForResult();
945 ASSERT_EQ(OK
, out
.rv
);
946 out
.rv
= callback2
.WaitForResult();
947 ASSERT_EQ(OK
, out
.rv
);
949 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
950 EXPECT_TRUE(response1
->headers
.get() != NULL
);
951 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
952 out
.status_line
= response1
->headers
->GetStatusLine();
953 out
.response_info
= *response1
;
954 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
955 EXPECT_EQ(OK
, out
.rv
);
956 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
957 EXPECT_EQ("hello!hello!", out
.response_data
);
959 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
960 EXPECT_TRUE(response2
->headers
.get() != NULL
);
961 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
962 out
.status_line
= response2
->headers
->GetStatusLine();
963 out
.response_info
= *response2
;
964 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
965 EXPECT_EQ(OK
, out
.rv
);
966 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
967 EXPECT_EQ("hello!hello!", out
.response_data
);
969 helper
.VerifyDataConsumed();
972 TEST_P(SpdyNetworkTransactionTest
, TwoGetsLateBindingFromPreconnect
) {
973 scoped_ptr
<SpdyFrame
> req(
974 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
975 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
976 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
977 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
979 scoped_ptr
<SpdyFrame
> req2(
980 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
981 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
982 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
983 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
985 MockWrite writes
[] = {
986 CreateMockWrite(*req
),
987 CreateMockWrite(*req2
),
990 CreateMockRead(*resp
, 1),
991 CreateMockRead(*body
),
992 CreateMockRead(*resp2
, 4),
993 CreateMockRead(*body2
),
994 CreateMockRead(*fbody
),
995 CreateMockRead(*fbody2
),
996 MockRead(ASYNC
, 0, 0), // EOF
998 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
999 writes
, arraysize(writes
));
1001 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
1003 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1004 data_placeholder
.set_connect_data(never_finishing_connect
);
1007 TransactionHelperResult out
;
1008 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1009 BoundNetLog(), GetParam(), NULL
);
1010 helper
.RunPreTestSetup();
1011 helper
.AddData(&preconnect_data
);
1012 // We require placeholder data because 3 connections are attempted (first is
1013 // the preconnect, 2nd and 3rd are the never finished connections.
1014 helper
.AddData(&data_placeholder
);
1015 helper
.AddData(&data_placeholder
);
1017 scoped_ptr
<HttpNetworkTransaction
> trans1(
1018 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1019 scoped_ptr
<HttpNetworkTransaction
> trans2(
1020 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1022 TestCompletionCallback callback1
;
1023 TestCompletionCallback callback2
;
1025 HttpRequestInfo httpreq
= CreateGetRequest();
1027 // Preconnect the first.
1028 SSLConfig preconnect_ssl_config
;
1029 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
1030 HttpStreamFactory
* http_stream_factory
=
1031 helper
.session()->http_stream_factory();
1032 if (http_stream_factory
->has_next_protos()) {
1033 preconnect_ssl_config
.next_protos
= http_stream_factory
->next_protos();
1036 http_stream_factory
->PreconnectStreams(
1037 1, httpreq
, DEFAULT_PRIORITY
,
1038 preconnect_ssl_config
, preconnect_ssl_config
);
1040 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
1041 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1042 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
1043 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1045 out
.rv
= callback1
.WaitForResult();
1046 ASSERT_EQ(OK
, out
.rv
);
1047 out
.rv
= callback2
.WaitForResult();
1048 ASSERT_EQ(OK
, out
.rv
);
1050 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1051 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1052 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1053 out
.status_line
= response1
->headers
->GetStatusLine();
1054 out
.response_info
= *response1
;
1055 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1056 EXPECT_EQ(OK
, out
.rv
);
1057 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1058 EXPECT_EQ("hello!hello!", out
.response_data
);
1060 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1061 EXPECT_TRUE(response2
->headers
.get() != NULL
);
1062 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
1063 out
.status_line
= response2
->headers
->GetStatusLine();
1064 out
.response_info
= *response2
;
1065 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1066 EXPECT_EQ(OK
, out
.rv
);
1067 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1068 EXPECT_EQ("hello!hello!", out
.response_data
);
1070 helper
.VerifyDataConsumed();
1073 // Similar to ThreeGets above, however this test adds a SETTINGS
1074 // frame. The SETTINGS frame is read during the IO loop waiting on
1075 // the first transaction completion, and sets a maximum concurrent
1076 // stream limit of 1. This means that our IO loop exists after the
1077 // second transaction completes, so we can assert on read_index().
1078 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrent
) {
1079 // Construct the request.
1080 scoped_ptr
<SpdyFrame
> req(
1081 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1082 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1083 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1084 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1086 scoped_ptr
<SpdyFrame
> req2(
1087 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1088 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1089 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1090 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1092 scoped_ptr
<SpdyFrame
> req3(
1093 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
1094 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1095 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, false));
1096 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1098 SettingsMap settings
;
1099 const uint32 max_concurrent_streams
= 1;
1100 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1101 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1102 scoped_ptr
<SpdyFrame
> settings_frame(
1103 spdy_util_
.ConstructSpdySettings(settings
));
1105 MockWrite writes
[] = {
1106 CreateMockWrite(*req
),
1107 CreateMockWrite(*req2
),
1108 CreateMockWrite(*req3
),
1111 MockRead reads
[] = {
1112 CreateMockRead(*settings_frame
, 1),
1113 CreateMockRead(*resp
),
1114 CreateMockRead(*body
),
1115 CreateMockRead(*fbody
),
1116 CreateMockRead(*resp2
, 7),
1117 CreateMockRead(*body2
),
1118 CreateMockRead(*fbody2
),
1119 CreateMockRead(*resp3
, 12),
1120 CreateMockRead(*body3
),
1121 CreateMockRead(*fbody3
),
1123 MockRead(ASYNC
, 0, 0), // EOF
1126 OrderedSocketData
data(reads
, arraysize(reads
),
1127 writes
, arraysize(writes
));
1128 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1131 TransactionHelperResult out
;
1133 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1134 BoundNetLog(), GetParam(), NULL
);
1135 helper
.RunPreTestSetup();
1136 helper
.AddData(&data
);
1137 // We require placeholder data because three get requests are sent out, so
1138 // there needs to be three sets of SSL connection data.
1139 helper
.AddData(&data_placeholder
);
1140 helper
.AddData(&data_placeholder
);
1141 scoped_ptr
<HttpNetworkTransaction
> trans1(
1142 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1143 scoped_ptr
<HttpNetworkTransaction
> trans2(
1144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1145 scoped_ptr
<HttpNetworkTransaction
> trans3(
1146 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1148 TestCompletionCallback callback1
;
1149 TestCompletionCallback callback2
;
1150 TestCompletionCallback callback3
;
1152 HttpRequestInfo httpreq1
= CreateGetRequest();
1153 HttpRequestInfo httpreq2
= CreateGetRequest();
1154 HttpRequestInfo httpreq3
= CreateGetRequest();
1156 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1157 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1158 // Run transaction 1 through quickly to force a read of our SETTINGS
1160 out
.rv
= callback1
.WaitForResult();
1161 ASSERT_EQ(OK
, out
.rv
);
1163 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1164 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1165 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1166 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1167 out
.rv
= callback2
.WaitForResult();
1168 ASSERT_EQ(OK
, out
.rv
);
1169 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1171 out
.rv
= callback3
.WaitForResult();
1172 ASSERT_EQ(OK
, out
.rv
);
1174 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1175 ASSERT_TRUE(response1
!= NULL
);
1176 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1177 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1178 out
.status_line
= response1
->headers
->GetStatusLine();
1179 out
.response_info
= *response1
;
1180 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1181 EXPECT_EQ(OK
, out
.rv
);
1182 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1183 EXPECT_EQ("hello!hello!", out
.response_data
);
1185 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1186 out
.status_line
= response2
->headers
->GetStatusLine();
1187 out
.response_info
= *response2
;
1188 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1189 EXPECT_EQ(OK
, out
.rv
);
1190 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1191 EXPECT_EQ("hello!hello!", out
.response_data
);
1193 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1194 out
.status_line
= response3
->headers
->GetStatusLine();
1195 out
.response_info
= *response3
;
1196 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1197 EXPECT_EQ(OK
, out
.rv
);
1198 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1199 EXPECT_EQ("hello!hello!", out
.response_data
);
1201 helper
.VerifyDataConsumed();
1203 EXPECT_EQ(OK
, out
.rv
);
1206 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1207 // a fourth transaction. The third and fourth transactions have
1208 // different data ("hello!" vs "hello!hello!") and because of the
1209 // user specified priority, we expect to see them inverted in
1210 // the response from the server.
1211 TEST_P(SpdyNetworkTransactionTest
, FourGetsWithMaxConcurrentPriority
) {
1212 // Construct the request.
1213 scoped_ptr
<SpdyFrame
> req(
1214 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1215 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1216 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1217 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1219 scoped_ptr
<SpdyFrame
> req2(
1220 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1221 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1222 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1223 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1225 scoped_ptr
<SpdyFrame
> req4(
1226 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
, true));
1227 scoped_ptr
<SpdyFrame
> resp4(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
1228 scoped_ptr
<SpdyFrame
> fbody4(spdy_util_
.ConstructSpdyBodyFrame(5, true));
1230 scoped_ptr
<SpdyFrame
> req3(
1231 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
, true));
1232 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 7));
1233 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(7, false));
1234 scoped_ptr
<SpdyFrame
> fbody3(spdy_util_
.ConstructSpdyBodyFrame(7, true));
1236 SettingsMap settings
;
1237 const uint32 max_concurrent_streams
= 1;
1238 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1239 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1240 scoped_ptr
<SpdyFrame
> settings_frame(
1241 spdy_util_
.ConstructSpdySettings(settings
));
1243 MockWrite writes
[] = { CreateMockWrite(*req
),
1244 CreateMockWrite(*req2
),
1245 CreateMockWrite(*req4
),
1246 CreateMockWrite(*req3
),
1248 MockRead reads
[] = {
1249 CreateMockRead(*settings_frame
, 1),
1250 CreateMockRead(*resp
),
1251 CreateMockRead(*body
),
1252 CreateMockRead(*fbody
),
1253 CreateMockRead(*resp2
, 7),
1254 CreateMockRead(*body2
),
1255 CreateMockRead(*fbody2
),
1256 CreateMockRead(*resp4
, 13),
1257 CreateMockRead(*fbody4
),
1258 CreateMockRead(*resp3
, 16),
1259 CreateMockRead(*body3
),
1260 CreateMockRead(*fbody3
),
1262 MockRead(ASYNC
, 0, 0), // EOF
1265 OrderedSocketData
data(reads
, arraysize(reads
),
1266 writes
, arraysize(writes
));
1267 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1270 TransactionHelperResult out
;
1271 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1272 BoundNetLog(), GetParam(), NULL
);
1273 helper
.RunPreTestSetup();
1274 helper
.AddData(&data
);
1275 // We require placeholder data because four get requests are sent out, so
1276 // there needs to be four sets of SSL connection data.
1277 helper
.AddData(&data_placeholder
);
1278 helper
.AddData(&data_placeholder
);
1279 helper
.AddData(&data_placeholder
);
1280 scoped_ptr
<HttpNetworkTransaction
> trans1(
1281 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1282 scoped_ptr
<HttpNetworkTransaction
> trans2(
1283 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1284 scoped_ptr
<HttpNetworkTransaction
> trans3(
1285 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1286 scoped_ptr
<HttpNetworkTransaction
> trans4(
1287 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
1289 TestCompletionCallback callback1
;
1290 TestCompletionCallback callback2
;
1291 TestCompletionCallback callback3
;
1292 TestCompletionCallback callback4
;
1294 HttpRequestInfo httpreq1
= CreateGetRequest();
1295 HttpRequestInfo httpreq2
= CreateGetRequest();
1296 HttpRequestInfo httpreq3
= CreateGetRequest();
1297 HttpRequestInfo httpreq4
= CreateGetRequest();
1299 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1300 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1301 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1302 out
.rv
= callback1
.WaitForResult();
1303 ASSERT_EQ(OK
, out
.rv
);
1305 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1306 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1307 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1308 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1309 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1310 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1312 out
.rv
= callback2
.WaitForResult();
1313 ASSERT_EQ(OK
, out
.rv
);
1314 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1316 out
.rv
= callback3
.WaitForResult();
1317 ASSERT_EQ(OK
, out
.rv
);
1319 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1320 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1321 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1322 out
.status_line
= response1
->headers
->GetStatusLine();
1323 out
.response_info
= *response1
;
1324 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1325 EXPECT_EQ(OK
, out
.rv
);
1326 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1327 EXPECT_EQ("hello!hello!", out
.response_data
);
1329 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1330 out
.status_line
= response2
->headers
->GetStatusLine();
1331 out
.response_info
= *response2
;
1332 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1333 EXPECT_EQ(OK
, out
.rv
);
1334 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1335 EXPECT_EQ("hello!hello!", out
.response_data
);
1337 // notice: response3 gets two hellos, response4 gets one
1338 // hello, so we know dequeuing priority was respected.
1339 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1340 out
.status_line
= response3
->headers
->GetStatusLine();
1341 out
.response_info
= *response3
;
1342 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1343 EXPECT_EQ(OK
, out
.rv
);
1344 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1345 EXPECT_EQ("hello!hello!", out
.response_data
);
1347 out
.rv
= callback4
.WaitForResult();
1348 EXPECT_EQ(OK
, out
.rv
);
1349 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1350 out
.status_line
= response4
->headers
->GetStatusLine();
1351 out
.response_info
= *response4
;
1352 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1353 EXPECT_EQ(OK
, out
.rv
);
1354 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1355 EXPECT_EQ("hello!", out
.response_data
);
1356 helper
.VerifyDataConsumed();
1357 EXPECT_EQ(OK
, out
.rv
);
1360 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1361 // deletes a session in the middle of the transaction to insure
1362 // that we properly remove pendingcreatestream objects from
1364 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentDelete
) {
1365 // Construct the request.
1366 scoped_ptr
<SpdyFrame
> req(
1367 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1368 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1369 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1370 scoped_ptr
<SpdyFrame
> fbody(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1372 scoped_ptr
<SpdyFrame
> req2(
1373 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1374 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1375 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, false));
1376 scoped_ptr
<SpdyFrame
> fbody2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
1378 SettingsMap settings
;
1379 const uint32 max_concurrent_streams
= 1;
1380 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1381 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1382 scoped_ptr
<SpdyFrame
> settings_frame(
1383 spdy_util_
.ConstructSpdySettings(settings
));
1385 MockWrite writes
[] = { CreateMockWrite(*req
),
1386 CreateMockWrite(*req2
),
1388 MockRead reads
[] = {
1389 CreateMockRead(*settings_frame
, 1),
1390 CreateMockRead(*resp
),
1391 CreateMockRead(*body
),
1392 CreateMockRead(*fbody
),
1393 CreateMockRead(*resp2
, 7),
1394 CreateMockRead(*body2
),
1395 CreateMockRead(*fbody2
),
1396 MockRead(ASYNC
, 0, 0), // EOF
1399 OrderedSocketData
data(reads
, arraysize(reads
),
1400 writes
, arraysize(writes
));
1401 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1404 TransactionHelperResult out
;
1405 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1406 BoundNetLog(), GetParam(), NULL
);
1407 helper
.RunPreTestSetup();
1408 helper
.AddData(&data
);
1409 // We require placeholder data because three get requests are sent out, so
1410 // there needs to be three sets of SSL connection data.
1411 helper
.AddData(&data_placeholder
);
1412 helper
.AddData(&data_placeholder
);
1413 scoped_ptr
<HttpNetworkTransaction
> trans1(
1414 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1415 scoped_ptr
<HttpNetworkTransaction
> trans2(
1416 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1417 scoped_ptr
<HttpNetworkTransaction
> trans3(
1418 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1420 TestCompletionCallback callback1
;
1421 TestCompletionCallback callback2
;
1422 TestCompletionCallback callback3
;
1424 HttpRequestInfo httpreq1
= CreateGetRequest();
1425 HttpRequestInfo httpreq2
= CreateGetRequest();
1426 HttpRequestInfo httpreq3
= CreateGetRequest();
1428 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1429 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1430 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1431 out
.rv
= callback1
.WaitForResult();
1432 ASSERT_EQ(OK
, out
.rv
);
1434 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1435 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1436 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1437 delete trans3
.release();
1438 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1439 out
.rv
= callback2
.WaitForResult();
1440 ASSERT_EQ(OK
, out
.rv
);
1442 EXPECT_EQ(8U, data
.read_index());
1444 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1445 ASSERT_TRUE(response1
!= NULL
);
1446 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1447 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1448 out
.status_line
= response1
->headers
->GetStatusLine();
1449 out
.response_info
= *response1
;
1450 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1451 EXPECT_EQ(OK
, out
.rv
);
1452 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1453 EXPECT_EQ("hello!hello!", out
.response_data
);
1455 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1456 ASSERT_TRUE(response2
!= NULL
);
1457 out
.status_line
= response2
->headers
->GetStatusLine();
1458 out
.response_info
= *response2
;
1459 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1460 EXPECT_EQ(OK
, out
.rv
);
1461 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1462 EXPECT_EQ("hello!hello!", out
.response_data
);
1463 helper
.VerifyDataConsumed();
1464 EXPECT_EQ(OK
, out
.rv
);
1469 // The KillerCallback will delete the transaction on error as part of the
1471 class KillerCallback
: public TestCompletionCallbackBase
{
1473 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1474 : transaction_(transaction
),
1475 callback_(base::Bind(&KillerCallback::OnComplete
,
1476 base::Unretained(this))) {
1479 virtual ~KillerCallback() {}
1481 const CompletionCallback
& callback() const { return callback_
; }
1484 void OnComplete(int result
) {
1486 delete transaction_
;
1491 HttpNetworkTransaction
* transaction_
;
1492 CompletionCallback callback_
;
1497 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1498 // closes the socket while we have a pending transaction waiting for
1499 // a pending stream creation. http://crbug.com/52901
1500 TEST_P(SpdyNetworkTransactionTest
, ThreeGetsWithMaxConcurrentSocketClose
) {
1501 // Construct the request.
1502 scoped_ptr
<SpdyFrame
> req(
1503 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1504 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1505 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1506 scoped_ptr
<SpdyFrame
> fin_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1508 scoped_ptr
<SpdyFrame
> req2(
1509 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1510 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1512 SettingsMap settings
;
1513 const uint32 max_concurrent_streams
= 1;
1514 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1515 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1516 scoped_ptr
<SpdyFrame
> settings_frame(
1517 spdy_util_
.ConstructSpdySettings(settings
));
1519 MockWrite writes
[] = { CreateMockWrite(*req
),
1520 CreateMockWrite(*req2
),
1522 MockRead reads
[] = {
1523 CreateMockRead(*settings_frame
, 1),
1524 CreateMockRead(*resp
),
1525 CreateMockRead(*body
),
1526 CreateMockRead(*fin_body
),
1527 CreateMockRead(*resp2
, 7),
1528 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1531 OrderedSocketData
data(reads
, arraysize(reads
),
1532 writes
, arraysize(writes
));
1533 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1536 TransactionHelperResult out
;
1537 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
1538 BoundNetLog(), GetParam(), NULL
);
1539 helper
.RunPreTestSetup();
1540 helper
.AddData(&data
);
1541 // We require placeholder data because three get requests are sent out, so
1542 // there needs to be three sets of SSL connection data.
1543 helper
.AddData(&data_placeholder
);
1544 helper
.AddData(&data_placeholder
);
1545 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, helper
.session().get());
1546 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, helper
.session().get());
1547 HttpNetworkTransaction
* trans3(
1548 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
1550 TestCompletionCallback callback1
;
1551 TestCompletionCallback callback2
;
1552 KillerCallback
callback3(trans3
);
1554 HttpRequestInfo httpreq1
= CreateGetRequest();
1555 HttpRequestInfo httpreq2
= CreateGetRequest();
1556 HttpRequestInfo httpreq3
= CreateGetRequest();
1558 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1559 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1560 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1561 out
.rv
= callback1
.WaitForResult();
1562 ASSERT_EQ(OK
, out
.rv
);
1564 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1565 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1566 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1567 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1568 out
.rv
= callback3
.WaitForResult();
1569 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1571 EXPECT_EQ(6U, data
.read_index());
1573 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1574 ASSERT_TRUE(response1
!= NULL
);
1575 EXPECT_TRUE(response1
->headers
.get() != NULL
);
1576 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1577 out
.status_line
= response1
->headers
->GetStatusLine();
1578 out
.response_info
= *response1
;
1579 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1580 EXPECT_EQ(OK
, out
.rv
);
1582 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1583 ASSERT_TRUE(response2
!= NULL
);
1584 out
.status_line
= response2
->headers
->GetStatusLine();
1585 out
.response_info
= *response2
;
1586 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1587 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1589 helper
.VerifyDataConsumed();
1592 // Test that a simple PUT request works.
1593 TEST_P(SpdyNetworkTransactionTest
, Put
) {
1594 // Setup the request
1595 HttpRequestInfo request
;
1596 request
.method
= "PUT";
1597 request
.url
= GURL("http://www.google.com/");
1599 const SpdyHeaderInfo kSynStartHeader
= {
1600 SYN_STREAM
, // Kind = Syn
1602 0, // Associated stream ID
1603 ConvertRequestPriorityToSpdyPriority(
1604 LOWEST
, spdy_util_
.spdy_version()),
1605 kSpdyCredentialSlotUnused
,
1606 CONTROL_FLAG_FIN
, // Control Flags
1607 false, // Compressed
1608 RST_STREAM_INVALID
, // Status
1611 DATA_FLAG_NONE
// Data Flags
1613 scoped_ptr
<SpdyHeaderBlock
> put_headers(
1614 spdy_util_
.ConstructPutHeaderBlock("http://www.google.com", 0));
1615 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyFrame(
1616 kSynStartHeader
, put_headers
.Pass()));
1617 MockWrite writes
[] = {
1618 CreateMockWrite(*req
),
1621 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1622 const SpdyHeaderInfo kSynReplyHeader
= {
1623 SYN_REPLY
, // Kind = SynReply
1625 0, // Associated stream ID
1626 ConvertRequestPriorityToSpdyPriority(
1627 LOWEST
, spdy_util_
.spdy_version()),
1628 kSpdyCredentialSlotUnused
,
1629 CONTROL_FLAG_NONE
, // Control Flags
1630 false, // Compressed
1631 RST_STREAM_INVALID
, // Status
1634 DATA_FLAG_NONE
// Data Flags
1636 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
1637 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
1638 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
1639 (*reply_headers
)["content-length"] = "1234";
1640 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyFrame(
1641 kSynReplyHeader
, reply_headers
.Pass()));
1642 MockRead reads
[] = {
1643 CreateMockRead(*resp
),
1644 CreateMockRead(*body
),
1645 MockRead(ASYNC
, 0, 0) // EOF
1648 DelayedSocketData
data(1, reads
, arraysize(reads
),
1649 writes
, arraysize(writes
));
1650 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1651 BoundNetLog(), GetParam(), NULL
);
1652 helper
.RunToCompletion(&data
);
1653 TransactionHelperResult out
= helper
.output();
1655 EXPECT_EQ(OK
, out
.rv
);
1656 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1659 // Test that a simple HEAD request works.
1660 TEST_P(SpdyNetworkTransactionTest
, Head
) {
1661 // Setup the request
1662 HttpRequestInfo request
;
1663 request
.method
= "HEAD";
1664 request
.url
= GURL("http://www.google.com/");
1666 const SpdyHeaderInfo kSynStartHeader
= {
1667 SYN_STREAM
, // Kind = Syn
1669 0, // Associated stream ID
1670 ConvertRequestPriorityToSpdyPriority(
1671 LOWEST
, spdy_util_
.spdy_version()),
1672 kSpdyCredentialSlotUnused
,
1673 CONTROL_FLAG_FIN
, // Control Flags
1674 false, // Compressed
1675 RST_STREAM_INVALID
, // Status
1678 DATA_FLAG_NONE
// Data Flags
1680 scoped_ptr
<SpdyHeaderBlock
> head_headers(
1681 spdy_util_
.ConstructHeadHeaderBlock("http://www.google.com", 0));
1682 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyFrame(
1683 kSynStartHeader
, head_headers
.Pass()));
1684 MockWrite writes
[] = {
1685 CreateMockWrite(*req
),
1688 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1689 const SpdyHeaderInfo kSynReplyHeader
= {
1690 SYN_REPLY
, // Kind = SynReply
1692 0, // Associated stream ID
1693 ConvertRequestPriorityToSpdyPriority(
1694 LOWEST
, spdy_util_
.spdy_version()),
1695 kSpdyCredentialSlotUnused
,
1696 CONTROL_FLAG_NONE
, // Control Flags
1697 false, // Compressed
1698 RST_STREAM_INVALID
, // Status
1701 DATA_FLAG_NONE
// Data Flags
1703 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
1704 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
1705 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
1706 (*reply_headers
)["content-length"] = "1234";
1707 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyFrame(
1709 reply_headers
.Pass()));
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 complex POST works.
1786 TEST_P(SpdyNetworkTransactionTest
, ComplexPost
) {
1787 scoped_ptr
<SpdyFrame
> req(
1788 spdy_util_
.ConstructSpdyPost(
1789 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
1790 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1791 MockWrite writes
[] = {
1792 CreateMockWrite(*req
),
1793 CreateMockWrite(*body
), // POST upload frame
1796 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1797 MockRead reads
[] = {
1798 CreateMockRead(*resp
),
1799 CreateMockRead(*body
),
1800 MockRead(ASYNC
, 0, 0) // EOF
1803 DelayedSocketData
data(2, reads
, arraysize(reads
),
1804 writes
, arraysize(writes
));
1805 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1807 BoundNetLog(), GetParam(), NULL
);
1808 helper
.RunToCompletion(&data
);
1809 TransactionHelperResult out
= helper
.output();
1810 EXPECT_EQ(OK
, out
.rv
);
1811 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1812 EXPECT_EQ("hello!", out
.response_data
);
1815 // Test that a chunked POST works.
1816 TEST_P(SpdyNetworkTransactionTest
, ChunkedPost
) {
1817 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1818 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1819 MockWrite writes
[] = {
1820 CreateMockWrite(*req
),
1821 CreateMockWrite(*body
),
1824 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1825 MockRead reads
[] = {
1826 CreateMockRead(*resp
),
1827 CreateMockRead(*body
),
1828 MockRead(ASYNC
, 0, 0) // EOF
1831 DelayedSocketData
data(2, reads
, arraysize(reads
),
1832 writes
, arraysize(writes
));
1833 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1835 BoundNetLog(), GetParam(), NULL
);
1837 // These chunks get merged into a single frame when being sent.
1838 const int kFirstChunkSize
= kUploadDataSize
/2;
1839 helper
.request().upload_data_stream
->AppendChunk(
1840 kUploadData
, kFirstChunkSize
, false);
1841 helper
.request().upload_data_stream
->AppendChunk(
1842 kUploadData
+ kFirstChunkSize
, kUploadDataSize
- kFirstChunkSize
, true);
1844 helper
.RunToCompletion(&data
);
1845 TransactionHelperResult out
= helper
.output();
1846 EXPECT_EQ(OK
, out
.rv
);
1847 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1848 EXPECT_EQ(kUploadData
, out
.response_data
);
1851 // Test that a chunked POST works with chunks appended after transaction starts.
1852 TEST_P(SpdyNetworkTransactionTest
, DelayedChunkedPost
) {
1853 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructChunkedSpdyPost(NULL
, 0));
1854 scoped_ptr
<SpdyFrame
> chunk1(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1855 scoped_ptr
<SpdyFrame
> chunk2(spdy_util_
.ConstructSpdyBodyFrame(1, false));
1856 scoped_ptr
<SpdyFrame
> chunk3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1857 MockWrite writes
[] = {
1858 CreateMockWrite(*req
),
1859 CreateMockWrite(*chunk1
),
1860 CreateMockWrite(*chunk2
),
1861 CreateMockWrite(*chunk3
),
1864 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1865 MockRead reads
[] = {
1866 CreateMockRead(*resp
),
1867 CreateMockRead(*chunk1
),
1868 CreateMockRead(*chunk2
),
1869 CreateMockRead(*chunk3
),
1870 MockRead(ASYNC
, 0, 0) // EOF
1873 DelayedSocketData
data(4, reads
, arraysize(reads
),
1874 writes
, arraysize(writes
));
1875 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1877 BoundNetLog(), GetParam(), NULL
);
1879 helper
.request().upload_data_stream
->AppendChunk(
1880 kUploadData
, kUploadDataSize
, false);
1882 helper
.RunPreTestSetup();
1883 helper
.AddData(&data
);
1884 ASSERT_TRUE(helper
.StartDefaultTest());
1886 base::RunLoop().RunUntilIdle();
1887 helper
.request().upload_data_stream
->AppendChunk(
1888 kUploadData
, kUploadDataSize
, false);
1889 base::RunLoop().RunUntilIdle();
1890 helper
.request().upload_data_stream
->AppendChunk(
1891 kUploadData
, kUploadDataSize
, true);
1893 helper
.FinishDefaultTest();
1894 helper
.VerifyDataConsumed();
1896 std::string expected_response
;
1897 expected_response
+= kUploadData
;
1898 expected_response
+= kUploadData
;
1899 expected_response
+= kUploadData
;
1901 TransactionHelperResult out
= helper
.output();
1902 EXPECT_EQ(OK
, out
.rv
);
1903 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1904 EXPECT_EQ(expected_response
, out
.response_data
);
1907 // Test that a POST without any post data works.
1908 TEST_P(SpdyNetworkTransactionTest
, NullPost
) {
1909 // Setup the request
1910 HttpRequestInfo request
;
1911 request
.method
= "POST";
1912 request
.url
= GURL(kRequestUrl
);
1913 // Create an empty UploadData.
1914 request
.upload_data_stream
= NULL
;
1916 // When request.upload_data_stream is NULL for post, content-length is
1917 // expected to be 0.
1918 scoped_ptr
<SpdyFrame
> req(
1919 spdy_util_
.ConstructSpdyPost(kRequestUrl
, 1, 0, LOWEST
, NULL
, 0));
1920 // Set the FIN bit since there will be no body.
1921 test::SetFrameFlags(req
.get(), CONTROL_FLAG_FIN
, spdy_util_
.spdy_version());
1922 MockWrite writes
[] = {
1923 CreateMockWrite(*req
),
1926 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1927 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1928 MockRead reads
[] = {
1929 CreateMockRead(*resp
),
1930 CreateMockRead(*body
),
1931 MockRead(ASYNC
, 0, 0) // EOF
1934 DelayedSocketData
data(1, reads
, arraysize(reads
),
1935 writes
, arraysize(writes
));
1937 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1938 BoundNetLog(), GetParam(), NULL
);
1939 helper
.RunToCompletion(&data
);
1940 TransactionHelperResult out
= helper
.output();
1941 EXPECT_EQ(OK
, out
.rv
);
1942 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1943 EXPECT_EQ("hello!", out
.response_data
);
1946 // Test that a simple POST works.
1947 TEST_P(SpdyNetworkTransactionTest
, EmptyPost
) {
1948 // Create an empty UploadDataStream.
1949 ScopedVector
<UploadElementReader
> element_readers
;
1950 UploadDataStream
stream(&element_readers
, 0);
1952 // Setup the request
1953 HttpRequestInfo request
;
1954 request
.method
= "POST";
1955 request
.url
= GURL(kRequestUrl
);
1956 request
.upload_data_stream
= &stream
;
1958 const uint64 kContentLength
= 0;
1959 scoped_ptr
<SpdyFrame
> req(
1960 spdy_util_
.ConstructSpdyPost(
1961 kRequestUrl
, 1, kContentLength
, LOWEST
, NULL
, 0));
1962 // Set the FIN bit since there will be no body.
1963 test::SetFrameFlags(req
.get(), CONTROL_FLAG_FIN
, spdy_util_
.spdy_version());
1964 MockWrite writes
[] = {
1965 CreateMockWrite(*req
),
1968 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
1969 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1970 MockRead reads
[] = {
1971 CreateMockRead(*resp
),
1972 CreateMockRead(*body
),
1973 MockRead(ASYNC
, 0, 0) // EOF
1976 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1978 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
1979 BoundNetLog(), GetParam(), NULL
);
1980 helper
.RunToCompletion(&data
);
1981 TransactionHelperResult out
= helper
.output();
1982 EXPECT_EQ(OK
, out
.rv
);
1983 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1984 EXPECT_EQ("hello!", out
.response_data
);
1987 // While we're doing a post, the server sends back a SYN_REPLY.
1988 TEST_P(SpdyNetworkTransactionTest
, PostWithEarlySynReply
) {
1989 static const char upload
[] = { "hello!" };
1990 ScopedVector
<UploadElementReader
> element_readers
;
1991 element_readers
.push_back(
1992 new UploadBytesElementReader(upload
, sizeof(upload
)));
1993 UploadDataStream
stream(&element_readers
, 0);
1995 // Setup the request
1996 HttpRequestInfo request
;
1997 request
.method
= "POST";
1998 request
.url
= GURL(kRequestUrl
);
1999 request
.upload_data_stream
= &stream
;
2001 scoped_ptr
<SpdyFrame
> stream_reply(
2002 spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
2003 MockRead reads
[] = {
2004 CreateMockRead(*stream_reply
, 1),
2005 MockRead(ASYNC
, 0, 4) // EOF
2008 scoped_ptr
<SpdyFrame
> req(
2009 spdy_util_
.ConstructSpdyPost(
2010 kRequestUrl
, 1, kUploadDataSize
, LOWEST
, NULL
, 0));
2011 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2012 scoped_ptr
<SpdyFrame
> rst(
2013 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2014 MockWrite writes
[] = {
2015 CreateMockWrite(*req
, 0),
2016 CreateMockWrite(*body
, 2),
2017 CreateMockWrite(*rst
, 3)
2020 DeterministicSocketData
data(reads
, arraysize(reads
),
2021 writes
, arraysize(writes
));
2022 NormalSpdyTransactionHelper
helper(CreatePostRequest(), DEFAULT_PRIORITY
,
2023 BoundNetLog(), GetParam(), NULL
);
2024 helper
.SetDeterministic();
2025 helper
.RunPreTestSetup();
2026 helper
.AddDeterministicData(&data
);
2027 HttpNetworkTransaction
* trans
= helper
.trans();
2029 TestCompletionCallback callback
;
2030 int rv
= trans
->Start(
2031 &CreatePostRequest(), callback
.callback(), BoundNetLog());
2032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2035 rv
= callback
.WaitForResult();
2036 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2040 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2041 // socket causes the TCP write to return zero. This test checks that the client
2042 // tries to queue up the RST_STREAM frame again.
2043 TEST_P(SpdyNetworkTransactionTest
, SocketWriteReturnsZero
) {
2044 scoped_ptr
<SpdyFrame
> req(
2045 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2046 scoped_ptr
<SpdyFrame
> rst(
2047 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2048 MockWrite writes
[] = {
2049 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
2050 MockWrite(SYNCHRONOUS
, 0, 0, 2),
2051 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
2054 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2055 MockRead reads
[] = {
2056 CreateMockRead(*resp
.get(), 1, ASYNC
),
2057 MockRead(ASYNC
, 0, 0, 4) // EOF
2060 DeterministicSocketData
data(reads
, arraysize(reads
),
2061 writes
, arraysize(writes
));
2062 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2063 BoundNetLog(), GetParam(), NULL
);
2064 helper
.SetDeterministic();
2065 helper
.RunPreTestSetup();
2066 helper
.AddDeterministicData(&data
);
2067 HttpNetworkTransaction
* trans
= helper
.trans();
2069 TestCompletionCallback callback
;
2070 int rv
= trans
->Start(
2071 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2072 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2076 helper
.ResetTrans();
2080 helper
.VerifyDataConsumed();
2083 // Test that the transaction doesn't crash when we don't have a reply.
2084 TEST_P(SpdyNetworkTransactionTest
, ResponseWithoutSynReply
) {
2085 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2086 MockRead reads
[] = {
2087 CreateMockRead(*body
),
2088 MockRead(ASYNC
, 0, 0) // EOF
2091 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
2092 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2093 BoundNetLog(), GetParam(), NULL
);
2094 helper
.RunToCompletion(&data
);
2095 TransactionHelperResult out
= helper
.output();
2096 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2099 // Test that the transaction doesn't crash when we get two replies on the same
2100 // stream ID. See http://crbug.com/45639.
2101 TEST_P(SpdyNetworkTransactionTest
, ResponseWithTwoSynReplies
) {
2102 scoped_ptr
<SpdyFrame
> req(
2103 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2104 scoped_ptr
<SpdyFrame
> rst(
2105 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE
));
2106 MockWrite writes
[] = {
2107 CreateMockWrite(*req
),
2108 CreateMockWrite(*rst
),
2111 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2112 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2113 MockRead reads
[] = {
2114 CreateMockRead(*resp
),
2115 CreateMockRead(*resp
),
2116 CreateMockRead(*body
),
2117 MockRead(ASYNC
, 0, 0) // EOF
2120 DelayedSocketData
data(1, reads
, arraysize(reads
),
2121 writes
, arraysize(writes
));
2123 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2124 BoundNetLog(), GetParam(), NULL
);
2125 helper
.RunPreTestSetup();
2126 helper
.AddData(&data
);
2128 HttpNetworkTransaction
* trans
= helper
.trans();
2130 TestCompletionCallback callback
;
2131 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2132 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2133 rv
= callback
.WaitForResult();
2136 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2137 ASSERT_TRUE(response
!= NULL
);
2138 EXPECT_TRUE(response
->headers
.get() != NULL
);
2139 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2140 std::string response_data
;
2141 rv
= ReadTransaction(trans
, &response_data
);
2142 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
2144 helper
.VerifyDataConsumed();
2147 TEST_P(SpdyNetworkTransactionTest
, ResetReplyWithTransferEncoding
) {
2148 // Construct the request.
2149 scoped_ptr
<SpdyFrame
> req(
2150 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2151 scoped_ptr
<SpdyFrame
> rst(
2152 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
2153 MockWrite writes
[] = {
2154 CreateMockWrite(*req
),
2155 CreateMockWrite(*rst
),
2158 const char* const headers
[] = {
2159 "transfer-encoding", "chunked"
2161 scoped_ptr
<SpdyFrame
> resp(
2162 spdy_util_
.ConstructSpdyGetSynReply(headers
, 1, 1));
2163 scoped_ptr
<SpdyFrame
> body(
2164 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2165 MockRead reads
[] = {
2166 CreateMockRead(*resp
),
2167 CreateMockRead(*body
),
2168 MockRead(ASYNC
, 0, 0) // EOF
2171 DelayedSocketData
data(1, reads
, arraysize(reads
),
2172 writes
, arraysize(writes
));
2173 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2174 BoundNetLog(), GetParam(), NULL
);
2175 helper
.RunToCompletion(&data
);
2176 TransactionHelperResult out
= helper
.output();
2177 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2179 helper
.session()->spdy_session_pool()->CloseAllSessions();
2180 helper
.VerifyDataConsumed();
2183 TEST_P(SpdyNetworkTransactionTest
, ResetPushWithTransferEncoding
) {
2184 // Construct the request.
2185 scoped_ptr
<SpdyFrame
> req(
2186 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2187 scoped_ptr
<SpdyFrame
> rst(
2188 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2189 MockWrite writes
[] = {
2190 CreateMockWrite(*req
),
2191 CreateMockWrite(*rst
),
2194 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2195 const char* const headers
[] = {
2196 "transfer-encoding", "chunked"
2198 scoped_ptr
<SpdyFrame
> push(
2199 spdy_util_
.ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2200 2, 1, "http://www.google.com/1"));
2201 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2202 MockRead reads
[] = {
2203 CreateMockRead(*resp
),
2204 CreateMockRead(*push
),
2205 CreateMockRead(*body
),
2206 MockRead(ASYNC
, 0, 0) // EOF
2209 DelayedSocketData
data(1, reads
, arraysize(reads
),
2210 writes
, arraysize(writes
));
2211 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2212 BoundNetLog(), GetParam(), NULL
);
2213 helper
.RunToCompletion(&data
);
2214 TransactionHelperResult out
= helper
.output();
2215 EXPECT_EQ(OK
, out
.rv
);
2216 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2217 EXPECT_EQ("hello!", out
.response_data
);
2219 helper
.session()->spdy_session_pool()->CloseAllSessions();
2220 helper
.VerifyDataConsumed();
2223 TEST_P(SpdyNetworkTransactionTest
, CancelledTransaction
) {
2224 // Construct the request.
2225 scoped_ptr
<SpdyFrame
> req(
2226 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2227 MockWrite writes
[] = {
2228 CreateMockWrite(*req
),
2231 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2232 MockRead reads
[] = {
2233 CreateMockRead(*resp
),
2234 // This following read isn't used by the test, except during the
2235 // RunUntilIdle() call at the end since the SpdySession survives the
2236 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2237 // MockRead will do here.
2238 MockRead(ASYNC
, 0, 0) // EOF
2241 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2242 writes
, arraysize(writes
));
2244 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2245 BoundNetLog(), GetParam(), NULL
);
2246 helper
.RunPreTestSetup();
2247 helper
.AddData(&data
);
2248 HttpNetworkTransaction
* trans
= helper
.trans();
2250 TestCompletionCallback callback
;
2251 int rv
= trans
->Start(
2252 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2254 helper
.ResetTrans(); // Cancel the transaction.
2256 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2257 // MockClientSocketFactory) are still alive.
2258 base::RunLoop().RunUntilIdle();
2259 helper
.VerifyDataNotConsumed();
2262 // Verify that the client sends a Rst Frame upon cancelling the stream.
2263 TEST_P(SpdyNetworkTransactionTest
, CancelledTransactionSendRst
) {
2264 scoped_ptr
<SpdyFrame
> req(
2265 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2266 scoped_ptr
<SpdyFrame
> rst(
2267 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2268 MockWrite writes
[] = {
2269 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2270 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2273 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2274 MockRead reads
[] = {
2275 CreateMockRead(*resp
, 1, ASYNC
),
2276 MockRead(ASYNC
, 0, 0, 3) // EOF
2279 DeterministicSocketData
data(reads
, arraysize(reads
),
2280 writes
, arraysize(writes
));
2282 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2285 helper
.SetDeterministic();
2286 helper
.RunPreTestSetup();
2287 helper
.AddDeterministicData(&data
);
2288 HttpNetworkTransaction
* trans
= helper
.trans();
2290 TestCompletionCallback callback
;
2292 int rv
= trans
->Start(
2293 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2294 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2298 helper
.ResetTrans();
2302 helper
.VerifyDataConsumed();
2305 // Verify that the client can correctly deal with the user callback attempting
2306 // to start another transaction on a session that is closing down. See
2307 // http://crbug.com/47455
2308 TEST_P(SpdyNetworkTransactionTest
, StartTransactionOnReadCallback
) {
2309 scoped_ptr
<SpdyFrame
> req(
2310 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2311 MockWrite writes
[] = { CreateMockWrite(*req
) };
2312 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2314 // The indicated length of this frame is longer than its actual length. When
2315 // the session receives an empty frame after this one, it shuts down the
2316 // session, and calls the read callback with the incomplete data.
2317 const uint8 kGetBodyFrame2
[] = {
2318 0x00, 0x00, 0x00, 0x01,
2319 0x01, 0x00, 0x00, 0x07,
2320 'h', 'e', 'l', 'l', 'o', '!',
2323 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2324 MockRead reads
[] = {
2325 CreateMockRead(*resp
, 2),
2326 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2327 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2328 arraysize(kGetBodyFrame2
), 4),
2329 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2330 MockRead(ASYNC
, 0, 0, 6), // EOF
2332 MockRead reads2
[] = {
2333 CreateMockRead(*resp
, 2),
2334 MockRead(ASYNC
, 0, 0, 3), // EOF
2337 OrderedSocketData
data(reads
, arraysize(reads
),
2338 writes
, arraysize(writes
));
2339 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2340 writes2
, arraysize(writes2
));
2342 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2343 BoundNetLog(), GetParam(), NULL
);
2344 helper
.RunPreTestSetup();
2345 helper
.AddData(&data
);
2346 helper
.AddData(&data2
);
2347 HttpNetworkTransaction
* trans
= helper
.trans();
2349 // Start the transaction with basic parameters.
2350 TestCompletionCallback callback
;
2351 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2352 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2353 rv
= callback
.WaitForResult();
2355 const int kSize
= 3000;
2356 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2360 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback
,
2362 // This forces an err_IO_pending, which sets the callback.
2363 data
.CompleteRead();
2364 // This finishes the read.
2365 data
.CompleteRead();
2366 helper
.VerifyDataConsumed();
2369 // Verify that the client can correctly deal with the user callback deleting the
2370 // transaction. Failures will usually be valgrind errors. See
2371 // http://crbug.com/46925
2372 TEST_P(SpdyNetworkTransactionTest
, DeleteSessionOnReadCallback
) {
2373 scoped_ptr
<SpdyFrame
> req(
2374 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2375 MockWrite writes
[] = { CreateMockWrite(*req
) };
2377 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2378 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2379 MockRead reads
[] = {
2380 CreateMockRead(*resp
.get(), 2),
2381 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2382 CreateMockRead(*body
.get(), 4),
2383 MockRead(ASYNC
, 0, 0, 5), // EOF
2386 OrderedSocketData
data(reads
, arraysize(reads
),
2387 writes
, arraysize(writes
));
2389 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2390 BoundNetLog(), GetParam(), NULL
);
2391 helper
.RunPreTestSetup();
2392 helper
.AddData(&data
);
2393 HttpNetworkTransaction
* trans
= helper
.trans();
2395 // Start the transaction with basic parameters.
2396 TestCompletionCallback callback
;
2397 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2398 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2399 rv
= callback
.WaitForResult();
2401 // Setup a user callback which will delete the session, and clear out the
2402 // memory holding the stream object. Note that the callback deletes trans.
2403 const int kSize
= 3000;
2404 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2408 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback
,
2409 base::Unretained(&helper
)));
2410 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2411 data
.CompleteRead();
2413 // Finish running rest of tasks.
2414 base::RunLoop().RunUntilIdle();
2415 helper
.VerifyDataConsumed();
2418 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2419 TEST_P(SpdyNetworkTransactionTest
, RedirectGetRequest
) {
2420 const SpdyHeaderInfo kSynStartHeader
= spdy_util_
.MakeSpdyHeader(SYN_STREAM
);
2421 scoped_ptr
<SpdyHeaderBlock
> headers(
2422 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2423 (*headers
)["user-agent"] = "";
2424 (*headers
)["accept-encoding"] = "gzip,deflate";
2425 scoped_ptr
<SpdyHeaderBlock
> headers2(
2426 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2427 (*headers2
)["user-agent"] = "";
2428 (*headers2
)["accept-encoding"] = "gzip,deflate";
2430 // Setup writes/reads to www.google.com
2431 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyFrame(
2432 kSynStartHeader
, headers
.Pass()));
2433 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyFrame(
2434 kSynStartHeader
, headers2
.Pass()));
2435 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReplyRedirect(1));
2436 MockWrite writes
[] = {
2437 CreateMockWrite(*req
, 1),
2439 MockRead reads
[] = {
2440 CreateMockRead(*resp
, 2),
2441 MockRead(ASYNC
, 0, 0, 3) // EOF
2444 // Setup writes/reads to www.foo.com
2445 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2446 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2447 MockWrite writes2
[] = {
2448 CreateMockWrite(*req2
, 1),
2450 MockRead reads2
[] = {
2451 CreateMockRead(*resp2
, 2),
2452 CreateMockRead(*body2
, 3),
2453 MockRead(ASYNC
, 0, 0, 4) // EOF
2455 OrderedSocketData
data(reads
, arraysize(reads
),
2456 writes
, arraysize(writes
));
2457 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2458 writes2
, arraysize(writes2
));
2460 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2461 HttpStreamFactory::set_force_spdy_over_ssl(false);
2462 HttpStreamFactory::set_force_spdy_always(true);
2465 SpdyURLRequestContext
spdy_url_request_context(GetParam().protocol
);
2467 GURL("http://www.google.com/"), &d
, &spdy_url_request_context
);
2468 spdy_url_request_context
.socket_factory().
2469 AddSocketDataProvider(&data
);
2470 spdy_url_request_context
.socket_factory().
2471 AddSocketDataProvider(&data2
);
2473 d
.set_quit_on_redirect(true);
2475 base::RunLoop().Run();
2477 EXPECT_EQ(1, d
.received_redirect_count());
2479 r
.FollowDeferredRedirect();
2480 base::RunLoop().Run();
2481 EXPECT_EQ(1, d
.response_started_count());
2482 EXPECT_FALSE(d
.received_data_before_response());
2483 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
.status().status());
2484 std::string
contents("hello!");
2485 EXPECT_EQ(contents
, d
.data_received());
2487 EXPECT_TRUE(data
.at_read_eof());
2488 EXPECT_TRUE(data
.at_write_eof());
2489 EXPECT_TRUE(data2
.at_read_eof());
2490 EXPECT_TRUE(data2
.at_write_eof());
2493 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2495 TEST_P(SpdyNetworkTransactionTest
, RedirectServerPush
) {
2496 const SpdyHeaderInfo kSynStartHeader
= spdy_util_
.MakeSpdyHeader(SYN_STREAM
);
2498 scoped_ptr
<SpdyHeaderBlock
> headers(
2499 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
2500 (*headers
)["user-agent"] = "";
2501 (*headers
)["accept-encoding"] = "gzip,deflate";
2503 // Setup writes/reads to www.google.com
2504 scoped_ptr
<SpdyFrame
> req(
2505 spdy_util_
.ConstructSpdyFrame(kSynStartHeader
, headers
.Pass()));
2506 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2507 scoped_ptr
<SpdyFrame
> rep(
2508 spdy_util_
.ConstructSpdyPush(NULL
,
2512 "http://www.google.com/foo.dat",
2513 "301 Moved Permanently",
2514 "http://www.foo.com/index.php"));
2515 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2516 scoped_ptr
<SpdyFrame
> rst(
2517 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
2518 MockWrite writes
[] = {
2519 CreateMockWrite(*req
, 1),
2520 CreateMockWrite(*rst
, 6),
2522 MockRead reads
[] = {
2523 CreateMockRead(*resp
, 2),
2524 CreateMockRead(*rep
, 3),
2525 CreateMockRead(*body
, 4),
2526 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2527 MockRead(ASYNC
, 0, 0, 7) // EOF
2530 // Setup writes/reads to www.foo.com
2531 scoped_ptr
<SpdyHeaderBlock
> headers2(
2532 spdy_util_
.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2533 (*headers2
)["user-agent"] = "";
2534 (*headers2
)["accept-encoding"] = "gzip,deflate";
2535 scoped_ptr
<SpdyFrame
> req2(
2536 spdy_util_
.ConstructSpdyFrame(kSynStartHeader
, headers2
.Pass()));
2537 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2538 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2539 MockWrite writes2
[] = {
2540 CreateMockWrite(*req2
, 1),
2542 MockRead reads2
[] = {
2543 CreateMockRead(*resp2
, 2),
2544 CreateMockRead(*body2
, 3),
2545 MockRead(ASYNC
, 0, 0, 5) // EOF
2547 OrderedSocketData
data(reads
, arraysize(reads
),
2548 writes
, arraysize(writes
));
2549 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2550 writes2
, arraysize(writes2
));
2552 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2553 HttpStreamFactory::set_force_spdy_over_ssl(false);
2554 HttpStreamFactory::set_force_spdy_always(true);
2557 SpdyURLRequestContext
spdy_url_request_context(GetParam().protocol
);
2560 GURL("http://www.google.com/"), &d
, &spdy_url_request_context
);
2561 spdy_url_request_context
.socket_factory().
2562 AddSocketDataProvider(&data
);
2565 base::RunLoop().Run();
2567 EXPECT_EQ(0, d
.received_redirect_count());
2568 std::string
contents("hello!");
2569 EXPECT_EQ(contents
, d
.data_received());
2572 GURL("http://www.google.com/foo.dat"), &d2
, &spdy_url_request_context
);
2573 spdy_url_request_context
.socket_factory().
2574 AddSocketDataProvider(&data2
);
2576 d2
.set_quit_on_redirect(true);
2578 base::RunLoop().Run();
2579 EXPECT_EQ(1, d2
.received_redirect_count());
2581 r2
.FollowDeferredRedirect();
2582 base::RunLoop().Run();
2583 EXPECT_EQ(1, d2
.response_started_count());
2584 EXPECT_FALSE(d2
.received_data_before_response());
2585 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
.status().status());
2586 std::string
contents2("hello!");
2587 EXPECT_EQ(contents2
, d2
.data_received());
2589 data
.CompleteRead();
2590 data2
.CompleteRead();
2591 EXPECT_TRUE(data
.at_read_eof());
2592 EXPECT_TRUE(data
.at_write_eof());
2593 EXPECT_TRUE(data2
.at_read_eof());
2594 EXPECT_TRUE(data2
.at_write_eof());
2597 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame
) {
2598 scoped_ptr
<SpdyFrame
> stream1_syn(
2599 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2600 scoped_ptr
<SpdyFrame
> stream1_body(
2601 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2602 MockWrite writes
[] = {
2603 CreateMockWrite(*stream1_syn
, 1),
2606 scoped_ptr
<SpdyFrame
>
2607 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2608 scoped_ptr
<SpdyFrame
>
2609 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2613 "http://www.google.com/foo.dat"));
2614 const char kPushedData
[] = "pushed";
2615 scoped_ptr
<SpdyFrame
> stream2_body(
2616 spdy_util_
.ConstructSpdyBodyFrame(
2617 2, kPushedData
, strlen(kPushedData
), true));
2618 MockRead reads
[] = {
2619 CreateMockRead(*stream1_reply
, 2),
2620 CreateMockRead(*stream2_syn
, 3),
2621 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2622 CreateMockRead(*stream2_body
, 5),
2623 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2626 HttpResponseInfo response
;
2627 HttpResponseInfo response2
;
2628 std::string
expected_push_result("pushed");
2629 OrderedSocketData
data(reads
, arraysize(reads
),
2630 writes
, arraysize(writes
));
2631 RunServerPushTest(&data
,
2634 expected_push_result
);
2636 // Verify the SYN_REPLY.
2637 EXPECT_TRUE(response
.headers
.get() != NULL
);
2638 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2640 // Verify the pushed stream.
2641 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2642 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2645 TEST_P(SpdyNetworkTransactionTest
, ServerPushBeforeSynReply
) {
2646 scoped_ptr
<SpdyFrame
> stream1_syn(
2647 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2648 scoped_ptr
<SpdyFrame
> stream1_body(
2649 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2650 MockWrite writes
[] = {
2651 CreateMockWrite(*stream1_syn
, 1),
2654 scoped_ptr
<SpdyFrame
>
2655 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2656 scoped_ptr
<SpdyFrame
>
2657 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2661 "http://www.google.com/foo.dat"));
2662 const char kPushedData
[] = "pushed";
2663 scoped_ptr
<SpdyFrame
> stream2_body(
2664 spdy_util_
.ConstructSpdyBodyFrame(
2665 2, kPushedData
, strlen(kPushedData
), true));
2666 MockRead reads
[] = {
2667 CreateMockRead(*stream2_syn
, 2),
2668 CreateMockRead(*stream1_reply
, 3),
2669 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
2670 CreateMockRead(*stream2_body
, 5),
2671 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2674 HttpResponseInfo response
;
2675 HttpResponseInfo response2
;
2676 std::string
expected_push_result("pushed");
2677 OrderedSocketData
data(reads
, arraysize(reads
),
2678 writes
, arraysize(writes
));
2679 RunServerPushTest(&data
,
2682 expected_push_result
);
2684 // Verify the SYN_REPLY.
2685 EXPECT_TRUE(response
.headers
.get() != NULL
);
2686 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2688 // Verify the pushed stream.
2689 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2690 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2693 TEST_P(SpdyNetworkTransactionTest
, ServerPushSingleDataFrame2
) {
2694 scoped_ptr
<SpdyFrame
> stream1_syn(
2695 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2696 MockWrite writes
[] = { CreateMockWrite(*stream1_syn
, 1), };
2698 scoped_ptr
<SpdyFrame
>
2699 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2700 scoped_ptr
<SpdyFrame
>
2701 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2705 "http://www.google.com/foo.dat"));
2706 const char kPushedData
[] = "pushed";
2707 scoped_ptr
<SpdyFrame
> stream2_body(
2708 spdy_util_
.ConstructSpdyBodyFrame(
2709 2, kPushedData
, strlen(kPushedData
), true));
2710 scoped_ptr
<SpdyFrame
>
2711 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2712 MockRead reads
[] = {
2713 CreateMockRead(*stream1_reply
, 2),
2714 CreateMockRead(*stream2_syn
, 3),
2715 CreateMockRead(*stream2_body
, 4),
2716 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2717 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2720 HttpResponseInfo response
;
2721 HttpResponseInfo response2
;
2722 std::string
expected_push_result("pushed");
2723 OrderedSocketData
data(reads
, arraysize(reads
),
2724 writes
, arraysize(writes
));
2725 RunServerPushTest(&data
,
2728 expected_push_result
);
2730 // Verify the SYN_REPLY.
2731 EXPECT_TRUE(response
.headers
.get() != NULL
);
2732 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2734 // Verify the pushed stream.
2735 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2736 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2739 TEST_P(SpdyNetworkTransactionTest
, ServerPushServerAborted
) {
2740 scoped_ptr
<SpdyFrame
> stream1_syn(
2741 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2742 scoped_ptr
<SpdyFrame
> stream1_body(
2743 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2744 MockWrite writes
[] = {
2745 CreateMockWrite(*stream1_syn
, 1),
2748 scoped_ptr
<SpdyFrame
>
2749 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2750 scoped_ptr
<SpdyFrame
>
2751 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2755 "http://www.google.com/foo.dat"));
2756 scoped_ptr
<SpdyFrame
> stream2_rst(
2757 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
2758 MockRead reads
[] = {
2759 CreateMockRead(*stream1_reply
, 2),
2760 CreateMockRead(*stream2_syn
, 3),
2761 CreateMockRead(*stream2_rst
, 4),
2762 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
2763 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2766 OrderedSocketData
data(reads
, arraysize(reads
),
2767 writes
, arraysize(writes
));
2768 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
2769 BoundNetLog(), GetParam(), NULL
);
2771 helper
.RunPreTestSetup();
2772 helper
.AddData(&data
);
2774 HttpNetworkTransaction
* trans
= helper
.trans();
2776 // Start the transaction with basic parameters.
2777 TestCompletionCallback callback
;
2778 int rv
= trans
->Start(
2779 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2780 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2781 rv
= callback
.WaitForResult();
2784 // Verify that we consumed all test data.
2785 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
2786 << data
.read_count()
2788 << data
.read_index();
2789 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
2790 << data
.write_count()
2792 << data
.write_index();
2794 // Verify the SYN_REPLY.
2795 HttpResponseInfo response
= *trans
->GetResponseInfo();
2796 EXPECT_TRUE(response
.headers
.get() != NULL
);
2797 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2800 // Verify that we don't leak streams and that we properly send a reset
2801 // if the server pushes the same stream twice.
2802 TEST_P(SpdyNetworkTransactionTest
, ServerPushDuplicate
) {
2803 scoped_ptr
<SpdyFrame
> stream1_syn(
2804 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2805 scoped_ptr
<SpdyFrame
> stream1_body(
2806 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2807 scoped_ptr
<SpdyFrame
> stream3_rst(
2808 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR
));
2809 MockWrite writes
[] = {
2810 CreateMockWrite(*stream1_syn
, 1),
2811 CreateMockWrite(*stream3_rst
, 5),
2814 scoped_ptr
<SpdyFrame
>
2815 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2816 scoped_ptr
<SpdyFrame
>
2817 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2821 "http://www.google.com/foo.dat"));
2822 const char kPushedData
[] = "pushed";
2823 scoped_ptr
<SpdyFrame
> stream2_body(
2824 spdy_util_
.ConstructSpdyBodyFrame(
2825 2, kPushedData
, strlen(kPushedData
), true));
2826 scoped_ptr
<SpdyFrame
>
2827 stream3_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2831 "http://www.google.com/foo.dat"));
2832 MockRead reads
[] = {
2833 CreateMockRead(*stream1_reply
, 2),
2834 CreateMockRead(*stream2_syn
, 3),
2835 CreateMockRead(*stream3_syn
, 4),
2836 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
2837 CreateMockRead(*stream2_body
, 7),
2838 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
2841 HttpResponseInfo response
;
2842 HttpResponseInfo response2
;
2843 std::string
expected_push_result("pushed");
2844 OrderedSocketData
data(reads
, arraysize(reads
),
2845 writes
, arraysize(writes
));
2846 RunServerPushTest(&data
,
2849 expected_push_result
);
2851 // Verify the SYN_REPLY.
2852 EXPECT_TRUE(response
.headers
.get() != NULL
);
2853 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2855 // Verify the pushed stream.
2856 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2857 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2860 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrame
) {
2861 scoped_ptr
<SpdyFrame
> stream1_syn(
2862 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2863 scoped_ptr
<SpdyFrame
> stream1_body(
2864 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2865 MockWrite writes
[] = {
2866 CreateMockWrite(*stream1_syn
, 1),
2869 scoped_ptr
<SpdyFrame
>
2870 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2871 scoped_ptr
<SpdyFrame
>
2872 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2876 "http://www.google.com/foo.dat"));
2877 static const char kPushedData
[] = "pushed my darling hello my baby";
2878 scoped_ptr
<SpdyFrame
> stream2_body_base(
2879 spdy_util_
.ConstructSpdyBodyFrame(
2880 2, kPushedData
, strlen(kPushedData
), true));
2881 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2882 scoped_ptr
<SpdyFrame
> stream2_body1(
2883 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2884 scoped_ptr
<SpdyFrame
> stream2_body2(
2885 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2886 scoped_ptr
<SpdyFrame
> stream2_body3(
2887 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2888 kChunkSize
, false));
2889 scoped_ptr
<SpdyFrame
> stream2_body4(
2890 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2891 stream2_body_base
->size() - 3 * kChunkSize
, false));
2892 MockRead reads
[] = {
2893 CreateMockRead(*stream1_reply
, 2),
2894 CreateMockRead(*stream2_syn
, 3),
2895 CreateMockRead(*stream2_body1
, 4),
2896 CreateMockRead(*stream2_body2
, 5),
2897 CreateMockRead(*stream2_body3
, 6),
2898 CreateMockRead(*stream2_body4
, 7),
2899 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
2900 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
2903 HttpResponseInfo response
;
2904 HttpResponseInfo response2
;
2905 std::string
expected_push_result("pushed my darling hello my baby");
2906 OrderedSocketData
data(reads
, arraysize(reads
),
2907 writes
, arraysize(writes
));
2908 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2910 // Verify the SYN_REPLY.
2911 EXPECT_TRUE(response
.headers
.get() != NULL
);
2912 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2914 // Verify the pushed stream.
2915 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2916 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2919 TEST_P(SpdyNetworkTransactionTest
, ServerPushMultipleDataFrameInterrupted
) {
2920 scoped_ptr
<SpdyFrame
> stream1_syn(
2921 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2922 scoped_ptr
<SpdyFrame
> stream1_body(
2923 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2924 MockWrite writes
[] = {
2925 CreateMockWrite(*stream1_syn
, 1),
2928 scoped_ptr
<SpdyFrame
>
2929 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2930 scoped_ptr
<SpdyFrame
>
2931 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2935 "http://www.google.com/foo.dat"));
2936 static const char kPushedData
[] = "pushed my darling hello my baby";
2937 scoped_ptr
<SpdyFrame
> stream2_body_base(
2938 spdy_util_
.ConstructSpdyBodyFrame(
2939 2, kPushedData
, strlen(kPushedData
), true));
2940 const size_t kChunkSize
= strlen(kPushedData
) / 4;
2941 scoped_ptr
<SpdyFrame
> stream2_body1(
2942 new SpdyFrame(stream2_body_base
->data(), kChunkSize
, false));
2943 scoped_ptr
<SpdyFrame
> stream2_body2(
2944 new SpdyFrame(stream2_body_base
->data() + kChunkSize
, kChunkSize
, false));
2945 scoped_ptr
<SpdyFrame
> stream2_body3(
2946 new SpdyFrame(stream2_body_base
->data() + 2 * kChunkSize
,
2947 kChunkSize
, false));
2948 scoped_ptr
<SpdyFrame
> stream2_body4(
2949 new SpdyFrame(stream2_body_base
->data() + 3 * kChunkSize
,
2950 stream2_body_base
->size() - 3 * kChunkSize
, false));
2951 MockRead reads
[] = {
2952 CreateMockRead(*stream1_reply
, 2),
2953 CreateMockRead(*stream2_syn
, 3),
2954 CreateMockRead(*stream2_body1
, 4),
2955 CreateMockRead(*stream2_body2
, 5),
2956 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
2957 CreateMockRead(*stream2_body3
, 7),
2958 CreateMockRead(*stream2_body4
, 8),
2959 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
2960 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
2963 HttpResponseInfo response
;
2964 HttpResponseInfo response2
;
2965 OrderedSocketData
data(reads
, arraysize(reads
),
2966 writes
, arraysize(writes
));
2967 RunServerPushTest(&data
, &response
, &response2
, kPushedData
);
2969 // Verify the SYN_REPLY.
2970 EXPECT_TRUE(response
.headers
.get() != NULL
);
2971 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
2973 // Verify the pushed stream.
2974 EXPECT_TRUE(response2
.headers
.get() != NULL
);
2975 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
2978 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID0
) {
2979 scoped_ptr
<SpdyFrame
> stream1_syn(
2980 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2981 scoped_ptr
<SpdyFrame
> stream1_body(
2982 spdy_util_
.ConstructSpdyBodyFrame(1, true));
2983 scoped_ptr
<SpdyFrame
> stream2_rst(
2984 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
2985 MockWrite writes
[] = {
2986 CreateMockWrite(*stream1_syn
, 1),
2987 CreateMockWrite(*stream2_rst
, 4),
2990 scoped_ptr
<SpdyFrame
>
2991 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2992 scoped_ptr
<SpdyFrame
>
2993 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
2997 "http://www.google.com/foo.dat"));
2998 MockRead reads
[] = {
2999 CreateMockRead(*stream1_reply
, 2),
3000 CreateMockRead(*stream2_syn
, 3),
3001 CreateMockRead(*stream1_body
, 4),
3002 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3005 OrderedSocketData
data(reads
, arraysize(reads
),
3006 writes
, arraysize(writes
));
3007 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3008 BoundNetLog(), GetParam(), NULL
);
3010 helper
.RunPreTestSetup();
3011 helper
.AddData(&data
);
3013 HttpNetworkTransaction
* trans
= helper
.trans();
3015 // Start the transaction with basic parameters.
3016 TestCompletionCallback callback
;
3017 int rv
= trans
->Start(
3018 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3019 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3020 rv
= callback
.WaitForResult();
3023 // Verify that we consumed all test data.
3024 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3025 << data
.read_count()
3027 << data
.read_index();
3028 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3029 << data
.write_count()
3031 << data
.write_index();
3033 // Verify the SYN_REPLY.
3034 HttpResponseInfo response
= *trans
->GetResponseInfo();
3035 EXPECT_TRUE(response
.headers
.get() != NULL
);
3036 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3039 TEST_P(SpdyNetworkTransactionTest
, ServerPushInvalidAssociatedStreamID9
) {
3040 scoped_ptr
<SpdyFrame
> stream1_syn(
3041 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3042 scoped_ptr
<SpdyFrame
> stream1_body(
3043 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3044 scoped_ptr
<SpdyFrame
> stream2_rst(
3045 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM
));
3046 MockWrite writes
[] = {
3047 CreateMockWrite(*stream1_syn
, 1),
3048 CreateMockWrite(*stream2_rst
, 4),
3051 scoped_ptr
<SpdyFrame
>
3052 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3053 scoped_ptr
<SpdyFrame
>
3054 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
3058 "http://www.google.com/foo.dat"));
3059 MockRead reads
[] = {
3060 CreateMockRead(*stream1_reply
, 2),
3061 CreateMockRead(*stream2_syn
, 3),
3062 CreateMockRead(*stream1_body
, 4),
3063 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3066 OrderedSocketData
data(reads
, arraysize(reads
),
3067 writes
, arraysize(writes
));
3068 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3069 BoundNetLog(), GetParam(), NULL
);
3071 helper
.RunPreTestSetup();
3072 helper
.AddData(&data
);
3074 HttpNetworkTransaction
* trans
= helper
.trans();
3076 // Start the transaction with basic parameters.
3077 TestCompletionCallback callback
;
3078 int rv
= trans
->Start(
3079 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3080 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3081 rv
= callback
.WaitForResult();
3084 // Verify that we consumed all test data.
3085 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3086 << data
.read_count()
3088 << data
.read_index();
3089 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3090 << data
.write_count()
3092 << data
.write_index();
3094 // Verify the SYN_REPLY.
3095 HttpResponseInfo response
= *trans
->GetResponseInfo();
3096 EXPECT_TRUE(response
.headers
.get() != NULL
);
3097 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3100 TEST_P(SpdyNetworkTransactionTest
, ServerPushNoURL
) {
3101 scoped_ptr
<SpdyFrame
> stream1_syn(
3102 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3103 scoped_ptr
<SpdyFrame
> stream1_body(
3104 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3105 scoped_ptr
<SpdyFrame
> stream2_rst(
3106 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR
));
3107 MockWrite writes
[] = {
3108 CreateMockWrite(*stream1_syn
, 1),
3109 CreateMockWrite(*stream2_rst
, 4),
3112 scoped_ptr
<SpdyFrame
>
3113 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3114 scoped_ptr
<SpdyHeaderBlock
> incomplete_headers(new SpdyHeaderBlock());
3115 (*incomplete_headers
)["hello"] = "bye";
3116 (*incomplete_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
3117 (*incomplete_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
3118 scoped_ptr
<SpdyFrame
> stream2_syn(
3119 spdy_util_
.ConstructSpdyControlFrame(incomplete_headers
.Pass(),
3125 // Associated stream ID
3127 MockRead reads
[] = {
3128 CreateMockRead(*stream1_reply
, 2),
3129 CreateMockRead(*stream2_syn
, 3),
3130 CreateMockRead(*stream1_body
, 4),
3131 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3134 OrderedSocketData
data(reads
, arraysize(reads
),
3135 writes
, arraysize(writes
));
3136 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3137 BoundNetLog(), GetParam(), NULL
);
3139 helper
.RunPreTestSetup();
3140 helper
.AddData(&data
);
3142 HttpNetworkTransaction
* trans
= helper
.trans();
3144 // Start the transaction with basic parameters.
3145 TestCompletionCallback callback
;
3146 int rv
= trans
->Start(
3147 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3148 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3149 rv
= callback
.WaitForResult();
3151 // Verify that we consumed all test data.
3152 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3153 << data
.read_count()
3155 << data
.read_index();
3156 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3157 << data
.write_count()
3159 << data
.write_index();
3161 // Verify the SYN_REPLY.
3162 HttpResponseInfo response
= *trans
->GetResponseInfo();
3163 EXPECT_TRUE(response
.headers
.get() != NULL
);
3164 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3167 // Verify that various SynReply headers parse correctly through the
3169 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeaders
) {
3170 struct SynReplyHeadersTests
{
3172 const char* extra_headers
[5];
3173 SpdyHeaderBlock expected_headers
;
3175 // This uses a multi-valued cookie header.
3178 "cookie", "val2", // will get appended separated by NULL
3182 // This is the minimalist set of headers.
3186 // Headers with a comma separated list.
3188 { "cookie", "val1,val2",
3194 test_cases
[0].expected_headers
["cookie"] = "val1";
3195 test_cases
[0].expected_headers
["cookie"] += '\0';
3196 test_cases
[0].expected_headers
["cookie"] += "val2";
3197 test_cases
[0].expected_headers
["hello"] = "bye";
3198 test_cases
[0].expected_headers
["status"] = "200";
3199 test_cases
[0].expected_headers
["version"] = "HTTP/1.1";
3201 test_cases
[1].expected_headers
["hello"] = "bye";
3202 test_cases
[1].expected_headers
["status"] = "200";
3203 test_cases
[1].expected_headers
["version"] = "HTTP/1.1";
3205 test_cases
[2].expected_headers
["cookie"] = "val1,val2";
3206 test_cases
[2].expected_headers
["hello"] = "bye";
3207 test_cases
[2].expected_headers
["status"] = "200";
3208 test_cases
[2].expected_headers
["version"] = "HTTP/1.1";
3210 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3211 scoped_ptr
<SpdyFrame
> req(
3212 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3213 MockWrite writes
[] = { CreateMockWrite(*req
) };
3215 scoped_ptr
<SpdyFrame
> resp(
3216 spdy_util_
.ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3217 test_cases
[i
].num_headers
,
3219 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3220 MockRead reads
[] = {
3221 CreateMockRead(*resp
),
3222 CreateMockRead(*body
),
3223 MockRead(ASYNC
, 0, 0) // EOF
3226 DelayedSocketData
data(1, reads
, arraysize(reads
),
3227 writes
, arraysize(writes
));
3228 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3229 BoundNetLog(), GetParam(), NULL
);
3230 helper
.RunToCompletion(&data
);
3231 TransactionHelperResult out
= helper
.output();
3233 EXPECT_EQ(OK
, out
.rv
);
3234 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3235 EXPECT_EQ("hello!", out
.response_data
);
3237 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3238 EXPECT_TRUE(headers
.get() != NULL
);
3240 std::string name
, value
;
3241 SpdyHeaderBlock header_block
;
3242 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3243 if (header_block
[name
].empty()) {
3244 header_block
[name
] = value
;
3246 header_block
[name
] += '\0';
3247 header_block
[name
] += value
;
3250 EXPECT_EQ(test_cases
[i
].expected_headers
, header_block
);
3254 // Verify that various SynReply headers parse vary fields correctly
3255 // through the HTTP layer, and the response matches the request.
3256 TEST_P(SpdyNetworkTransactionTest
, SynReplyHeadersVary
) {
3257 static const SpdyHeaderInfo syn_reply_info
= {
3258 SYN_REPLY
, // Syn Reply
3260 0, // Associated Stream ID
3261 ConvertRequestPriorityToSpdyPriority(
3262 LOWEST
, spdy_util_
.spdy_version()),
3263 kSpdyCredentialSlotUnused
,
3264 CONTROL_FLAG_NONE
, // Control Flags
3265 false, // Compressed
3266 RST_STREAM_INVALID
, // Status
3269 DATA_FLAG_NONE
// Data Flags
3271 // Modify the following data to change/add test cases:
3272 struct SynReplyTests
{
3273 const SpdyHeaderInfo
* syn_reply
;
3276 const char* extra_headers
[2][16];
3278 // Test the case of a multi-valued cookie. When the value is delimited
3279 // with NUL characters, it needs to be unfolded into multiple headers.
3284 { { "cookie", "val1,val2",
3288 spdy_util_
.GetStatusKey(), "200",
3289 spdy_util_
.GetPathKey(), "/index.php",
3290 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3294 }, { // Multiple vary fields.
3298 { { "friend", "barney",
3299 "enemy", "snaggletooth",
3304 spdy_util_
.GetStatusKey(), "200",
3305 spdy_util_
.GetPathKey(), "/index.php",
3306 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3310 }, { // Test a '*' vary field.
3314 { { "cookie", "val1,val2",
3318 spdy_util_
.GetStatusKey(), "200",
3319 spdy_util_
.GetPathKey(), "/index.php",
3320 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3324 }, { // Multiple comma-separated vary fields.
3328 { { "friend", "barney",
3329 "enemy", "snaggletooth",
3332 { "vary", "friend,enemy",
3333 spdy_util_
.GetStatusKey(), "200",
3334 spdy_util_
.GetPathKey(), "/index.php",
3335 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3342 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3343 // Construct the request.
3344 scoped_ptr
<SpdyFrame
> frame_req(
3345 spdy_util_
.ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3346 test_cases
[i
].num_headers
[0],
3347 false, 1, LOWEST
, true));
3349 MockWrite writes
[] = {
3350 CreateMockWrite(*frame_req
),
3353 // Construct the reply.
3354 scoped_ptr
<SpdyFrame
> frame_reply(
3355 spdy_util_
.ConstructSpdyFrame(*test_cases
[i
].syn_reply
,
3356 test_cases
[i
].extra_headers
[1],
3357 test_cases
[i
].num_headers
[1],
3361 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3362 MockRead reads
[] = {
3363 CreateMockRead(*frame_reply
),
3364 CreateMockRead(*body
),
3365 MockRead(ASYNC
, 0, 0) // EOF
3368 // Attach the headers to the request.
3369 int header_count
= test_cases
[i
].num_headers
[0];
3371 HttpRequestInfo request
= CreateGetRequest();
3372 for (int ct
= 0; ct
< header_count
; ct
++) {
3373 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3374 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3375 request
.extra_headers
.SetHeader(header_key
, header_value
);
3378 DelayedSocketData
data(1, reads
, arraysize(reads
),
3379 writes
, arraysize(writes
));
3380 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
3381 BoundNetLog(), GetParam(), NULL
);
3382 helper
.RunToCompletion(&data
);
3383 TransactionHelperResult out
= helper
.output();
3385 EXPECT_EQ(OK
, out
.rv
) << i
;
3386 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3387 EXPECT_EQ("hello!", out
.response_data
) << i
;
3389 // Test the response information.
3390 EXPECT_TRUE(out
.response_info
.response_time
>
3391 out
.response_info
.request_time
) << i
;
3392 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3393 out
.response_info
.request_time
;
3394 base::TimeDelta min_expected_delay
;
3395 min_expected_delay
.FromMilliseconds(10);
3396 EXPECT_GT(test_delay
.InMillisecondsF(),
3397 min_expected_delay
.InMillisecondsF()) << i
;
3398 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3399 test_cases
[i
].vary_matches
) << i
;
3401 // Check the headers.
3402 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3403 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3405 std::string name
, value
, lines
;
3406 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3409 lines
.append(value
);
3413 // Construct the expected header reply string.
3414 SpdyHeaderBlock reply_headers
;
3415 AppendToHeaderBlock(test_cases
[i
].extra_headers
[1],
3416 test_cases
[i
].num_headers
[1],
3418 std::string expected_reply
=
3419 spdy_util_
.ConstructSpdyReplyString(reply_headers
);
3420 EXPECT_EQ(expected_reply
, lines
) << i
;
3424 // Verify that we don't crash on invalid SynReply responses.
3425 TEST_P(SpdyNetworkTransactionTest
, InvalidSynReply
) {
3426 const SpdyHeaderInfo kSynStartHeader
= {
3427 SYN_REPLY
, // Kind = SynReply
3429 0, // Associated stream ID
3430 ConvertRequestPriorityToSpdyPriority(
3431 LOWEST
, spdy_util_
.spdy_version()),
3432 kSpdyCredentialSlotUnused
,
3433 CONTROL_FLAG_NONE
, // Control Flags
3434 false, // Compressed
3435 RST_STREAM_INVALID
, // Status
3438 DATA_FLAG_NONE
// Data Flags
3441 struct InvalidSynReplyTests
{
3443 const char* headers
[10];
3445 // SYN_REPLY missing status header
3449 spdy_util_
.GetPathKey(), "/index.php",
3450 spdy_util_
.GetVersionKey(), "HTTP/1.1",
3454 // SYN_REPLY missing version header
3457 spdy_util_
.GetPathKey(), "/index.php",
3461 // SYN_REPLY with no headers
3465 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3466 scoped_ptr
<SpdyFrame
> req(
3467 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3468 scoped_ptr
<SpdyFrame
> rst(
3469 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3470 MockWrite writes
[] = {
3471 CreateMockWrite(*req
),
3472 CreateMockWrite(*rst
),
3475 scoped_ptr
<SpdyFrame
> resp(
3476 spdy_util_
.ConstructSpdyFrame(kSynStartHeader
,
3478 test_cases
[i
].headers
,
3479 test_cases
[i
].num_headers
));
3480 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3481 MockRead reads
[] = {
3482 CreateMockRead(*resp
),
3483 MockRead(ASYNC
, 0, 0) // EOF
3486 DelayedSocketData
data(1, reads
, arraysize(reads
),
3487 writes
, arraysize(writes
));
3488 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3489 BoundNetLog(), GetParam(), NULL
);
3490 helper
.RunToCompletion(&data
);
3491 TransactionHelperResult out
= helper
.output();
3492 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3496 // Verify that we don't crash on some corrupt frames.
3497 TEST_P(SpdyNetworkTransactionTest
, CorruptFrameSessionError
) {
3498 // This is the length field that's too short.
3499 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
3500 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3501 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3503 (spdy_util_
.spdy_version() < SPDY4
) ?
3504 syn_reply_wrong_length
->size() - framer
.GetControlFrameHeaderSize() :
3505 syn_reply_wrong_length
->size();
3506 size_t wrong_size
= right_size
- 4;
3507 test::SetFrameLength(syn_reply_wrong_length
.get(),
3509 spdy_util_
.spdy_version());
3511 struct SynReplyTests
{
3512 const SpdyFrame
* syn_reply
;
3514 { syn_reply_wrong_length
.get(), },
3517 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3518 scoped_ptr
<SpdyFrame
> req(
3519 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3520 scoped_ptr
<SpdyFrame
> rst(
3521 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3522 MockWrite writes
[] = {
3523 CreateMockWrite(*req
),
3524 CreateMockWrite(*rst
),
3527 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3528 MockRead reads
[] = {
3529 MockRead(ASYNC
, test_cases
[i
].syn_reply
->data(), wrong_size
),
3530 CreateMockRead(*body
),
3531 MockRead(ASYNC
, 0, 0) // EOF
3534 DelayedSocketData
data(1, reads
, arraysize(reads
),
3535 writes
, arraysize(writes
));
3536 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3537 BoundNetLog(), GetParam(), NULL
);
3538 helper
.RunToCompletion(&data
);
3539 TransactionHelperResult out
= helper
.output();
3540 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3544 // Test that we shutdown correctly on write errors.
3545 TEST_P(SpdyNetworkTransactionTest
, WriteError
) {
3546 scoped_ptr
<SpdyFrame
> req(
3547 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3548 MockWrite writes
[] = {
3549 // We'll write 10 bytes successfully
3550 MockWrite(ASYNC
, req
->data(), 10),
3551 // Followed by ERROR!
3552 MockWrite(ASYNC
, ERR_FAILED
),
3555 DelayedSocketData
data(2, NULL
, 0,
3556 writes
, arraysize(writes
));
3557 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3558 BoundNetLog(), GetParam(), NULL
);
3559 helper
.RunToCompletion(&data
);
3560 TransactionHelperResult out
= helper
.output();
3561 EXPECT_EQ(ERR_FAILED
, out
.rv
);
3565 // Test that partial writes work.
3566 TEST_P(SpdyNetworkTransactionTest
, PartialWrite
) {
3567 // Chop the SYN_STREAM frame into 5 chunks.
3568 scoped_ptr
<SpdyFrame
> req(
3569 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3570 const int kChunks
= 5;
3571 scoped_ptr
<MockWrite
[]> writes(ChopWriteFrame(*req
.get(), kChunks
));
3573 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3574 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3575 MockRead reads
[] = {
3576 CreateMockRead(*resp
),
3577 CreateMockRead(*body
),
3578 MockRead(ASYNC
, 0, 0) // EOF
3581 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
3582 writes
.get(), kChunks
);
3583 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3584 BoundNetLog(), GetParam(), NULL
);
3585 helper
.RunToCompletion(&data
);
3586 TransactionHelperResult out
= helper
.output();
3587 EXPECT_EQ(OK
, out
.rv
);
3588 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3589 EXPECT_EQ("hello!", out
.response_data
);
3592 // In this test, we enable compression, but get a uncompressed SynReply from
3593 // the server. Verify that teardown is all clean.
3594 TEST_P(SpdyNetworkTransactionTest
, DecompressFailureOnSynReply
) {
3595 scoped_ptr
<SpdyFrame
> compressed(
3596 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
, true));
3597 scoped_ptr
<SpdyFrame
> rst(
3598 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
3599 MockWrite writes
[] = {
3600 CreateMockWrite(*compressed
),
3603 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3604 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3605 MockRead reads
[] = {
3606 CreateMockRead(*resp
),
3609 DelayedSocketData
data(1, reads
, arraysize(reads
),
3610 writes
, arraysize(writes
));
3611 SpdySessionDependencies
* session_deps
=
3612 CreateSpdySessionDependencies(GetParam());
3613 session_deps
->enable_compression
= true;
3614 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3615 BoundNetLog(), GetParam(), session_deps
);
3616 helper
.RunToCompletion(&data
);
3617 TransactionHelperResult out
= helper
.output();
3618 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
3622 // Test that the NetLog contains good data for a simple GET request.
3623 TEST_P(SpdyNetworkTransactionTest
, NetLog
) {
3624 static const char* const kExtraHeaders
[] = {
3625 "user-agent", "Chrome",
3627 scoped_ptr
<SpdyFrame
> req(
3628 spdy_util_
.ConstructSpdyGet(kExtraHeaders
, 1, false, 1, LOWEST
, true));
3629 MockWrite writes
[] = { CreateMockWrite(*req
) };
3631 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3632 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3633 MockRead reads
[] = {
3634 CreateMockRead(*resp
),
3635 CreateMockRead(*body
),
3636 MockRead(ASYNC
, 0, 0) // EOF
3639 CapturingBoundNetLog log
;
3641 DelayedSocketData
data(1, reads
, arraysize(reads
),
3642 writes
, arraysize(writes
));
3643 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
3645 log
.bound(), GetParam(), NULL
);
3646 helper
.RunToCompletion(&data
);
3647 TransactionHelperResult out
= helper
.output();
3648 EXPECT_EQ(OK
, out
.rv
);
3649 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3650 EXPECT_EQ("hello!", out
.response_data
);
3652 // Check that the NetLog was filled reasonably.
3653 // This test is intentionally non-specific about the exact ordering of the
3654 // log; instead we just check to make sure that certain events exist, and that
3655 // they are in the right order.
3656 net::CapturingNetLog::CapturedEntryList entries
;
3657 log
.GetEntries(&entries
);
3659 EXPECT_LT(0u, entries
.size());
3661 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
3662 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3663 net::NetLog::PHASE_BEGIN
);
3664 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3665 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
3666 net::NetLog::PHASE_END
);
3667 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3668 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3669 net::NetLog::PHASE_BEGIN
);
3670 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3671 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
3672 net::NetLog::PHASE_END
);
3673 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3674 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3675 net::NetLog::PHASE_BEGIN
);
3676 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
3677 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
3678 net::NetLog::PHASE_END
);
3680 // Check that we logged all the headers correctly
3681 pos
= net::ExpectLogContainsSomewhere(
3683 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
3684 net::NetLog::PHASE_NONE
);
3686 base::ListValue
* header_list
;
3687 ASSERT_TRUE(entries
[pos
].params
.get());
3688 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
3690 std::vector
<std::string
> expected
;
3691 expected
.push_back(std::string(spdy_util_
.GetHostKey()) + ": www.google.com");
3692 expected
.push_back(std::string(spdy_util_
.GetPathKey()) + ": /");
3693 expected
.push_back(std::string(spdy_util_
.GetSchemeKey()) + ": http");
3694 expected
.push_back(std::string(spdy_util_
.GetVersionKey()) + ": HTTP/1.1");
3695 expected
.push_back(std::string(spdy_util_
.GetMethodKey()) + ": GET");
3696 expected
.push_back("user-agent: Chrome");
3697 EXPECT_EQ(expected
.size(), header_list
->GetSize());
3698 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
3699 it
!= expected
.end();
3701 base::StringValue
header(*it
);
3702 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
3703 "Header not found: " << *it
;
3707 // Since we buffer the IO from the stream to the renderer, this test verifies
3708 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3709 // on the network, but issued a Read for only 5 of those bytes) that the data
3710 // flow still works correctly.
3711 TEST_P(SpdyNetworkTransactionTest
, BufferFull
) {
3712 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3714 scoped_ptr
<SpdyFrame
> req(
3715 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3716 MockWrite writes
[] = { CreateMockWrite(*req
) };
3718 // 2 data frames in a single read.
3719 scoped_ptr
<SpdyFrame
> data_frame_1(
3720 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
3721 scoped_ptr
<SpdyFrame
> data_frame_2(
3722 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
3723 const SpdyFrame
* data_frames
[2] = {
3727 char combined_data_frames
[100];
3728 int combined_data_frames_len
=
3729 CombineFrames(data_frames
, arraysize(data_frames
),
3730 combined_data_frames
, arraysize(combined_data_frames
));
3731 scoped_ptr
<SpdyFrame
> last_frame(
3732 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
3734 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3735 MockRead reads
[] = {
3736 CreateMockRead(*resp
),
3737 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3738 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3739 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3740 CreateMockRead(*last_frame
),
3741 MockRead(ASYNC
, 0, 0) // EOF
3744 DelayedSocketData
data(1, reads
, arraysize(reads
),
3745 writes
, arraysize(writes
));
3747 TestCompletionCallback callback
;
3749 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3750 BoundNetLog(), GetParam(), NULL
);
3751 helper
.RunPreTestSetup();
3752 helper
.AddData(&data
);
3753 HttpNetworkTransaction
* trans
= helper
.trans();
3754 int rv
= trans
->Start(
3755 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3758 TransactionHelperResult out
= helper
.output();
3759 out
.rv
= callback
.WaitForResult();
3760 EXPECT_EQ(out
.rv
, OK
);
3762 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3763 EXPECT_TRUE(response
->headers
.get() != NULL
);
3764 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3765 out
.status_line
= response
->headers
->GetStatusLine();
3766 out
.response_info
= *response
; // Make a copy so we can verify.
3769 TestCompletionCallback read_callback
;
3771 std::string content
;
3773 // Read small chunks at a time.
3774 const int kSmallReadSize
= 3;
3775 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3776 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3777 if (rv
== net::ERR_IO_PENDING
) {
3778 data
.CompleteRead();
3779 rv
= read_callback
.WaitForResult();
3782 content
.append(buf
->data(), rv
);
3783 } else if (rv
< 0) {
3788 out
.response_data
.swap(content
);
3790 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3791 // MockClientSocketFactory) are still alive.
3792 base::RunLoop().RunUntilIdle();
3794 // Verify that we consumed all test data.
3795 helper
.VerifyDataConsumed();
3797 EXPECT_EQ(OK
, out
.rv
);
3798 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3799 EXPECT_EQ("goodbye world", out
.response_data
);
3802 // Verify that basic buffering works; when multiple data frames arrive
3803 // at the same time, ensure that we don't notify a read completion for
3804 // each data frame individually.
3805 TEST_P(SpdyNetworkTransactionTest
, Buffering
) {
3806 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3808 scoped_ptr
<SpdyFrame
> req(
3809 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3810 MockWrite writes
[] = { CreateMockWrite(*req
) };
3812 // 4 data frames in a single read.
3813 scoped_ptr
<SpdyFrame
> data_frame(
3814 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3815 scoped_ptr
<SpdyFrame
> data_frame_fin(
3816 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3817 const SpdyFrame
* data_frames
[4] = {
3821 data_frame_fin
.get()
3823 char combined_data_frames
[100];
3824 int combined_data_frames_len
=
3825 CombineFrames(data_frames
, arraysize(data_frames
),
3826 combined_data_frames
, arraysize(combined_data_frames
));
3828 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3829 MockRead reads
[] = {
3830 CreateMockRead(*resp
),
3831 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
3832 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
3833 MockRead(ASYNC
, 0, 0) // EOF
3836 DelayedSocketData
data(1, reads
, arraysize(reads
),
3837 writes
, arraysize(writes
));
3839 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3840 BoundNetLog(), GetParam(), NULL
);
3841 helper
.RunPreTestSetup();
3842 helper
.AddData(&data
);
3843 HttpNetworkTransaction
* trans
= helper
.trans();
3845 TestCompletionCallback callback
;
3846 int rv
= trans
->Start(
3847 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3848 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3850 TransactionHelperResult out
= helper
.output();
3851 out
.rv
= callback
.WaitForResult();
3852 EXPECT_EQ(out
.rv
, OK
);
3854 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3855 EXPECT_TRUE(response
->headers
.get() != NULL
);
3856 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3857 out
.status_line
= response
->headers
->GetStatusLine();
3858 out
.response_info
= *response
; // Make a copy so we can verify.
3861 TestCompletionCallback read_callback
;
3863 std::string content
;
3864 int reads_completed
= 0;
3866 // Read small chunks at a time.
3867 const int kSmallReadSize
= 14;
3868 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3869 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3870 if (rv
== net::ERR_IO_PENDING
) {
3871 data
.CompleteRead();
3872 rv
= read_callback
.WaitForResult();
3875 EXPECT_EQ(kSmallReadSize
, rv
);
3876 content
.append(buf
->data(), rv
);
3877 } else if (rv
< 0) {
3878 FAIL() << "Unexpected read error: " << rv
;
3883 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
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("messagemessagemessagemessage", out
.response_data
);
3899 // Verify the case where we buffer data but read it after it has been buffered.
3900 TEST_P(SpdyNetworkTransactionTest
, BufferedAll
) {
3901 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3903 scoped_ptr
<SpdyFrame
> req(
3904 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3905 MockWrite writes
[] = { CreateMockWrite(*req
) };
3907 // 5 data frames in a single read.
3908 scoped_ptr
<SpdyFrame
> syn_reply(
3909 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3911 test::SetFrameFlags(
3912 syn_reply
.get(), CONTROL_FLAG_NONE
, spdy_util_
.spdy_version());
3913 scoped_ptr
<SpdyFrame
> data_frame(
3914 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
3915 scoped_ptr
<SpdyFrame
> data_frame_fin(
3916 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
3917 const SpdyFrame
* frames
[5] = {
3922 data_frame_fin
.get()
3924 char combined_frames
[200];
3925 int combined_frames_len
=
3926 CombineFrames(frames
, arraysize(frames
),
3927 combined_frames
, arraysize(combined_frames
));
3929 MockRead reads
[] = {
3930 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
3931 MockRead(ASYNC
, 0, 0) // EOF
3934 DelayedSocketData
data(1, reads
, arraysize(reads
),
3935 writes
, arraysize(writes
));
3937 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
3938 BoundNetLog(), GetParam(), NULL
);
3939 helper
.RunPreTestSetup();
3940 helper
.AddData(&data
);
3941 HttpNetworkTransaction
* trans
= helper
.trans();
3943 TestCompletionCallback callback
;
3944 int rv
= trans
->Start(
3945 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3948 TransactionHelperResult out
= helper
.output();
3949 out
.rv
= callback
.WaitForResult();
3950 EXPECT_EQ(out
.rv
, OK
);
3952 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3953 EXPECT_TRUE(response
->headers
.get() != NULL
);
3954 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3955 out
.status_line
= response
->headers
->GetStatusLine();
3956 out
.response_info
= *response
; // Make a copy so we can verify.
3959 TestCompletionCallback read_callback
;
3961 std::string content
;
3962 int reads_completed
= 0;
3964 // Read small chunks at a time.
3965 const int kSmallReadSize
= 14;
3966 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
3967 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
3969 EXPECT_EQ(kSmallReadSize
, rv
);
3970 content
.append(buf
->data(), rv
);
3971 } else if (rv
< 0) {
3972 FAIL() << "Unexpected read error: " << rv
;
3977 EXPECT_EQ(3, reads_completed
);
3979 out
.response_data
.swap(content
);
3981 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3982 // MockClientSocketFactory) are still alive.
3983 base::RunLoop().RunUntilIdle();
3985 // Verify that we consumed all test data.
3986 helper
.VerifyDataConsumed();
3988 EXPECT_EQ(OK
, out
.rv
);
3989 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3990 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
3993 // Verify the case where we buffer data and close the connection.
3994 TEST_P(SpdyNetworkTransactionTest
, BufferedClosed
) {
3995 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3997 scoped_ptr
<SpdyFrame
> req(
3998 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3999 MockWrite writes
[] = { CreateMockWrite(*req
) };
4001 // All data frames in a single read.
4002 // NOTE: We don't FIN the stream.
4003 scoped_ptr
<SpdyFrame
> data_frame(
4004 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4005 const SpdyFrame
* data_frames
[4] = {
4011 char combined_data_frames
[100];
4012 int combined_data_frames_len
=
4013 CombineFrames(data_frames
, arraysize(data_frames
),
4014 combined_data_frames
, arraysize(combined_data_frames
));
4015 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4016 MockRead reads
[] = {
4017 CreateMockRead(*resp
),
4018 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4019 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4020 MockRead(ASYNC
, 0, 0) // EOF
4023 DelayedSocketData
data(1, reads
, arraysize(reads
),
4024 writes
, arraysize(writes
));
4026 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4027 BoundNetLog(), GetParam(), NULL
);
4028 helper
.RunPreTestSetup();
4029 helper
.AddData(&data
);
4030 HttpNetworkTransaction
* trans
= helper
.trans();
4032 TestCompletionCallback callback
;
4034 int rv
= trans
->Start(
4035 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4036 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4038 TransactionHelperResult out
= helper
.output();
4039 out
.rv
= callback
.WaitForResult();
4040 EXPECT_EQ(out
.rv
, OK
);
4042 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4043 EXPECT_TRUE(response
->headers
.get() != NULL
);
4044 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4045 out
.status_line
= response
->headers
->GetStatusLine();
4046 out
.response_info
= *response
; // Make a copy so we can verify.
4049 TestCompletionCallback read_callback
;
4051 std::string content
;
4052 int reads_completed
= 0;
4054 // Read small chunks at a time.
4055 const int kSmallReadSize
= 14;
4056 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4057 rv
= trans
->Read(buf
.get(), kSmallReadSize
, read_callback
.callback());
4058 if (rv
== net::ERR_IO_PENDING
) {
4059 data
.CompleteRead();
4060 rv
= read_callback
.WaitForResult();
4063 content
.append(buf
->data(), rv
);
4064 } else if (rv
< 0) {
4065 // This test intentionally closes the connection, and will get an error.
4066 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4072 EXPECT_EQ(0, reads_completed
);
4074 out
.response_data
.swap(content
);
4076 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4077 // MockClientSocketFactory) are still alive.
4078 base::RunLoop().RunUntilIdle();
4080 // Verify that we consumed all test data.
4081 helper
.VerifyDataConsumed();
4084 // Verify the case where we buffer data and cancel the transaction.
4085 TEST_P(SpdyNetworkTransactionTest
, BufferedCancelled
) {
4086 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
4088 scoped_ptr
<SpdyFrame
> req(
4089 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4090 MockWrite writes
[] = { CreateMockWrite(*req
) };
4092 // NOTE: We don't FIN the stream.
4093 scoped_ptr
<SpdyFrame
> data_frame(
4094 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4096 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4097 MockRead reads
[] = {
4098 CreateMockRead(*resp
),
4099 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4100 CreateMockRead(*data_frame
),
4101 MockRead(ASYNC
, 0, 0) // EOF
4104 DelayedSocketData
data(1, reads
, arraysize(reads
),
4105 writes
, arraysize(writes
));
4107 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4108 BoundNetLog(), GetParam(), NULL
);
4109 helper
.RunPreTestSetup();
4110 helper
.AddData(&data
);
4111 HttpNetworkTransaction
* trans
= helper
.trans();
4112 TestCompletionCallback callback
;
4114 int rv
= trans
->Start(
4115 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4118 TransactionHelperResult out
= helper
.output();
4119 out
.rv
= callback
.WaitForResult();
4120 EXPECT_EQ(out
.rv
, OK
);
4122 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4123 EXPECT_TRUE(response
->headers
.get() != NULL
);
4124 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4125 out
.status_line
= response
->headers
->GetStatusLine();
4126 out
.response_info
= *response
; // Make a copy so we can verify.
4129 TestCompletionCallback read_callback
;
4132 const int kReadSize
= 256;
4133 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4134 rv
= trans
->Read(buf
.get(), kReadSize
, read_callback
.callback());
4135 if (rv
== net::ERR_IO_PENDING
) {
4136 // Complete the read now, which causes buffering to start.
4137 data
.CompleteRead();
4138 // Destroy the transaction, causing the stream to get cancelled
4139 // and orphaning the buffered IO task.
4140 helper
.ResetTrans();
4143 // We shouldn't get here in this test.
4144 FAIL() << "Unexpected read: " << rv
;
4147 // Flush the MessageLoop; this will cause the buffered IO task
4148 // to run for the final time.
4149 base::RunLoop().RunUntilIdle();
4151 // Verify that we consumed all test data.
4152 helper
.VerifyDataConsumed();
4155 // Test that if the server requests persistence of settings, that we save
4156 // the settings in the HttpServerProperties.
4157 TEST_P(SpdyNetworkTransactionTest
, SettingsSaved
) {
4158 static const SpdyHeaderInfo kSynReplyInfo
= {
4159 SYN_REPLY
, // Syn Reply
4161 0, // Associated Stream ID
4162 ConvertRequestPriorityToSpdyPriority(
4163 LOWEST
, spdy_util_
.spdy_version()),
4164 kSpdyCredentialSlotUnused
,
4165 CONTROL_FLAG_NONE
, // Control Flags
4166 false, // Compressed
4167 RST_STREAM_INVALID
, // Status
4170 DATA_FLAG_NONE
// Data Flags
4173 BoundNetLog net_log
;
4174 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4175 net_log
, GetParam(), NULL
);
4176 helper
.RunPreTestSetup();
4178 // Verify that no settings exist initially.
4179 HostPortPair
host_port_pair("www.google.com", helper
.port());
4180 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4181 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4182 host_port_pair
).empty());
4184 // Construct the request.
4185 scoped_ptr
<SpdyFrame
> req(
4186 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4187 MockWrite writes
[] = { CreateMockWrite(*req
) };
4189 // Construct the reply.
4190 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4191 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4192 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4193 scoped_ptr
<SpdyFrame
> reply(
4194 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4196 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4197 unsigned int kSampleValue1
= 0x0a0a0a0a;
4198 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4199 unsigned int kSampleValue2
= 0x0b0b0b0b;
4200 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4201 unsigned int kSampleValue3
= 0x0c0c0c0c;
4202 scoped_ptr
<SpdyFrame
> settings_frame
;
4204 // Construct the SETTINGS frame.
4205 SettingsMap settings
;
4206 // First add a persisted setting.
4207 settings
[kSampleId1
] =
4208 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4209 // Next add a non-persisted setting.
4210 settings
[kSampleId2
] =
4211 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4212 // Next add another persisted setting.
4213 settings
[kSampleId3
] =
4214 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4215 settings_frame
.reset(spdy_util_
.ConstructSpdySettings(settings
));
4218 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4219 MockRead reads
[] = {
4220 CreateMockRead(*reply
),
4221 CreateMockRead(*body
),
4222 CreateMockRead(*settings_frame
),
4223 MockRead(ASYNC
, 0, 0) // EOF
4226 DelayedSocketData
data(1, reads
, arraysize(reads
),
4227 writes
, arraysize(writes
));
4228 helper
.AddData(&data
);
4229 helper
.RunDefaultTest();
4230 helper
.VerifyDataConsumed();
4231 TransactionHelperResult out
= helper
.output();
4232 EXPECT_EQ(OK
, out
.rv
);
4233 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4234 EXPECT_EQ("hello!", out
.response_data
);
4237 // Verify we had two persisted settings.
4238 const SettingsMap
& settings_map
=
4239 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4241 ASSERT_EQ(2u, settings_map
.size());
4243 // Verify the first persisted setting.
4244 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4245 EXPECT_TRUE(it1
!= settings_map
.end());
4246 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4247 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4248 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4250 // Verify the second persisted setting.
4251 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4252 EXPECT_TRUE(it3
!= settings_map
.end());
4253 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4254 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4255 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4259 // Test that when there are settings saved that they are sent back to the
4260 // server upon session establishment.
4261 TEST_P(SpdyNetworkTransactionTest
, SettingsPlayback
) {
4262 static const SpdyHeaderInfo kSynReplyInfo
= {
4263 SYN_REPLY
, // Syn Reply
4265 0, // Associated Stream ID
4266 ConvertRequestPriorityToSpdyPriority(
4267 LOWEST
, spdy_util_
.spdy_version()),
4268 kSpdyCredentialSlotUnused
,
4269 CONTROL_FLAG_NONE
, // Control Flags
4270 false, // Compressed
4271 RST_STREAM_INVALID
, // Status
4274 DATA_FLAG_NONE
// Data Flags
4277 BoundNetLog net_log
;
4278 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4279 net_log
, GetParam(), NULL
);
4280 helper
.RunPreTestSetup();
4282 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4284 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
4285 pool_peer
.SetEnableSendingInitialData(true);
4287 // Verify that no settings exist initially.
4288 HostPortPair
host_port_pair("www.google.com", helper
.port());
4289 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4290 host_port_pair
).empty());
4292 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4293 unsigned int kSampleValue1
= 0x0a0a0a0a;
4294 const SpdySettingsIds kSampleId2
= SETTINGS_ROUND_TRIP_TIME
;
4295 unsigned int kSampleValue2
= 0x0c0c0c0c;
4297 // First add a persisted setting.
4298 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4301 SETTINGS_FLAG_PLEASE_PERSIST
,
4304 // Next add another persisted setting.
4305 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4308 SETTINGS_FLAG_PLEASE_PERSIST
,
4311 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4312 host_port_pair
).size());
4314 // Construct the initial SETTINGS frame.
4315 SettingsMap initial_settings
;
4316 initial_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4317 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
4318 scoped_ptr
<SpdyFrame
> initial_settings_frame(
4319 spdy_util_
.ConstructSpdySettings(initial_settings
));
4321 // Construct the initial window update.
4322 scoped_ptr
<SpdyFrame
> initial_window_update(
4323 spdy_util_
.ConstructSpdyWindowUpdate(
4324 kSessionFlowControlStreamId
,
4325 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
4327 // Construct the persisted SETTINGS frame.
4328 const SettingsMap
& settings
=
4329 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4331 scoped_ptr
<SpdyFrame
> settings_frame(
4332 spdy_util_
.ConstructSpdySettings(settings
));
4334 // Construct the request.
4335 scoped_ptr
<SpdyFrame
> req(
4336 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4338 std::vector
<MockWrite
> writes
;
4339 if (GetParam().protocol
== kProtoHTTP2Draft04
) {
4342 kHttp2ConnectionHeaderPrefix
,
4343 kHttp2ConnectionHeaderPrefixSize
));
4345 writes
.push_back(CreateMockWrite(*initial_settings_frame
));
4346 if (GetParam().protocol
>= kProtoSPDY31
) {
4347 writes
.push_back(CreateMockWrite(*initial_window_update
));
4349 writes
.push_back(CreateMockWrite(*settings_frame
));
4350 writes
.push_back(CreateMockWrite(*req
));
4352 // Construct the reply.
4353 scoped_ptr
<SpdyHeaderBlock
> reply_headers(new SpdyHeaderBlock());
4354 (*reply_headers
)[spdy_util_
.GetStatusKey()] = "200";
4355 (*reply_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4356 scoped_ptr
<SpdyFrame
> reply(
4357 spdy_util_
.ConstructSpdyFrame(kSynReplyInfo
, reply_headers
.Pass()));
4359 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4360 MockRead reads
[] = {
4361 CreateMockRead(*reply
),
4362 CreateMockRead(*body
),
4363 MockRead(ASYNC
, 0, 0) // EOF
4366 DelayedSocketData
data(2, reads
, arraysize(reads
),
4367 vector_as_array(&writes
), writes
.size());
4368 helper
.AddData(&data
);
4369 helper
.RunDefaultTest();
4370 helper
.VerifyDataConsumed();
4371 TransactionHelperResult out
= helper
.output();
4372 EXPECT_EQ(OK
, out
.rv
);
4373 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4374 EXPECT_EQ("hello!", out
.response_data
);
4377 // Verify we had two persisted settings.
4378 const SettingsMap
& settings_map
=
4379 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4381 ASSERT_EQ(2u, settings_map
.size());
4383 // Verify the first persisted setting.
4384 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4385 EXPECT_TRUE(it1
!= settings_map
.end());
4386 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4387 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4388 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4390 // Verify the second persisted setting.
4391 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4392 EXPECT_TRUE(it2
!= settings_map
.end());
4393 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4394 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4395 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4399 TEST_P(SpdyNetworkTransactionTest
, GoAwayWithActiveStream
) {
4400 scoped_ptr
<SpdyFrame
> req(
4401 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4402 MockWrite writes
[] = { CreateMockWrite(*req
) };
4404 scoped_ptr
<SpdyFrame
> go_away(spdy_util_
.ConstructSpdyGoAway());
4405 MockRead reads
[] = {
4406 CreateMockRead(*go_away
),
4409 DelayedSocketData
data(1, reads
, arraysize(reads
),
4410 writes
, arraysize(writes
));
4411 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4412 BoundNetLog(), GetParam(), NULL
);
4413 helper
.AddData(&data
);
4414 helper
.RunToCompletion(&data
);
4415 TransactionHelperResult out
= helper
.output();
4416 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4419 TEST_P(SpdyNetworkTransactionTest
, CloseWithActiveStream
) {
4420 scoped_ptr
<SpdyFrame
> req(
4421 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4422 MockWrite writes
[] = { CreateMockWrite(*req
) };
4424 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4425 MockRead reads
[] = {
4426 CreateMockRead(*resp
),
4427 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4430 DelayedSocketData
data(1, reads
, arraysize(reads
),
4431 writes
, arraysize(writes
));
4433 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4434 log
, GetParam(), NULL
);
4435 helper
.RunPreTestSetup();
4436 helper
.AddData(&data
);
4437 HttpNetworkTransaction
* trans
= helper
.trans();
4439 TestCompletionCallback callback
;
4440 TransactionHelperResult out
;
4441 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4443 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4444 out
.rv
= callback
.WaitForResult();
4445 EXPECT_EQ(out
.rv
, OK
);
4447 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4448 EXPECT_TRUE(response
->headers
.get() != NULL
);
4449 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4450 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4451 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4453 // Verify that we consumed all test data.
4454 helper
.VerifyDataConsumed();
4457 // Test to make sure we can correctly connect through a proxy.
4458 TEST_P(SpdyNetworkTransactionTest
, ProxyConnect
) {
4459 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4460 BoundNetLog(), GetParam(), NULL
);
4461 helper
.session_deps().reset(CreateSpdySessionDependencies(
4463 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4464 helper
.SetSession(make_scoped_refptr(
4465 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4466 helper
.RunPreTestSetup();
4467 HttpNetworkTransaction
* trans
= helper
.trans();
4469 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4470 "Host: www.google.com\r\n"
4471 "Proxy-Connection: keep-alive\r\n\r\n"};
4472 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4473 "Host: www.google.com\r\n"
4474 "Proxy-Connection: keep-alive\r\n\r\n"};
4475 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4476 scoped_ptr
<SpdyFrame
> req(
4477 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4478 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4479 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4481 MockWrite writes_SPDYNPN
[] = {
4482 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4483 CreateMockWrite(*req
, 2),
4485 MockRead reads_SPDYNPN
[] = {
4486 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4487 CreateMockRead(*resp
, 3),
4488 CreateMockRead(*body
.get(), 4),
4489 MockRead(ASYNC
, 0, 0, 5),
4492 MockWrite writes_SPDYSSL
[] = {
4493 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4494 CreateMockWrite(*req
, 2),
4496 MockRead reads_SPDYSSL
[] = {
4497 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4498 CreateMockRead(*resp
, 3),
4499 CreateMockRead(*body
.get(), 4),
4500 MockRead(ASYNC
, 0, 0, 5),
4503 MockWrite writes_SPDYNOSSL
[] = {
4504 CreateMockWrite(*req
, 0),
4507 MockRead reads_SPDYNOSSL
[] = {
4508 CreateMockRead(*resp
, 1),
4509 CreateMockRead(*body
.get(), 2),
4510 MockRead(ASYNC
, 0, 0, 3),
4513 scoped_ptr
<OrderedSocketData
> data
;
4514 switch(GetParam().ssl_type
) {
4516 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4517 arraysize(reads_SPDYNOSSL
),
4519 arraysize(writes_SPDYNOSSL
)));
4522 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
4523 arraysize(reads_SPDYSSL
),
4525 arraysize(writes_SPDYSSL
)));
4528 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
4529 arraysize(reads_SPDYNPN
),
4531 arraysize(writes_SPDYNPN
)));
4537 helper
.AddData(data
.get());
4538 TestCompletionCallback callback
;
4540 int rv
= trans
->Start(
4541 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4542 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4544 rv
= callback
.WaitForResult();
4547 // Verify the SYN_REPLY.
4548 HttpResponseInfo response
= *trans
->GetResponseInfo();
4549 EXPECT_TRUE(response
.headers
.get() != NULL
);
4550 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
4552 std::string response_data
;
4553 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
4554 EXPECT_EQ("hello!", response_data
);
4555 helper
.VerifyDataConsumed();
4558 // Test to make sure we can correctly connect through a proxy to www.google.com,
4559 // if there already exists a direct spdy connection to www.google.com. See
4560 // http://crbug.com/49874
4561 TEST_P(SpdyNetworkTransactionTest
, DirectConnectProxyReconnect
) {
4562 // When setting up the first transaction, we store the SpdySessionPool so that
4563 // we can use the same pool in the second transaction.
4564 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4565 BoundNetLog(), GetParam(), NULL
);
4567 // Use a proxy service which returns a proxy fallback list from DIRECT to
4568 // myproxy:70. For this test there will be no fallback, so it is equivalent
4569 // to simply DIRECT. The reason for appending the second proxy is to verify
4570 // that the session pool key used does is just "DIRECT".
4571 helper
.session_deps().reset(CreateSpdySessionDependencies(
4573 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4574 helper
.SetSession(make_scoped_refptr(
4575 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4577 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4578 helper
.RunPreTestSetup();
4580 // Construct and send a simple GET request.
4581 scoped_ptr
<SpdyFrame
> req(
4582 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4583 MockWrite writes
[] = {
4584 CreateMockWrite(*req
, 1),
4587 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4588 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4589 MockRead reads
[] = {
4590 CreateMockRead(*resp
, 2),
4591 CreateMockRead(*body
, 3),
4592 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
4593 MockRead(ASYNC
, 0, 5) // EOF
4595 OrderedSocketData
data(reads
, arraysize(reads
),
4596 writes
, arraysize(writes
));
4597 helper
.AddData(&data
);
4598 HttpNetworkTransaction
* trans
= helper
.trans();
4600 TestCompletionCallback callback
;
4601 TransactionHelperResult out
;
4602 out
.rv
= trans
->Start(
4603 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4605 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4606 out
.rv
= callback
.WaitForResult();
4607 EXPECT_EQ(out
.rv
, OK
);
4609 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4610 EXPECT_TRUE(response
->headers
.get() != NULL
);
4611 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4612 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4613 EXPECT_EQ(OK
, out
.rv
);
4614 out
.status_line
= response
->headers
->GetStatusLine();
4615 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4616 EXPECT_EQ("hello!", out
.response_data
);
4618 // Check that the SpdySession is still in the SpdySessionPool.
4619 HostPortPair
host_port_pair("www.google.com", helper
.port());
4620 SpdySessionKey
session_pool_key_direct(
4621 host_port_pair
, ProxyServer::Direct(), kPrivacyModeDisabled
);
4622 EXPECT_TRUE(HasSpdySession(spdy_session_pool
, session_pool_key_direct
));
4623 SpdySessionKey
session_pool_key_proxy(
4625 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
),
4626 kPrivacyModeDisabled
);
4627 EXPECT_FALSE(HasSpdySession(spdy_session_pool
, session_pool_key_proxy
));
4629 // Set up data for the proxy connection.
4630 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4631 "Host: www.google.com\r\n"
4632 "Proxy-Connection: keep-alive\r\n\r\n"};
4633 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4634 "Host: www.google.com\r\n"
4635 "Proxy-Connection: keep-alive\r\n\r\n"};
4636 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4637 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
4638 "http://www.google.com/foo.dat", false, 1, LOWEST
));
4639 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4640 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4642 MockWrite writes_SPDYNPN
[] = {
4643 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4644 CreateMockWrite(*req2
, 2),
4646 MockRead reads_SPDYNPN
[] = {
4647 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4648 CreateMockRead(*resp2
, 3),
4649 CreateMockRead(*body2
, 4),
4650 MockRead(ASYNC
, 0, 5) // EOF
4653 MockWrite writes_SPDYNOSSL
[] = {
4654 CreateMockWrite(*req2
, 0),
4656 MockRead reads_SPDYNOSSL
[] = {
4657 CreateMockRead(*resp2
, 1),
4658 CreateMockRead(*body2
, 2),
4659 MockRead(ASYNC
, 0, 3) // EOF
4662 MockWrite writes_SPDYSSL
[] = {
4663 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4664 CreateMockWrite(*req2
, 2),
4666 MockRead reads_SPDYSSL
[] = {
4667 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4668 CreateMockRead(*resp2
, 3),
4669 CreateMockRead(*body2
, 4),
4670 MockRead(ASYNC
, 0, 0, 5),
4673 scoped_ptr
<OrderedSocketData
> data_proxy
;
4674 switch(GetParam().ssl_type
) {
4676 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
4677 arraysize(reads_SPDYNPN
),
4679 arraysize(writes_SPDYNPN
)));
4682 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
4683 arraysize(reads_SPDYNOSSL
),
4685 arraysize(writes_SPDYNOSSL
)));
4688 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
4689 arraysize(reads_SPDYSSL
),
4691 arraysize(writes_SPDYSSL
)));
4697 // Create another request to www.google.com, but this time through a proxy.
4698 HttpRequestInfo request_proxy
;
4699 request_proxy
.method
= "GET";
4700 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
4701 request_proxy
.load_flags
= 0;
4702 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(
4703 CreateSpdySessionDependencies(GetParam()));
4704 // Ensure that this transaction uses the same SpdySessionPool.
4705 scoped_refptr
<HttpNetworkSession
> session_proxy(
4706 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
4707 NormalSpdyTransactionHelper
helper_proxy(request_proxy
, DEFAULT_PRIORITY
,
4708 BoundNetLog(), GetParam(), NULL
);
4709 HttpNetworkSessionPeer
session_peer(session_proxy
);
4710 scoped_ptr
<net::ProxyService
> proxy_service(
4711 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4712 session_peer
.SetProxyService(proxy_service
.get());
4713 helper_proxy
.session_deps().swap(ssd_proxy
);
4714 helper_proxy
.SetSession(session_proxy
);
4715 helper_proxy
.RunPreTestSetup();
4716 helper_proxy
.AddData(data_proxy
.get());
4718 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
4719 TestCompletionCallback callback_proxy
;
4720 int rv
= trans_proxy
->Start(
4721 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
4722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4723 rv
= callback_proxy
.WaitForResult();
4726 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
4727 EXPECT_TRUE(response_proxy
.headers
.get() != NULL
);
4728 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
4730 std::string response_data
;
4731 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
4732 EXPECT_EQ("hello!", response_data
);
4734 data
.CompleteRead();
4735 helper_proxy
.VerifyDataConsumed();
4738 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4739 // on a new connection, if the connection was previously known to be good.
4740 // This can happen when a server reboots without saying goodbye, or when
4741 // we're behind a NAT that masked the RST.
4742 TEST_P(SpdyNetworkTransactionTest
, VerifyRetryOnConnectionReset
) {
4743 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4744 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4745 MockRead reads
[] = {
4746 CreateMockRead(*resp
),
4747 CreateMockRead(*body
),
4748 MockRead(ASYNC
, ERR_IO_PENDING
),
4749 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
4752 MockRead reads2
[] = {
4753 CreateMockRead(*resp
),
4754 CreateMockRead(*body
),
4755 MockRead(ASYNC
, 0, 0) // EOF
4758 // This test has a couple of variants.
4760 // Induce the RST while waiting for our transaction to send.
4761 VARIANT_RST_DURING_SEND_COMPLETION
,
4762 // Induce the RST while waiting for our transaction to read.
4763 // In this case, the send completed - everything copied into the SNDBUF.
4764 VARIANT_RST_DURING_READ_COMPLETION
4767 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
4768 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
4770 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
4772 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
4774 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4775 BoundNetLog(), GetParam(), NULL
);
4776 helper
.AddData(&data1
);
4777 helper
.AddData(&data2
);
4778 helper
.RunPreTestSetup();
4780 for (int i
= 0; i
< 2; ++i
) {
4781 scoped_ptr
<HttpNetworkTransaction
> trans(
4782 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
4784 TestCompletionCallback callback
;
4785 int rv
= trans
->Start(
4786 &helper
.request(), callback
.callback(), BoundNetLog());
4787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4788 // On the second transaction, we trigger the RST.
4790 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
4791 // Writes to the socket complete asynchronously on SPDY by running
4792 // through the message loop. Complete the write here.
4793 base::RunLoop().RunUntilIdle();
4796 // Now schedule the ERR_CONNECTION_RESET.
4797 EXPECT_EQ(3u, data1
.read_index());
4798 data1
.CompleteRead();
4799 EXPECT_EQ(4u, data1
.read_index());
4801 rv
= callback
.WaitForResult();
4804 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4805 ASSERT_TRUE(response
!= NULL
);
4806 EXPECT_TRUE(response
->headers
.get() != NULL
);
4807 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4808 std::string response_data
;
4809 rv
= ReadTransaction(trans
.get(), &response_data
);
4811 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4812 EXPECT_EQ("hello!", response_data
);
4815 helper
.VerifyDataConsumed();
4819 // Test that turning SPDY on and off works properly.
4820 TEST_P(SpdyNetworkTransactionTest
, SpdyOnOffToggle
) {
4821 net::HttpStreamFactory::set_spdy_enabled(true);
4822 scoped_ptr
<SpdyFrame
> req(
4823 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4824 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
4826 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4827 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4828 MockRead spdy_reads
[] = {
4829 CreateMockRead(*resp
),
4830 CreateMockRead(*body
),
4831 MockRead(ASYNC
, 0, 0) // EOF
4834 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
4835 spdy_writes
, arraysize(spdy_writes
));
4836 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
4837 BoundNetLog(), GetParam(), NULL
);
4838 helper
.RunToCompletion(&data
);
4839 TransactionHelperResult out
= helper
.output();
4840 EXPECT_EQ(OK
, out
.rv
);
4841 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4842 EXPECT_EQ("hello!", out
.response_data
);
4844 net::HttpStreamFactory::set_spdy_enabled(false);
4845 MockRead http_reads
[] = {
4846 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4847 MockRead("hello from http"),
4848 MockRead(SYNCHRONOUS
, OK
),
4850 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
4851 NormalSpdyTransactionHelper
helper2(CreateGetRequest(), DEFAULT_PRIORITY
,
4852 BoundNetLog(), GetParam(), NULL
);
4853 helper2
.SetSpdyDisabled();
4854 helper2
.RunToCompletion(&data2
);
4855 TransactionHelperResult out2
= helper2
.output();
4856 EXPECT_EQ(OK
, out2
.rv
);
4857 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
4858 EXPECT_EQ("hello from http", out2
.response_data
);
4860 net::HttpStreamFactory::set_spdy_enabled(true);
4863 // Tests that Basic authentication works over SPDY
4864 TEST_P(SpdyNetworkTransactionTest
, SpdyBasicAuth
) {
4865 net::HttpStreamFactory::set_spdy_enabled(true);
4867 // The first request will be a bare GET, the second request will be a
4868 // GET with an Authorization header.
4869 scoped_ptr
<SpdyFrame
> req_get(
4870 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4871 const char* const kExtraAuthorizationHeaders
[] = {
4872 "authorization", "Basic Zm9vOmJhcg=="
4874 scoped_ptr
<SpdyFrame
> req_get_authorization(
4875 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
4876 arraysize(kExtraAuthorizationHeaders
) / 2,
4877 false, 3, LOWEST
, true));
4878 MockWrite spdy_writes
[] = {
4879 CreateMockWrite(*req_get
, 1),
4880 CreateMockWrite(*req_get_authorization
, 4),
4883 // The first response is a 401 authentication challenge, and the second
4884 // response will be a 200 response since the second request includes a valid
4885 // Authorization header.
4886 const char* const kExtraAuthenticationHeaders
[] = {
4888 "Basic realm=\"MyRealm\""
4890 scoped_ptr
<SpdyFrame
> resp_authentication(
4891 spdy_util_
.ConstructSpdySynReplyError(
4892 "401 Authentication Required",
4893 kExtraAuthenticationHeaders
,
4894 arraysize(kExtraAuthenticationHeaders
) / 2,
4896 scoped_ptr
<SpdyFrame
> body_authentication(
4897 spdy_util_
.ConstructSpdyBodyFrame(1, true));
4898 scoped_ptr
<SpdyFrame
> resp_data(
4899 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4900 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
4901 MockRead spdy_reads
[] = {
4902 CreateMockRead(*resp_authentication
, 2),
4903 CreateMockRead(*body_authentication
, 3),
4904 CreateMockRead(*resp_data
, 5),
4905 CreateMockRead(*body_data
, 6),
4906 MockRead(ASYNC
, 0, 7),
4909 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
4910 spdy_writes
, arraysize(spdy_writes
));
4911 HttpRequestInfo
request(CreateGetRequest());
4912 BoundNetLog net_log
;
4913 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
4914 net_log
, GetParam(), NULL
);
4916 helper
.RunPreTestSetup();
4917 helper
.AddData(&data
);
4918 HttpNetworkTransaction
* trans
= helper
.trans();
4919 TestCompletionCallback callback
;
4920 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
4921 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
4922 const int rv_start_complete
= callback
.WaitForResult();
4923 EXPECT_EQ(OK
, rv_start_complete
);
4925 // Make sure the response has an auth challenge.
4926 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
4927 ASSERT_TRUE(response_start
!= NULL
);
4928 ASSERT_TRUE(response_start
->headers
.get() != NULL
);
4929 EXPECT_EQ(401, response_start
->headers
->response_code());
4930 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
4931 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
4932 ASSERT_TRUE(auth_challenge
!= NULL
);
4933 EXPECT_FALSE(auth_challenge
->is_proxy
);
4934 EXPECT_EQ("basic", auth_challenge
->scheme
);
4935 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
4937 // Restart with a username/password.
4938 AuthCredentials
credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
4939 TestCompletionCallback callback_restart
;
4940 const int rv_restart
= trans
->RestartWithAuth(
4941 credentials
, callback_restart
.callback());
4942 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
4943 const int rv_restart_complete
= callback_restart
.WaitForResult();
4944 EXPECT_EQ(OK
, rv_restart_complete
);
4945 // TODO(cbentzel): This is actually the same response object as before, but
4946 // data has changed.
4947 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
4948 ASSERT_TRUE(response_restart
!= NULL
);
4949 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
4950 EXPECT_EQ(200, response_restart
->headers
->response_code());
4951 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
4954 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithHeaders
) {
4955 scoped_ptr
<SpdyFrame
> stream1_syn(
4956 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4957 scoped_ptr
<SpdyFrame
> stream1_body(
4958 spdy_util_
.ConstructSpdyBodyFrame(1, true));
4959 MockWrite writes
[] = {
4960 CreateMockWrite(*stream1_syn
, 1),
4963 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
4964 spdy_util_
.AddUrlToHeaderBlock(
4965 "http://www.google.com/foo.dat", initial_headers
.get());
4966 scoped_ptr
<SpdyFrame
> stream2_syn(
4967 spdy_util_
.ConstructSpdyControlFrame(initial_headers
.Pass(),
4975 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
4976 (*late_headers
)["hello"] = "bye";
4977 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
4978 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
4979 scoped_ptr
<SpdyFrame
> stream2_headers(
4980 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
4988 scoped_ptr
<SpdyFrame
>
4989 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4990 const char kPushedData
[] = "pushed";
4991 scoped_ptr
<SpdyFrame
> stream2_body(
4992 spdy_util_
.ConstructSpdyBodyFrame(
4993 2, kPushedData
, strlen(kPushedData
), true));
4994 MockRead reads
[] = {
4995 CreateMockRead(*stream1_reply
, 2),
4996 CreateMockRead(*stream2_syn
, 3),
4997 CreateMockRead(*stream2_headers
, 4),
4998 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
4999 CreateMockRead(*stream2_body
, 5),
5000 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5003 HttpResponseInfo response
;
5004 HttpResponseInfo response2
;
5005 std::string
expected_push_result("pushed");
5006 OrderedSocketData
data(reads
, arraysize(reads
),
5007 writes
, arraysize(writes
));
5008 RunServerPushTest(&data
,
5011 expected_push_result
);
5013 // Verify the SYN_REPLY.
5014 EXPECT_TRUE(response
.headers
.get() != NULL
);
5015 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5017 // Verify the pushed stream.
5018 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5019 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5022 TEST_P(SpdyNetworkTransactionTest
, ServerPushClaimBeforeHeaders
) {
5023 // We push a stream and attempt to claim it before the headers come down.
5024 scoped_ptr
<SpdyFrame
> stream1_syn(
5025 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5026 scoped_ptr
<SpdyFrame
> stream1_body(
5027 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5028 MockWrite writes
[] = {
5029 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5032 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5033 spdy_util_
.AddUrlToHeaderBlock(
5034 "http://www.google.com/foo.dat", initial_headers
.get());
5035 scoped_ptr
<SpdyFrame
> stream2_syn(
5036 spdy_util_
.ConstructSpdyControlFrame(initial_headers
.Pass(),
5044 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5045 (*late_headers
)["hello"] = "bye";
5046 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5047 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5048 scoped_ptr
<SpdyFrame
> stream2_headers(
5049 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5057 scoped_ptr
<SpdyFrame
>
5058 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5059 const char kPushedData
[] = "pushed";
5060 scoped_ptr
<SpdyFrame
> stream2_body(
5061 spdy_util_
.ConstructSpdyBodyFrame(
5062 2, kPushedData
, strlen(kPushedData
), true));
5063 MockRead reads
[] = {
5064 CreateMockRead(*stream1_reply
, 1),
5065 CreateMockRead(*stream2_syn
, 2),
5066 CreateMockRead(*stream1_body
, 3),
5067 CreateMockRead(*stream2_headers
, 4),
5068 CreateMockRead(*stream2_body
, 5),
5069 MockRead(ASYNC
, 0, 6), // EOF
5072 HttpResponseInfo response
;
5073 HttpResponseInfo response2
;
5074 std::string
expected_push_result("pushed");
5075 DeterministicSocketData
data(reads
, arraysize(reads
),
5076 writes
, arraysize(writes
));
5078 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5079 BoundNetLog(), GetParam(), NULL
);
5080 helper
.SetDeterministic();
5081 helper
.AddDeterministicData(&data
);
5082 helper
.RunPreTestSetup();
5084 HttpNetworkTransaction
* trans
= helper
.trans();
5086 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5087 // and the body of the primary stream, but before we've received the HEADERS
5088 // for the pushed stream.
5091 // Start the transaction.
5092 TestCompletionCallback callback
;
5093 int rv
= trans
->Start(
5094 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5097 rv
= callback
.WaitForResult();
5100 // Request the pushed path. At this point, we've received the push, but the
5101 // headers are not yet complete.
5102 scoped_ptr
<HttpNetworkTransaction
> trans2(
5103 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5105 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5108 base::RunLoop().RunUntilIdle();
5110 // Read the server push body.
5111 std::string result2
;
5112 ReadResult(trans2
.get(), &data
, &result2
);
5113 // Read the response body.
5115 ReadResult(trans
, &data
, &result
);
5117 // Verify that the received push data is same as the expected push data.
5118 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5119 << "Received data: "
5121 << "||||| Expected data: "
5122 << expected_push_result
;
5124 // Verify the SYN_REPLY.
5125 // Copy the response info, because trans goes away.
5126 response
= *trans
->GetResponseInfo();
5127 response2
= *trans2
->GetResponseInfo();
5129 VerifyStreamsClosed(helper
);
5131 // Verify the SYN_REPLY.
5132 EXPECT_TRUE(response
.headers
.get() != NULL
);
5133 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5135 // Verify the pushed stream.
5136 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5137 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5139 // Read the final EOF (which will close the session)
5142 // Verify that we consumed all test data.
5143 EXPECT_TRUE(data
.at_read_eof());
5144 EXPECT_TRUE(data
.at_write_eof());
5147 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithTwoHeaderFrames
) {
5148 // We push a stream and attempt to claim it before the headers come down.
5149 scoped_ptr
<SpdyFrame
> stream1_syn(
5150 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5151 scoped_ptr
<SpdyFrame
> stream1_body(
5152 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5153 MockWrite writes
[] = {
5154 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5157 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5158 spdy_util_
.AddUrlToHeaderBlock(
5159 "http://www.google.com/foo.dat", initial_headers
.get());
5160 scoped_ptr
<SpdyFrame
> stream2_syn(
5161 spdy_util_
.ConstructSpdyControlFrame(initial_headers
.Pass(),
5169 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5170 (*middle_headers
)["hello"] = "bye";
5171 scoped_ptr
<SpdyFrame
> stream2_headers1(
5172 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5180 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5181 (*late_headers
)[spdy_util_
.GetStatusKey()] = "200";
5182 (*late_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5183 scoped_ptr
<SpdyFrame
> stream2_headers2(
5184 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5192 scoped_ptr
<SpdyFrame
>
5193 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5194 const char kPushedData
[] = "pushed";
5195 scoped_ptr
<SpdyFrame
> stream2_body(
5196 spdy_util_
.ConstructSpdyBodyFrame(
5197 2, kPushedData
, strlen(kPushedData
), true));
5198 MockRead reads
[] = {
5199 CreateMockRead(*stream1_reply
, 1),
5200 CreateMockRead(*stream2_syn
, 2),
5201 CreateMockRead(*stream1_body
, 3),
5202 CreateMockRead(*stream2_headers1
, 4),
5203 CreateMockRead(*stream2_headers2
, 5),
5204 CreateMockRead(*stream2_body
, 6),
5205 MockRead(ASYNC
, 0, 7), // EOF
5208 HttpResponseInfo response
;
5209 HttpResponseInfo response2
;
5210 std::string
expected_push_result("pushed");
5211 DeterministicSocketData
data(reads
, arraysize(reads
),
5212 writes
, arraysize(writes
));
5214 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5215 BoundNetLog(), GetParam(), NULL
);
5216 helper
.SetDeterministic();
5217 helper
.AddDeterministicData(&data
);
5218 helper
.RunPreTestSetup();
5220 HttpNetworkTransaction
* trans
= helper
.trans();
5222 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5223 // the first HEADERS frame, and the body of the primary stream, but before
5224 // we've received the final HEADERS for the pushed stream.
5227 // Start the transaction.
5228 TestCompletionCallback callback
;
5229 int rv
= trans
->Start(
5230 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5231 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5233 rv
= callback
.WaitForResult();
5236 // Request the pushed path. At this point, we've received the push, but the
5237 // headers are not yet complete.
5238 scoped_ptr
<HttpNetworkTransaction
> trans2(
5239 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5241 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5242 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5244 base::RunLoop().RunUntilIdle();
5246 // Read the server push body.
5247 std::string result2
;
5248 ReadResult(trans2
.get(), &data
, &result2
);
5249 // Read the response body.
5251 ReadResult(trans
, &data
, &result
);
5253 // Verify that the received push data is same as the expected push data.
5254 EXPECT_EQ(expected_push_result
, result2
);
5256 // Verify the SYN_REPLY.
5257 // Copy the response info, because trans goes away.
5258 response
= *trans
->GetResponseInfo();
5259 response2
= *trans2
->GetResponseInfo();
5261 VerifyStreamsClosed(helper
);
5263 // Verify the SYN_REPLY.
5264 EXPECT_TRUE(response
.headers
.get() != NULL
);
5265 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5267 // Verify the pushed stream.
5268 EXPECT_TRUE(response2
.headers
.get() != NULL
);
5269 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5271 // Verify we got all the headers
5272 if (spdy_util_
.spdy_version() < SPDY3
) {
5273 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5275 "http://www.google.com/foo.dat"));
5277 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5279 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5280 "host", "www.google.com"));
5281 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5282 "path", "/foo.dat"));
5284 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5285 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5286 EXPECT_TRUE(response2
.headers
->HasHeaderValue("version", "HTTP/1.1"));
5288 // Read the final EOF (which will close the session)
5291 // Verify that we consumed all test data.
5292 EXPECT_TRUE(data
.at_read_eof());
5293 EXPECT_TRUE(data
.at_write_eof());
5296 TEST_P(SpdyNetworkTransactionTest
, ServerPushWithNoStatusHeaderFrames
) {
5297 // We push a stream and attempt to claim it before the headers come down.
5298 scoped_ptr
<SpdyFrame
> stream1_syn(
5299 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5300 scoped_ptr
<SpdyFrame
> stream1_body(
5301 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5302 MockWrite writes
[] = {
5303 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5306 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5307 spdy_util_
.AddUrlToHeaderBlock(
5308 "http://www.google.com/foo.dat", initial_headers
.get());
5309 scoped_ptr
<SpdyFrame
> stream2_syn(
5310 spdy_util_
.ConstructSpdyControlFrame(initial_headers
.Pass(),
5318 scoped_ptr
<SpdyHeaderBlock
> middle_headers(new SpdyHeaderBlock());
5319 (*middle_headers
)["hello"] = "bye";
5320 scoped_ptr
<SpdyFrame
> stream2_headers1(
5321 spdy_util_
.ConstructSpdyControlFrame(middle_headers
.Pass(),
5329 scoped_ptr
<SpdyFrame
>
5330 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5331 const char kPushedData
[] = "pushed";
5332 scoped_ptr
<SpdyFrame
> stream2_body(
5333 spdy_util_
.ConstructSpdyBodyFrame(
5334 2, kPushedData
, strlen(kPushedData
), true));
5335 MockRead reads
[] = {
5336 CreateMockRead(*stream1_reply
, 1),
5337 CreateMockRead(*stream2_syn
, 2),
5338 CreateMockRead(*stream1_body
, 3),
5339 CreateMockRead(*stream2_headers1
, 4),
5340 CreateMockRead(*stream2_body
, 5),
5341 MockRead(ASYNC
, 0, 6), // EOF
5344 DeterministicSocketData
data(reads
, arraysize(reads
),
5345 writes
, arraysize(writes
));
5347 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5348 BoundNetLog(), GetParam(), NULL
);
5349 helper
.SetDeterministic();
5350 helper
.AddDeterministicData(&data
);
5351 helper
.RunPreTestSetup();
5353 HttpNetworkTransaction
* trans
= helper
.trans();
5355 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5356 // the first HEADERS frame, and the body of the primary stream, but before
5357 // we've received the final HEADERS for the pushed stream.
5360 // Start the transaction.
5361 TestCompletionCallback callback
;
5362 int rv
= trans
->Start(
5363 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5364 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5366 rv
= callback
.WaitForResult();
5369 // Request the pushed path. At this point, we've received the push, but the
5370 // headers are not yet complete.
5371 scoped_ptr
<HttpNetworkTransaction
> trans2(
5372 new HttpNetworkTransaction(DEFAULT_PRIORITY
, helper
.session().get()));
5374 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5377 base::RunLoop().RunUntilIdle();
5379 // Read the server push body.
5380 std::string result2
;
5381 ReadResult(trans2
.get(), &data
, &result2
);
5382 // Read the response body.
5384 ReadResult(trans
, &data
, &result
);
5385 EXPECT_EQ("hello!", result
);
5387 // Verify that we haven't received any push data.
5388 EXPECT_EQ("", result2
);
5390 // Verify the SYN_REPLY.
5391 // Copy the response info, because trans goes away.
5392 HttpResponseInfo response
= *trans
->GetResponseInfo();
5393 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5395 VerifyStreamsClosed(helper
);
5397 // Verify the SYN_REPLY.
5398 EXPECT_TRUE(response
.headers
.get() != NULL
);
5399 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5401 // Read the final EOF (which will close the session).
5404 // Verify that we consumed all test data.
5405 EXPECT_TRUE(data
.at_read_eof());
5406 EXPECT_TRUE(data
.at_write_eof());
5409 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithHeaders
) {
5410 scoped_ptr
<SpdyFrame
> req(
5411 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5412 scoped_ptr
<SpdyFrame
> rst(
5413 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5414 MockWrite writes
[] = {
5415 CreateMockWrite(*req
),
5416 CreateMockWrite(*rst
),
5419 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5420 (*initial_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
5421 (*initial_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5422 scoped_ptr
<SpdyFrame
> stream1_reply(
5423 spdy_util_
.ConstructSpdyControlFrame(initial_headers
.Pass(),
5431 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5432 (*late_headers
)["hello"] = "bye";
5433 scoped_ptr
<SpdyFrame
> stream1_headers(
5434 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5441 scoped_ptr
<SpdyFrame
> stream1_body(
5442 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5443 MockRead reads
[] = {
5444 CreateMockRead(*stream1_reply
),
5445 CreateMockRead(*stream1_headers
),
5446 CreateMockRead(*stream1_body
),
5447 MockRead(ASYNC
, 0, 0) // EOF
5450 DelayedSocketData
data(1, reads
, arraysize(reads
),
5451 writes
, arraysize(writes
));
5452 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5453 BoundNetLog(), GetParam(), NULL
);
5454 helper
.RunToCompletion(&data
);
5455 TransactionHelperResult out
= helper
.output();
5456 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5459 TEST_P(SpdyNetworkTransactionTest
, SynReplyWithLateHeaders
) {
5460 scoped_ptr
<SpdyFrame
> req(
5461 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5462 scoped_ptr
<SpdyFrame
> rst(
5463 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR
));
5464 MockWrite writes
[] = {
5465 CreateMockWrite(*req
),
5466 CreateMockWrite(*rst
),
5469 scoped_ptr
<SpdyHeaderBlock
> initial_headers(new SpdyHeaderBlock());
5470 (*initial_headers
)[spdy_util_
.GetStatusKey()] = "200 OK";
5471 (*initial_headers
)[spdy_util_
.GetVersionKey()] = "HTTP/1.1";
5472 scoped_ptr
<SpdyFrame
> stream1_reply(
5473 spdy_util_
.ConstructSpdyControlFrame(initial_headers
.Pass(),
5481 scoped_ptr
<SpdyHeaderBlock
> late_headers(new SpdyHeaderBlock());
5482 (*late_headers
)["hello"] = "bye";
5483 scoped_ptr
<SpdyFrame
> stream1_headers(
5484 spdy_util_
.ConstructSpdyControlFrame(late_headers
.Pass(),
5491 scoped_ptr
<SpdyFrame
> stream1_body(
5492 spdy_util_
.ConstructSpdyBodyFrame(1, false));
5493 scoped_ptr
<SpdyFrame
> stream1_body2(
5494 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5495 MockRead reads
[] = {
5496 CreateMockRead(*stream1_reply
),
5497 CreateMockRead(*stream1_body
),
5498 CreateMockRead(*stream1_headers
),
5499 CreateMockRead(*stream1_body2
),
5500 MockRead(ASYNC
, 0, 0) // EOF
5503 DelayedSocketData
data(1, reads
, arraysize(reads
),
5504 writes
, arraysize(writes
));
5505 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5506 BoundNetLog(), GetParam(), NULL
);
5507 helper
.RunToCompletion(&data
);
5508 TransactionHelperResult out
= helper
.output();
5509 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
5512 TEST_P(SpdyNetworkTransactionTest
, ServerPushCrossOriginCorrectness
) {
5513 // In this test we want to verify that we can't accidentally push content
5514 // which can't be pushed by this content server.
5515 // This test assumes that:
5516 // - if we're requesting http://www.foo.com/barbaz
5517 // - the browser has made a connection to "www.foo.com".
5519 // A list of the URL to fetch, followed by the URL being pushed.
5520 static const char* const kTestCases
[] = {
5521 "http://www.google.com/foo.html",
5522 "http://www.google.com:81/foo.js", // Bad port
5524 "http://www.google.com/foo.html",
5525 "https://www.google.com/foo.js", // Bad protocol
5527 "http://www.google.com/foo.html",
5528 "ftp://www.google.com/foo.js", // Invalid Protocol
5530 "http://www.google.com/foo.html",
5531 "http://blat.www.google.com/foo.js", // Cross subdomain
5533 "http://www.google.com/foo.html",
5534 "http://www.foo.com/foo.js", // Cross domain
5537 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
5538 const char* url_to_fetch
= kTestCases
[index
];
5539 const char* url_to_push
= kTestCases
[index
+ 1];
5541 scoped_ptr
<SpdyFrame
> stream1_syn(
5542 spdy_util_
.ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
5543 scoped_ptr
<SpdyFrame
> stream1_body(
5544 spdy_util_
.ConstructSpdyBodyFrame(1, true));
5545 scoped_ptr
<SpdyFrame
> push_rst(
5546 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
5547 MockWrite writes
[] = {
5548 CreateMockWrite(*stream1_syn
, 1),
5549 CreateMockWrite(*push_rst
, 4),
5552 scoped_ptr
<SpdyFrame
>
5553 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5554 scoped_ptr
<SpdyFrame
>
5555 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
5560 const char kPushedData
[] = "pushed";
5561 scoped_ptr
<SpdyFrame
> stream2_body(
5562 spdy_util_
.ConstructSpdyBodyFrame(
5563 2, kPushedData
, strlen(kPushedData
), true));
5564 scoped_ptr
<SpdyFrame
> rst(
5565 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5567 MockRead reads
[] = {
5568 CreateMockRead(*stream1_reply
, 2),
5569 CreateMockRead(*stream2_syn
, 3),
5570 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5571 CreateMockRead(*stream2_body
, 6),
5572 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5575 HttpResponseInfo response
;
5576 OrderedSocketData
data(reads
, arraysize(reads
),
5577 writes
, arraysize(writes
));
5579 HttpRequestInfo request
;
5580 request
.method
= "GET";
5581 request
.url
= GURL(url_to_fetch
);
5582 request
.load_flags
= 0;
5584 // Enable cross-origin push. Since we are not using a proxy, this should
5585 // not actually enable cross-origin SPDY push.
5586 scoped_ptr
<SpdySessionDependencies
> session_deps(
5587 CreateSpdySessionDependencies(GetParam()));
5588 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
5589 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5590 BoundNetLog(), GetParam(),
5591 session_deps
.release());
5592 helper
.RunPreTestSetup();
5593 helper
.AddData(&data
);
5595 HttpNetworkTransaction
* trans
= helper
.trans();
5597 // Start the transaction with basic parameters.
5598 TestCompletionCallback callback
;
5600 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5601 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5602 rv
= callback
.WaitForResult();
5604 // Read the response body.
5606 ReadResult(trans
, &data
, &result
);
5608 // Verify that we consumed all test data.
5609 EXPECT_TRUE(data
.at_read_eof());
5610 EXPECT_TRUE(data
.at_write_eof());
5612 // Verify the SYN_REPLY.
5613 // Copy the response info, because trans goes away.
5614 response
= *trans
->GetResponseInfo();
5616 VerifyStreamsClosed(helper
);
5618 // Verify the SYN_REPLY.
5619 EXPECT_TRUE(response
.headers
.get() != NULL
);
5620 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5624 TEST_P(SpdyNetworkTransactionTest
, RetryAfterRefused
) {
5625 // Construct the request.
5626 scoped_ptr
<SpdyFrame
> req(
5627 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5628 scoped_ptr
<SpdyFrame
> req2(
5629 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
5630 MockWrite writes
[] = {
5631 CreateMockWrite(*req
, 1),
5632 CreateMockWrite(*req2
, 3),
5635 scoped_ptr
<SpdyFrame
> refused(
5636 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
5637 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5638 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5639 MockRead reads
[] = {
5640 CreateMockRead(*refused
, 2),
5641 CreateMockRead(*resp
, 4),
5642 CreateMockRead(*body
, 5),
5643 MockRead(ASYNC
, 0, 6) // EOF
5646 OrderedSocketData
data(reads
, arraysize(reads
),
5647 writes
, arraysize(writes
));
5648 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5649 BoundNetLog(), GetParam(), NULL
);
5651 helper
.RunPreTestSetup();
5652 helper
.AddData(&data
);
5654 HttpNetworkTransaction
* trans
= helper
.trans();
5656 // Start the transaction with basic parameters.
5657 TestCompletionCallback callback
;
5658 int rv
= trans
->Start(
5659 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5660 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5661 rv
= callback
.WaitForResult();
5664 // Verify that we consumed all test data.
5665 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
5666 << data
.read_count()
5668 << data
.read_index();
5669 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
5670 << data
.write_count()
5672 << data
.write_index();
5674 // Verify the SYN_REPLY.
5675 HttpResponseInfo response
= *trans
->GetResponseInfo();
5676 EXPECT_TRUE(response
.headers
.get() != NULL
);
5677 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5680 TEST_P(SpdyNetworkTransactionTest
, OutOfOrderSynStream
) {
5681 // This first request will start to establish the SpdySession.
5682 // Then we will start the second (MEDIUM priority) and then third
5683 // (HIGHEST priority) request in such a way that the third will actually
5684 // start before the second, causing the second to be numbered differently
5685 // than the order they were created.
5686 scoped_ptr
<SpdyFrame
> req1(
5687 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5688 scoped_ptr
<SpdyFrame
> req2(
5689 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
, true));
5690 scoped_ptr
<SpdyFrame
> req3(
5691 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
, true));
5692 MockWrite writes
[] = {
5693 CreateMockWrite(*req1
, 0),
5694 CreateMockWrite(*req2
, 3),
5695 CreateMockWrite(*req3
, 4),
5698 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5699 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
5700 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
5701 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
5702 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
5703 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
5704 MockRead reads
[] = {
5705 CreateMockRead(*resp1
, 1),
5706 CreateMockRead(*body1
, 2),
5707 CreateMockRead(*resp2
, 5),
5708 CreateMockRead(*body2
, 6),
5709 CreateMockRead(*resp3
, 7),
5710 CreateMockRead(*body3
, 8),
5711 MockRead(ASYNC
, 0, 9) // EOF
5714 DeterministicSocketData
data(reads
, arraysize(reads
),
5715 writes
, arraysize(writes
));
5716 NormalSpdyTransactionHelper
helper(CreateGetRequest(), LOWEST
,
5717 BoundNetLog(), GetParam(), NULL
);
5718 helper
.SetDeterministic();
5719 helper
.RunPreTestSetup();
5720 helper
.AddDeterministicData(&data
);
5722 // Start the first transaction to set up the SpdySession
5723 HttpNetworkTransaction
* trans
= helper
.trans();
5724 TestCompletionCallback callback
;
5725 HttpRequestInfo info1
= CreateGetRequest();
5726 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
5727 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5729 // Run the message loop, but do not allow the write to complete.
5730 // This leaves the SpdySession with a write pending, which prevents
5731 // SpdySession from attempting subsequent writes until this write completes.
5732 base::RunLoop().RunUntilIdle();
5734 // Now, start both new transactions
5735 HttpRequestInfo info2
= CreateGetRequest();
5736 TestCompletionCallback callback2
;
5737 scoped_ptr
<HttpNetworkTransaction
> trans2(
5738 new HttpNetworkTransaction(MEDIUM
, helper
.session().get()));
5739 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
5740 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5741 base::RunLoop().RunUntilIdle();
5743 HttpRequestInfo info3
= CreateGetRequest();
5744 TestCompletionCallback callback3
;
5745 scoped_ptr
<HttpNetworkTransaction
> trans3(
5746 new HttpNetworkTransaction(HIGHEST
, helper
.session().get()));
5747 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
5748 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5749 base::RunLoop().RunUntilIdle();
5751 // We now have two SYN_STREAM frames queued up which will be
5752 // dequeued only once the first write completes, which we
5753 // now allow to happen.
5755 EXPECT_EQ(OK
, callback
.WaitForResult());
5757 // And now we can allow everything else to run to completion.
5760 EXPECT_EQ(OK
, callback2
.WaitForResult());
5761 EXPECT_EQ(OK
, callback3
.WaitForResult());
5763 helper
.VerifyDataConsumed();
5766 // The tests below are only for SPDY/3 and above.
5768 // Test that sent data frames and received WINDOW_UPDATE frames change
5769 // the send_window_size_ correctly.
5771 // WINDOW_UPDATE is different than most other frames in that it can arrive
5772 // while the client is still sending the request body. In order to enforce
5773 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5774 // socket data provider, so that initial read that is done as soon as the
5775 // stream is created, succeeds and schedules another read. This way reads
5776 // and writes are interleaved; after doing a full frame write, SpdyStream
5777 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5778 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5779 // since request has not been completely written, therefore we feed
5780 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5781 // write, leading to a complete write of request body; after that we send
5782 // a reply with a body, to cause a graceful shutdown.
5784 // TODO(agayev): develop a socket data provider where both, reads and
5785 // writes are ordered so that writing tests like these are easy and rewrite
5786 // all these tests using it. Right now we are working around the
5787 // limitations as described above and it's not deterministic, tests may
5788 // fail under specific circumstances.
5789 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateReceived
) {
5790 if (GetParam().protocol
< kProtoSPDY3
)
5793 static int kFrameCount
= 2;
5794 scoped_ptr
<std::string
> content(
5795 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
5796 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
5797 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
5798 scoped_ptr
<SpdyFrame
> body(
5799 spdy_util_
.ConstructSpdyBodyFrame(
5800 1, content
->c_str(), content
->size(), false));
5801 scoped_ptr
<SpdyFrame
> body_end(
5802 spdy_util_
.ConstructSpdyBodyFrame(
5803 1, content
->c_str(), content
->size(), true));
5805 MockWrite writes
[] = {
5806 CreateMockWrite(*req
, 0),
5807 CreateMockWrite(*body
, 1),
5808 CreateMockWrite(*body_end
, 2),
5811 static const int32 kDeltaWindowSize
= 0xff;
5812 static const int kDeltaCount
= 4;
5813 scoped_ptr
<SpdyFrame
> window_update(
5814 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
5815 scoped_ptr
<SpdyFrame
> window_update_dummy(
5816 spdy_util_
.ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
5817 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
5818 MockRead reads
[] = {
5819 CreateMockRead(*window_update_dummy
, 3),
5820 CreateMockRead(*window_update_dummy
, 4),
5821 CreateMockRead(*window_update_dummy
, 5),
5822 CreateMockRead(*window_update
, 6), // Four updates, therefore window
5823 CreateMockRead(*window_update
, 7), // size should increase by
5824 CreateMockRead(*window_update
, 8), // kDeltaWindowSize * 4
5825 CreateMockRead(*window_update
, 9),
5826 CreateMockRead(*resp
, 10),
5827 CreateMockRead(*body_end
, 11),
5828 MockRead(ASYNC
, 0, 0, 12) // EOF
5831 DeterministicSocketData
data(reads
, arraysize(reads
),
5832 writes
, arraysize(writes
));
5834 ScopedVector
<UploadElementReader
> element_readers
;
5835 for (int i
= 0; i
< kFrameCount
; ++i
) {
5836 element_readers
.push_back(
5837 new UploadBytesElementReader(content
->c_str(), content
->size()));
5839 UploadDataStream
upload_data_stream(&element_readers
, 0);
5841 // Setup the request
5842 HttpRequestInfo request
;
5843 request
.method
= "POST";
5844 request
.url
= GURL(kDefaultURL
);
5845 request
.upload_data_stream
= &upload_data_stream
;
5847 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
5848 BoundNetLog(), GetParam(), NULL
);
5849 helper
.SetDeterministic();
5850 helper
.AddDeterministicData(&data
);
5851 helper
.RunPreTestSetup();
5853 HttpNetworkTransaction
* trans
= helper
.trans();
5855 TestCompletionCallback callback
;
5856 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5858 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5862 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5863 ASSERT_TRUE(stream
!= NULL
);
5864 ASSERT_TRUE(stream
->stream() != NULL
);
5865 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
) +
5866 kDeltaWindowSize
* kDeltaCount
-
5867 kMaxSpdyFrameChunkSize
* kFrameCount
,
5868 stream
->stream()->send_window_size());
5872 rv
= callback
.WaitForResult();
5875 helper
.VerifyDataConsumed();
5878 // Test that received data frames and sent WINDOW_UPDATE frames change
5879 // the recv_window_size_ correctly.
5880 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateSent
) {
5881 if (GetParam().protocol
< kProtoSPDY3
)
5884 // Set the data in the body frame large enough to trigger sending a
5885 // WINDOW_UPDATE by the stream.
5886 const std::string
body_data(kSpdyStreamInitialWindowSize
/ 2 + 1, 'x');
5888 scoped_ptr
<SpdyFrame
> req(
5889 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
5890 scoped_ptr
<SpdyFrame
> session_window_update(
5891 spdy_util_
.ConstructSpdyWindowUpdate(0, body_data
.size()));
5892 scoped_ptr
<SpdyFrame
> window_update(
5893 spdy_util_
.ConstructSpdyWindowUpdate(1, body_data
.size()));
5895 std::vector
<MockWrite
> writes
;
5896 writes
.push_back(CreateMockWrite(*req
));
5897 if (GetParam().protocol
>= kProtoSPDY31
)
5898 writes
.push_back(CreateMockWrite(*session_window_update
));
5899 writes
.push_back(CreateMockWrite(*window_update
));
5901 scoped_ptr
<SpdyFrame
> resp(
5902 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
5903 scoped_ptr
<SpdyFrame
> body_no_fin(
5904 spdy_util_
.ConstructSpdyBodyFrame(
5905 1, body_data
.data(), body_data
.size(), false));
5906 scoped_ptr
<SpdyFrame
> body_fin(
5907 spdy_util_
.ConstructSpdyBodyFrame(1, NULL
, 0, true));
5908 MockRead reads
[] = {
5909 CreateMockRead(*resp
),
5910 CreateMockRead(*body_no_fin
),
5911 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Force a pause
5912 CreateMockRead(*body_fin
),
5913 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Force a pause
5914 MockRead(ASYNC
, 0, 0) // EOF
5917 DelayedSocketData
data(1, reads
, arraysize(reads
),
5918 vector_as_array(&writes
), writes
.size());
5920 NormalSpdyTransactionHelper
helper(CreateGetRequest(), DEFAULT_PRIORITY
,
5921 BoundNetLog(), GetParam(), NULL
);
5922 helper
.AddData(&data
);
5923 helper
.RunPreTestSetup();
5924 HttpNetworkTransaction
* trans
= helper
.trans();
5926 TestCompletionCallback callback
;
5927 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
5929 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5930 rv
= callback
.WaitForResult();
5933 SpdyHttpStream
* stream
=
5934 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
5935 ASSERT_TRUE(stream
!= NULL
);
5936 ASSERT_TRUE(stream
->stream() != NULL
);
5939 static_cast<int>(kSpdyStreamInitialWindowSize
- body_data
.size()),
5940 stream
->stream()->recv_window_size());
5942 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5943 ASSERT_TRUE(response
!= NULL
);
5944 ASSERT_TRUE(response
->headers
.get() != NULL
);
5945 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5946 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5948 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5949 // size increased to default.
5950 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(body_data
.size()));
5951 rv
= trans
->Read(buf
.get(), body_data
.size(), CompletionCallback());
5952 EXPECT_EQ(static_cast<int>(body_data
.size()), rv
);
5953 std::string
content(buf
->data(), buf
->data() + body_data
.size());
5954 EXPECT_EQ(body_data
, content
);
5956 // Schedule the reading of empty data frame with FIN
5957 data
.CompleteRead();
5959 // Force write of WINDOW_UPDATE which was scheduled during the above
5961 base::RunLoop().RunUntilIdle();
5964 data
.CompleteRead();
5966 helper
.VerifyDataConsumed();
5969 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5970 TEST_P(SpdyNetworkTransactionTest
, WindowUpdateOverflow
) {
5971 if (GetParam().protocol
< kProtoSPDY3
)
5974 // Number of full frames we hope to write (but will not, used to
5975 // set content-length header correctly)
5976 static int kFrameCount
= 3;
5978 scoped_ptr
<std::string
> content(
5979 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
5980 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
5981 kRequestUrl
, 1, kMaxSpdyFrameChunkSize
* kFrameCount
, LOWEST
, NULL
, 0));
5982 scoped_ptr
<SpdyFrame
> body(
5983 spdy_util_
.ConstructSpdyBodyFrame(
5984 1, content
->c_str(), content
->size(), false));
5985 scoped_ptr
<SpdyFrame
> rst(
5986 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
5988 // We're not going to write a data frame with FIN, we'll receive a bad
5989 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5990 MockWrite writes
[] = {
5991 CreateMockWrite(*req
, 0),
5992 CreateMockWrite(*body
, 2),
5993 CreateMockWrite(*rst
, 3),
5996 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
5997 scoped_ptr
<SpdyFrame
> window_update(
5998 spdy_util_
.ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
5999 MockRead reads
[] = {
6000 CreateMockRead(*window_update
, 1),
6001 MockRead(ASYNC
, 0, 4) // EOF
6004 DeterministicSocketData
data(reads
, arraysize(reads
),
6005 writes
, arraysize(writes
));
6007 ScopedVector
<UploadElementReader
> element_readers
;
6008 for (int i
= 0; i
< kFrameCount
; ++i
) {
6009 element_readers
.push_back(
6010 new UploadBytesElementReader(content
->c_str(), content
->size()));
6012 UploadDataStream
upload_data_stream(&element_readers
, 0);
6014 // Setup the request
6015 HttpRequestInfo request
;
6016 request
.method
= "POST";
6017 request
.url
= GURL("http://www.google.com/");
6018 request
.upload_data_stream
= &upload_data_stream
;
6020 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6021 BoundNetLog(), GetParam(), NULL
);
6022 helper
.SetDeterministic();
6023 helper
.RunPreTestSetup();
6024 helper
.AddDeterministicData(&data
);
6025 HttpNetworkTransaction
* trans
= helper
.trans();
6027 TestCompletionCallback callback
;
6028 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6029 ASSERT_EQ(ERR_IO_PENDING
, rv
);
6032 ASSERT_TRUE(callback
.have_result());
6033 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
6034 helper
.VerifyDataConsumed();
6037 // Test that after hitting a send window size of 0, the write process
6038 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6040 // This test constructs a POST request followed by enough data frames
6041 // containing 'a' that would make the window size 0, followed by another
6042 // data frame containing default content (which is "hello!") and this frame
6043 // also contains a FIN flag. DelayedSocketData is used to enforce all
6044 // writes go through before a read could happen. However, the last frame
6045 // ("hello!") is not supposed to go through since by the time its turn
6046 // arrives, window size is 0. At this point MessageLoop::Run() called via
6047 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6048 // which returns after performing all possible writes. We use DCHECKS to
6049 // ensure that last data frame is still there and stream has stalled.
6050 // After that, next read is artifically enforced, which causes a
6051 // WINDOW_UPDATE to be read and I/O process resumes.
6052 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResume
) {
6053 if (GetParam().protocol
< kProtoSPDY3
)
6056 // Number of frames we need to send to zero out the window size: data
6057 // frames plus SYN_STREAM plus the last data frame; also we need another
6058 // data frame that we will send once the WINDOW_UPDATE is received,
6060 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6062 // Calculate last frame's size; 0 size data frame is legal.
6063 size_t last_frame_size
=
6064 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6066 // Construct content for a data frame of maximum size.
6067 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6069 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6070 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6074 scoped_ptr
<SpdyFrame
> body1(
6075 spdy_util_
.ConstructSpdyBodyFrame(
6076 1, content
.c_str(), content
.size(), false));
6078 // Last frame to zero out the window size.
6079 scoped_ptr
<SpdyFrame
> body2(
6080 spdy_util_
.ConstructSpdyBodyFrame(
6081 1, content
.c_str(), last_frame_size
, false));
6083 // Data frame to be sent once WINDOW_UPDATE frame is received.
6084 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6086 // Fill in mock writes.
6087 scoped_ptr
<MockWrite
[]> writes(new MockWrite
[num_writes
]);
6089 writes
[i
] = CreateMockWrite(*req
);
6090 for (i
= 1; i
< num_writes
- 2; i
++)
6091 writes
[i
] = CreateMockWrite(*body1
);
6092 writes
[i
++] = CreateMockWrite(*body2
);
6093 writes
[i
] = CreateMockWrite(*body3
);
6095 // Construct read frame, give enough space to upload the rest of the
6097 scoped_ptr
<SpdyFrame
> session_window_update(
6098 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6099 scoped_ptr
<SpdyFrame
> window_update(
6100 spdy_util_
.ConstructSpdyWindowUpdate(1, kUploadDataSize
));
6101 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6102 MockRead reads
[] = {
6103 CreateMockRead(*session_window_update
),
6104 CreateMockRead(*session_window_update
),
6105 CreateMockRead(*window_update
),
6106 CreateMockRead(*window_update
),
6107 CreateMockRead(*reply
),
6108 CreateMockRead(*body2
),
6109 CreateMockRead(*body3
),
6110 MockRead(ASYNC
, 0, 0) // EOF
6113 // Skip the session window updates unless we're using SPDY/3.1 and
6115 size_t read_offset
= (GetParam().protocol
>= kProtoSPDY31
) ? 0 : 2;
6116 size_t num_reads
= arraysize(reads
) - read_offset
;
6118 // Force all writes to happen before any read, last write will not
6119 // actually queue a frame, due to window size being 0.
6120 DelayedSocketData
data(num_writes
, reads
+ read_offset
, num_reads
,
6121 writes
.get(), num_writes
);
6123 ScopedVector
<UploadElementReader
> element_readers
;
6124 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6125 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6126 element_readers
.push_back(new UploadBytesElementReader(
6127 upload_data_string
.c_str(), upload_data_string
.size()));
6128 UploadDataStream
upload_data_stream(&element_readers
, 0);
6130 HttpRequestInfo request
;
6131 request
.method
= "POST";
6132 request
.url
= GURL("http://www.google.com/");
6133 request
.upload_data_stream
= &upload_data_stream
;
6134 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6135 BoundNetLog(), GetParam(), NULL
);
6136 helper
.AddData(&data
);
6137 helper
.RunPreTestSetup();
6139 HttpNetworkTransaction
* trans
= helper
.trans();
6141 TestCompletionCallback callback
;
6142 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6143 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6145 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6147 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6148 ASSERT_TRUE(stream
!= NULL
);
6149 ASSERT_TRUE(stream
->stream() != NULL
);
6150 EXPECT_EQ(0, stream
->stream()->send_window_size());
6151 // All the body data should have been read.
6152 // TODO(satorux): This is because of the weirdness in reading the request
6153 // body in OnSendBodyComplete(). See crbug.com/113107.
6154 EXPECT_TRUE(upload_data_stream
.IsEOF());
6155 // But the body is not yet fully sent (kUploadData is not yet sent)
6156 // since we're send-stalled.
6157 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6159 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6160 rv
= callback
.WaitForResult();
6161 helper
.VerifyDataConsumed();
6164 // Test we correctly handle the case where the SETTINGS frame results in
6165 // unstalling the send window.
6166 TEST_P(SpdyNetworkTransactionTest
, FlowControlStallResumeAfterSettings
) {
6167 if (GetParam().protocol
< kProtoSPDY3
)
6170 // Number of frames we need to send to zero out the window size: data
6171 // frames plus SYN_STREAM plus the last data frame; also we need another
6172 // data frame that we will send once the SETTING is received, therefore +3.
6173 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6175 // Calculate last frame's size; 0 size data frame is legal.
6176 size_t last_frame_size
=
6177 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6179 // Construct content for a data frame of maximum size.
6180 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6182 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6183 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6187 scoped_ptr
<SpdyFrame
> body1(
6188 spdy_util_
.ConstructSpdyBodyFrame(
6189 1, content
.c_str(), content
.size(), false));
6191 // Last frame to zero out the window size.
6192 scoped_ptr
<SpdyFrame
> body2(
6193 spdy_util_
.ConstructSpdyBodyFrame(
6194 1, content
.c_str(), last_frame_size
, false));
6196 // Data frame to be sent once SETTINGS frame is received.
6197 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6199 // Fill in mock reads/writes.
6200 std::vector
<MockRead
> reads
;
6201 std::vector
<MockWrite
> writes
;
6203 writes
.push_back(CreateMockWrite(*req
, i
++));
6204 while (i
< num_writes
- 2)
6205 writes
.push_back(CreateMockWrite(*body1
, i
++));
6206 writes
.push_back(CreateMockWrite(*body2
, i
++));
6208 // Construct read frame for SETTINGS that gives enough space to upload the
6209 // rest of the data.
6210 SettingsMap settings
;
6211 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6212 SettingsFlagsAndValue(
6213 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
* 2);
6214 scoped_ptr
<SpdyFrame
> settings_frame_large(
6215 spdy_util_
.ConstructSpdySettings(settings
));
6217 reads
.push_back(CreateMockRead(*settings_frame_large
, i
++));
6219 scoped_ptr
<SpdyFrame
> session_window_update(
6220 spdy_util_
.ConstructSpdyWindowUpdate(0, kUploadDataSize
));
6221 if (GetParam().protocol
>= kProtoSPDY31
)
6222 reads
.push_back(CreateMockRead(*session_window_update
, i
++));
6224 writes
.push_back(CreateMockWrite(*body3
, i
++));
6226 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6227 reads
.push_back(CreateMockRead(*reply
, i
++));
6228 reads
.push_back(CreateMockRead(*body2
, i
++));
6229 reads
.push_back(CreateMockRead(*body3
, i
++));
6230 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6232 // Force all writes to happen before any read, last write will not
6233 // actually queue a frame, due to window size being 0.
6234 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6235 vector_as_array(&writes
), writes
.size());
6237 ScopedVector
<UploadElementReader
> element_readers
;
6238 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6239 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6240 element_readers
.push_back(new UploadBytesElementReader(
6241 upload_data_string
.c_str(), upload_data_string
.size()));
6242 UploadDataStream
upload_data_stream(&element_readers
, 0);
6244 HttpRequestInfo request
;
6245 request
.method
= "POST";
6246 request
.url
= GURL("http://www.google.com/");
6247 request
.upload_data_stream
= &upload_data_stream
;
6248 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6249 BoundNetLog(), GetParam(), NULL
);
6250 helper
.SetDeterministic();
6251 helper
.RunPreTestSetup();
6252 helper
.AddDeterministicData(&data
);
6254 HttpNetworkTransaction
* trans
= helper
.trans();
6256 TestCompletionCallback callback
;
6257 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6258 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6260 data
.RunFor(num_writes
- 1); // Write as much as we can.
6262 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6263 ASSERT_TRUE(stream
!= NULL
);
6264 ASSERT_TRUE(stream
->stream() != NULL
);
6265 EXPECT_EQ(0, stream
->stream()->send_window_size());
6267 // All the body data should have been read.
6268 // TODO(satorux): This is because of the weirdness in reading the request
6269 // body in OnSendBodyComplete(). See crbug.com/113107.
6270 EXPECT_TRUE(upload_data_stream
.IsEOF());
6271 // But the body is not yet fully sent (kUploadData is not yet sent)
6272 // since we're send-stalled.
6273 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6275 data
.RunFor(6); // Read in SETTINGS frame to unstall.
6276 rv
= callback
.WaitForResult();
6277 helper
.VerifyDataConsumed();
6278 // If stream is NULL, that means it was unstalled and closed.
6279 EXPECT_TRUE(stream
->stream() == NULL
);
6282 // Test we correctly handle the case where the SETTINGS frame results in a
6283 // negative send window size.
6284 TEST_P(SpdyNetworkTransactionTest
, FlowControlNegativeSendWindowSize
) {
6285 if (GetParam().protocol
< kProtoSPDY3
)
6288 // Number of frames we need to send to zero out the window size: data
6289 // frames plus SYN_STREAM plus the last data frame; also we need another
6290 // data frame that we will send once the SETTING is received, therefore +3.
6291 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
6293 // Calculate last frame's size; 0 size data frame is legal.
6294 size_t last_frame_size
=
6295 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
6297 // Construct content for a data frame of maximum size.
6298 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
6300 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
6301 kRequestUrl
, 1, kSpdyStreamInitialWindowSize
+ kUploadDataSize
,
6305 scoped_ptr
<SpdyFrame
> body1(
6306 spdy_util_
.ConstructSpdyBodyFrame(
6307 1, content
.c_str(), content
.size(), false));
6309 // Last frame to zero out the window size.
6310 scoped_ptr
<SpdyFrame
> body2(
6311 spdy_util_
.ConstructSpdyBodyFrame(
6312 1, content
.c_str(), last_frame_size
, false));
6314 // Data frame to be sent once SETTINGS frame is received.
6315 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6317 // Fill in mock reads/writes.
6318 std::vector
<MockRead
> reads
;
6319 std::vector
<MockWrite
> writes
;
6321 writes
.push_back(CreateMockWrite(*req
, i
++));
6322 while (i
< num_writes
- 2)
6323 writes
.push_back(CreateMockWrite(*body1
, i
++));
6324 writes
.push_back(CreateMockWrite(*body2
, i
++));
6326 // Construct read frame for SETTINGS that makes the send_window_size
6328 SettingsMap new_settings
;
6329 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
6330 SettingsFlagsAndValue(
6331 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
/ 2);
6332 scoped_ptr
<SpdyFrame
> settings_frame_small(
6333 spdy_util_
.ConstructSpdySettings(new_settings
));
6334 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6336 scoped_ptr
<SpdyFrame
> session_window_update_init_size(
6337 spdy_util_
.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize
));
6338 scoped_ptr
<SpdyFrame
> window_update_init_size(
6339 spdy_util_
.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize
));
6341 reads
.push_back(CreateMockRead(*settings_frame_small
, i
++));
6343 if (GetParam().protocol
>= kProtoSPDY3
)
6344 reads
.push_back(CreateMockRead(*session_window_update_init_size
, i
++));
6346 reads
.push_back(CreateMockRead(*window_update_init_size
, i
++));
6348 writes
.push_back(CreateMockWrite(*body3
, i
++));
6350 scoped_ptr
<SpdyFrame
> reply(spdy_util_
.ConstructSpdyPostSynReply(NULL
, 0));
6351 reads
.push_back(CreateMockRead(*reply
, i
++));
6352 reads
.push_back(CreateMockRead(*body2
, i
++));
6353 reads
.push_back(CreateMockRead(*body3
, i
++));
6354 reads
.push_back(MockRead(ASYNC
, 0, i
++)); // EOF
6356 // Force all writes to happen before any read, last write will not
6357 // actually queue a frame, due to window size being 0.
6358 DeterministicSocketData
data(vector_as_array(&reads
), reads
.size(),
6359 vector_as_array(&writes
), writes
.size());
6361 ScopedVector
<UploadElementReader
> element_readers
;
6362 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
6363 upload_data_string
.append(kUploadData
, kUploadDataSize
);
6364 element_readers
.push_back(new UploadBytesElementReader(
6365 upload_data_string
.c_str(), upload_data_string
.size()));
6366 UploadDataStream
upload_data_stream(&element_readers
, 0);
6368 HttpRequestInfo request
;
6369 request
.method
= "POST";
6370 request
.url
= GURL("http://www.google.com/");
6371 request
.upload_data_stream
= &upload_data_stream
;
6372 NormalSpdyTransactionHelper
helper(request
, DEFAULT_PRIORITY
,
6373 BoundNetLog(), GetParam(), NULL
);
6374 helper
.SetDeterministic();
6375 helper
.RunPreTestSetup();
6376 helper
.AddDeterministicData(&data
);
6378 HttpNetworkTransaction
* trans
= helper
.trans();
6380 TestCompletionCallback callback
;
6381 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
6382 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6384 data
.RunFor(num_writes
- 1); // Write as much as we can.
6386 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
6387 ASSERT_TRUE(stream
!= NULL
);
6388 ASSERT_TRUE(stream
->stream() != NULL
);
6389 EXPECT_EQ(0, stream
->stream()->send_window_size());
6391 // All the body data should have been read.
6392 // TODO(satorux): This is because of the weirdness in reading the request
6393 // body in OnSendBodyComplete(). See crbug.com/113107.
6394 EXPECT_TRUE(upload_data_stream
.IsEOF());
6395 // But the body is not yet fully sent (kUploadData is not yet sent)
6396 // since we're send-stalled.
6397 EXPECT_TRUE(stream
->stream()->send_stalled_by_flow_control());
6399 // Read in WINDOW_UPDATE or SETTINGS frame.
6400 data
.RunFor((GetParam().protocol
>= kProtoSPDY31
) ? 8 : 7);
6401 rv
= callback
.WaitForResult();
6402 helper
.VerifyDataConsumed();