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.
5 #include "net/http/http_network_transaction.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/scoped_vector.h"
15 #include "net/base/auth.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/upload_bytes_element_reader.h"
18 #include "net/base/upload_data_stream.h"
19 #include "net/base/upload_file_element_reader.h"
20 #include "net/http/http_network_session_peer.h"
21 #include "net/http/http_transaction_unittest.h"
22 #include "net/socket/client_socket_pool_base.h"
23 #include "net/spdy/buffered_spdy_framer.h"
24 #include "net/spdy/spdy_http_stream.h"
25 #include "net/spdy/spdy_http_utils.h"
26 #include "net/spdy/spdy_session.h"
27 #include "net/spdy/spdy_session_pool.h"
28 #include "net/spdy/spdy_test_util_spdy3.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/platform_test.h"
32 using namespace net::test_spdy3
;
34 //-----------------------------------------------------------------------------
38 enum SpdyNetworkTransactionSpdy3TestTypes
{
44 class SpdyNetworkTransactionSpdy3Test
45 : public ::testing::TestWithParam
<SpdyNetworkTransactionSpdy3TestTypes
> {
48 virtual void SetUp() {
49 google_get_request_initialized_
= false;
50 google_post_request_initialized_
= false;
51 google_chunked_post_request_initialized_
= false;
52 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
55 virtual void TearDown() {
56 UploadDataStream::ResetMergeChunks();
57 // Empty the current queue.
58 MessageLoop::current()->RunUntilIdle();
61 void set_merge_chunks(bool merge
) {
62 UploadDataStream::set_merge_chunks(merge
);
65 struct TransactionHelperResult
{
67 std::string status_line
;
68 std::string response_data
;
69 HttpResponseInfo response_info
;
72 // A helper class that handles all the initial npn/ssl setup.
73 class NormalSpdyTransactionHelper
{
75 NormalSpdyTransactionHelper(const HttpRequestInfo
& request
,
76 const BoundNetLog
& log
,
77 SpdyNetworkTransactionSpdy3TestTypes test_type
,
78 SpdySessionDependencies
* session_deps
)
80 session_deps_(session_deps
== NULL
?
81 new SpdySessionDependencies() : session_deps
),
82 session_(SpdySessionDependencies::SpdyCreateSession(
83 session_deps_
.get())),
85 test_type_(test_type
),
86 deterministic_(false),
101 ~NormalSpdyTransactionHelper() {
102 // Any test which doesn't close the socket by sending it an EOF will
103 // have a valid session left open, which leaks the entire session pool.
104 // This is just fine - in fact, some of our tests intentionally do this
105 // so that we can check consistency of the SpdySessionPool as the test
106 // finishes. If we had put an EOF on the socket, the SpdySession would
107 // have closed and we wouldn't be able to check the consistency.
109 // Forcefully close existing sessions here.
110 session()->spdy_session_pool()->CloseAllSessions();
113 void SetDeterministic() {
114 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
115 session_deps_
.get());
116 deterministic_
= true;
119 void SetSpdyDisabled() {
120 spdy_enabled_
= false;
124 void RunPreTestSetup() {
125 if (!session_deps_
.get())
126 session_deps_
.reset(new SpdySessionDependencies());
128 session_
= SpdySessionDependencies::SpdyCreateSession(
129 session_deps_
.get());
130 HttpStreamFactory::set_use_alternate_protocols(false);
131 HttpStreamFactory::set_force_spdy_over_ssl(false);
132 HttpStreamFactory::set_force_spdy_always(false);
134 std::vector
<std::string
> next_protos
;
135 next_protos
.push_back("http/1.1");
136 next_protos
.push_back("spdy/2");
137 next_protos
.push_back("spdy/3");
139 switch (test_type_
) {
141 session_
->http_server_properties()->SetAlternateProtocol(
142 HostPortPair("www.google.com", 80), 443,
144 HttpStreamFactory::set_use_alternate_protocols(true);
145 HttpStreamFactory::SetNextProtos(next_protos
);
148 HttpStreamFactory::set_force_spdy_over_ssl(false);
149 HttpStreamFactory::set_force_spdy_always(true);
152 HttpStreamFactory::set_force_spdy_over_ssl(true);
153 HttpStreamFactory::set_force_spdy_always(true);
159 // We're now ready to use SSL-npn SPDY.
160 trans_
.reset(new HttpNetworkTransaction(session_
));
163 // Start the transaction, read some data, finish.
164 void RunDefaultTest() {
165 output_
.rv
= trans_
->Start(&request_
, callback
.callback(), log_
);
167 // We expect an IO Pending or some sort of error.
168 EXPECT_LT(output_
.rv
, 0);
169 if (output_
.rv
!= ERR_IO_PENDING
)
172 output_
.rv
= callback
.WaitForResult();
173 if (output_
.rv
!= OK
) {
174 session_
->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED
);
179 const HttpResponseInfo
* response
= trans_
->GetResponseInfo();
180 ASSERT_TRUE(response
!= NULL
);
181 ASSERT_TRUE(response
->headers
!= NULL
);
182 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
183 EXPECT_EQ(spdy_enabled_
, response
->was_fetched_via_spdy
);
184 if (test_type_
== SPDYNPN
&& spdy_enabled_
) {
185 EXPECT_TRUE(response
->was_npn_negotiated
);
187 EXPECT_TRUE(!response
->was_npn_negotiated
);
189 // If SPDY is not enabled, a HTTP request should not be diverted
190 // over a SSL session.
191 if (!spdy_enabled_
) {
192 EXPECT_EQ(request_
.url
.SchemeIs("https"),
193 response
->was_npn_negotiated
);
195 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
196 EXPECT_EQ(port_
, response
->socket_address
.port());
197 output_
.status_line
= response
->headers
->GetStatusLine();
198 output_
.response_info
= *response
; // Make a copy so we can verify.
199 output_
.rv
= ReadTransaction(trans_
.get(), &output_
.response_data
);
202 // Most tests will want to call this function. In particular, the MockReads
203 // should end with an empty read, and that read needs to be processed to
204 // ensure proper deletion of the spdy_session_pool.
205 void VerifyDataConsumed() {
206 for (DataVector::iterator it
= data_vector_
.begin();
207 it
!= data_vector_
.end(); ++it
) {
208 EXPECT_TRUE((*it
)->at_read_eof()) << "Read count: "
209 << (*it
)->read_count()
211 << (*it
)->read_index();
212 EXPECT_TRUE((*it
)->at_write_eof()) << "Write count: "
213 << (*it
)->write_count()
215 << (*it
)->write_index();
219 // Occasionally a test will expect to error out before certain reads are
220 // processed. In that case we want to explicitly ensure that the reads were
222 void VerifyDataNotConsumed() {
223 for (DataVector::iterator it
= data_vector_
.begin();
224 it
!= data_vector_
.end(); ++it
) {
225 EXPECT_TRUE(!(*it
)->at_read_eof()) << "Read count: "
226 << (*it
)->read_count()
228 << (*it
)->read_index();
229 EXPECT_TRUE(!(*it
)->at_write_eof()) << "Write count: "
230 << (*it
)->write_count()
232 << (*it
)->write_index();
236 void RunToCompletion(StaticSocketDataProvider
* data
) {
240 VerifyDataConsumed();
243 void AddData(StaticSocketDataProvider
* data
) {
244 DCHECK(!deterministic_
);
245 data_vector_
.push_back(data
);
246 SSLSocketDataProvider
* ssl_provider
=
247 new SSLSocketDataProvider(ASYNC
, OK
);
248 if (test_type_
== SPDYNPN
)
249 ssl_provider
->SetNextProto(kProtoSPDY3
);
251 ssl_vector_
.push_back(ssl_provider
);
252 if (test_type_
== SPDYNPN
|| test_type_
== SPDYSSL
)
253 session_deps_
->socket_factory
->AddSSLSocketDataProvider(ssl_provider
);
255 session_deps_
->socket_factory
->AddSocketDataProvider(data
);
256 if (test_type_
== SPDYNPN
) {
257 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
258 StaticSocketDataProvider
* hanging_non_alternate_protocol_socket
=
259 new StaticSocketDataProvider(NULL
, 0, NULL
, 0);
260 hanging_non_alternate_protocol_socket
->set_connect_data(
261 never_finishing_connect
);
262 session_deps_
->socket_factory
->AddSocketDataProvider(
263 hanging_non_alternate_protocol_socket
);
264 alternate_vector_
.push_back(hanging_non_alternate_protocol_socket
);
268 void AddDeterministicData(DeterministicSocketData
* data
) {
269 DCHECK(deterministic_
);
270 data_vector_
.push_back(data
);
271 SSLSocketDataProvider
* ssl_provider
=
272 new SSLSocketDataProvider(ASYNC
, OK
);
273 if (test_type_
== SPDYNPN
)
274 ssl_provider
->SetNextProto(kProtoSPDY3
);
276 ssl_vector_
.push_back(ssl_provider
);
277 if (test_type_
== SPDYNPN
|| test_type_
== SPDYSSL
) {
278 session_deps_
->deterministic_socket_factory
->
279 AddSSLSocketDataProvider(ssl_provider
);
281 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(data
);
282 if (test_type_
== SPDYNPN
) {
283 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
284 DeterministicSocketData
* hanging_non_alternate_protocol_socket
=
285 new DeterministicSocketData(NULL
, 0, NULL
, 0);
286 hanging_non_alternate_protocol_socket
->set_connect_data(
287 never_finishing_connect
);
288 session_deps_
->deterministic_socket_factory
->AddSocketDataProvider(
289 hanging_non_alternate_protocol_socket
);
290 alternate_deterministic_vector_
.push_back(
291 hanging_non_alternate_protocol_socket
);
295 void SetSession(const scoped_refptr
<HttpNetworkSession
>& session
) {
298 HttpNetworkTransaction
* trans() { return trans_
.get(); }
299 void ResetTrans() { trans_
.reset(); }
300 TransactionHelperResult
& output() { return output_
; }
301 const HttpRequestInfo
& request() const { return request_
; }
302 const scoped_refptr
<HttpNetworkSession
>& session() const {
305 scoped_ptr
<SpdySessionDependencies
>& session_deps() {
306 return session_deps_
;
308 int port() const { return port_
; }
309 SpdyNetworkTransactionSpdy3TestTypes
test_type() const {
314 typedef std::vector
<StaticSocketDataProvider
*> DataVector
;
315 typedef ScopedVector
<SSLSocketDataProvider
> SSLVector
;
316 typedef ScopedVector
<StaticSocketDataProvider
> AlternateVector
;
317 typedef ScopedVector
<DeterministicSocketData
> AlternateDeterministicVector
;
318 HttpRequestInfo request_
;
319 scoped_ptr
<SpdySessionDependencies
> session_deps_
;
320 scoped_refptr
<HttpNetworkSession
> session_
;
321 TransactionHelperResult output_
;
322 scoped_ptr
<StaticSocketDataProvider
> first_transaction_
;
323 SSLVector ssl_vector_
;
324 TestCompletionCallback callback
;
325 scoped_ptr
<HttpNetworkTransaction
> trans_
;
326 scoped_ptr
<HttpNetworkTransaction
> trans_http_
;
327 DataVector data_vector_
;
328 AlternateVector alternate_vector_
;
329 AlternateDeterministicVector alternate_deterministic_vector_
;
330 const BoundNetLog
& log_
;
331 SpdyNetworkTransactionSpdy3TestTypes test_type_
;
337 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
338 int expected_status
);
340 void ConnectStatusHelper(const MockRead
& status
);
342 const HttpRequestInfo
& CreateGetPushRequest() {
343 google_get_push_request_
.method
= "GET";
344 google_get_push_request_
.url
= GURL("http://www.google.com/foo.dat");
345 google_get_push_request_
.load_flags
= 0;
346 return google_get_push_request_
;
349 const HttpRequestInfo
& CreateGetRequest() {
350 if (!google_get_request_initialized_
) {
351 google_get_request_
.method
= "GET";
352 google_get_request_
.url
= GURL(kDefaultURL
);
353 google_get_request_
.load_flags
= 0;
354 google_get_request_initialized_
= true;
356 return google_get_request_
;
359 const HttpRequestInfo
& CreateGetRequestWithUserAgent() {
360 if (!google_get_request_initialized_
) {
361 google_get_request_
.method
= "GET";
362 google_get_request_
.url
= GURL(kDefaultURL
);
363 google_get_request_
.load_flags
= 0;
364 google_get_request_
.extra_headers
.SetHeader("User-Agent", "Chrome");
365 google_get_request_initialized_
= true;
367 return google_get_request_
;
370 const HttpRequestInfo
& CreatePostRequest() {
371 if (!google_post_request_initialized_
) {
372 ScopedVector
<UploadElementReader
> element_readers
;
373 element_readers
.push_back(
374 new UploadBytesElementReader(kUploadData
, kUploadDataSize
));
375 upload_data_stream_
.reset(new UploadDataStream(&element_readers
, 0));
377 google_post_request_
.method
= "POST";
378 google_post_request_
.url
= GURL(kDefaultURL
);
379 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
380 google_post_request_initialized_
= true;
382 return google_post_request_
;
385 const HttpRequestInfo
& CreateFilePostRequest() {
386 if (!google_post_request_initialized_
) {
388 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
389 CHECK_EQ(static_cast<int>(kUploadDataSize
),
390 file_util::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
392 ScopedVector
<UploadElementReader
> element_readers
;
393 element_readers
.push_back(new UploadFileElementReader(
394 base::MessageLoopProxy::current(),
395 file_path
, 0, kUploadDataSize
, base::Time()));
396 upload_data_stream_
.reset(new UploadDataStream(&element_readers
, 0));
398 google_post_request_
.method
= "POST";
399 google_post_request_
.url
= GURL(kDefaultURL
);
400 google_post_request_
.upload_data_stream
= upload_data_stream_
.get();
401 google_post_request_initialized_
= true;
403 return google_post_request_
;
406 const HttpRequestInfo
& CreateComplexPostRequest() {
407 if (!google_post_request_initialized_
) {
408 const int kFileRangeOffset
= 1;
409 const int kFileRangeLength
= 3;
410 CHECK_LT(kFileRangeOffset
+ kFileRangeLength
, kUploadDataSize
);
413 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_
.path(), &file_path
));
414 CHECK_EQ(static_cast<int>(kUploadDataSize
),
415 file_util::WriteFile(file_path
, kUploadData
, kUploadDataSize
));
417 ScopedVector
<UploadElementReader
> element_readers
;
418 element_readers
.push_back(
419 new UploadBytesElementReader(kUploadData
, kFileRangeOffset
));
420 element_readers
.push_back(new UploadFileElementReader(
421 base::MessageLoopProxy::current(),
422 file_path
, kFileRangeOffset
, kFileRangeLength
, base::Time()));
423 element_readers
.push_back(new UploadBytesElementReader(
424 kUploadData
+ kFileRangeOffset
+ kFileRangeLength
,
425 kUploadDataSize
- (kFileRangeOffset
+ kFileRangeLength
)));
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
& CreateChunkedPostRequest() {
437 if (!google_chunked_post_request_initialized_
) {
438 upload_data_stream_
.reset(
439 new UploadDataStream(UploadDataStream::CHUNKED
, 0));
440 upload_data_stream_
->AppendChunk(kUploadData
, kUploadDataSize
, false);
441 upload_data_stream_
->AppendChunk(kUploadData
, kUploadDataSize
, true);
443 google_chunked_post_request_
.method
= "POST";
444 google_chunked_post_request_
.url
= GURL(kDefaultURL
);
445 google_chunked_post_request_
.upload_data_stream
=
446 upload_data_stream_
.get();
447 google_chunked_post_request_initialized_
= true;
449 return google_chunked_post_request_
;
452 // Read the result of a particular transaction, knowing that we've got
453 // multiple transactions in the read pipeline; so as we read, we may have
454 // to skip over data destined for other transactions while we consume
455 // the data for |trans|.
456 int ReadResult(HttpNetworkTransaction
* trans
,
457 StaticSocketDataProvider
* data
,
458 std::string
* result
) {
459 const int kSize
= 3000;
462 scoped_refptr
<net::IOBufferWithSize
> buf(new net::IOBufferWithSize(kSize
));
463 TestCompletionCallback callback
;
465 int rv
= trans
->Read(buf
, kSize
, callback
.callback());
466 if (rv
== ERR_IO_PENDING
) {
467 // Multiple transactions may be in the data set. Keep pulling off
468 // reads until we complete our callback.
469 while (!callback
.have_result()) {
470 data
->CompleteRead();
471 MessageLoop::current()->RunUntilIdle();
473 rv
= callback
.WaitForResult();
474 } else if (rv
<= 0) {
477 result
->append(buf
->data(), rv
);
483 void VerifyStreamsClosed(const NormalSpdyTransactionHelper
& helper
) {
484 // This lengthy block is reaching into the pool to dig out the active
485 // session. Once we have the session, we verify that the streams are
486 // all closed and not leaked at this point.
487 const GURL
& url
= helper
.request().url
;
488 int port
= helper
.test_type() == SPDYNPN
? 443 : 80;
489 HostPortPair
host_port_pair(url
.host(), port
);
490 HostPortProxyPair
pair(host_port_pair
, ProxyServer::Direct());
492 const scoped_refptr
<HttpNetworkSession
>& session
= helper
.session();
493 SpdySessionPool
* pool(session
->spdy_session_pool());
494 EXPECT_TRUE(pool
->HasSession(pair
));
495 scoped_refptr
<SpdySession
> spdy_session(pool
->Get(pair
, log
));
496 ASSERT_TRUE(spdy_session
.get() != NULL
);
497 EXPECT_EQ(0u, spdy_session
->num_active_streams());
498 EXPECT_EQ(0u, spdy_session
->num_unclaimed_pushed_streams());
501 void RunServerPushTest(OrderedSocketData
* data
,
502 HttpResponseInfo
* response
,
503 HttpResponseInfo
* push_response
,
504 std::string
& expected
) {
505 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
506 BoundNetLog(), GetParam(), NULL
);
507 helper
.RunPreTestSetup();
508 helper
.AddData(data
);
510 HttpNetworkTransaction
* trans
= helper
.trans();
512 // Start the transaction with basic parameters.
513 TestCompletionCallback callback
;
514 int rv
= trans
->Start(
515 &CreateGetRequest(), callback
.callback(), BoundNetLog());
516 EXPECT_EQ(ERR_IO_PENDING
, rv
);
517 rv
= callback
.WaitForResult();
519 // Request the pushed path.
520 scoped_ptr
<HttpNetworkTransaction
> trans2(
521 new HttpNetworkTransaction(helper
.session()));
523 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
524 EXPECT_EQ(ERR_IO_PENDING
, rv
);
525 MessageLoop::current()->RunUntilIdle();
527 // The data for the pushed path may be coming in more than 1 packet. Compile
528 // the results into a single string.
530 // Read the server push body.
532 ReadResult(trans2
.get(), data
, &result2
);
533 // Read the response body.
535 ReadResult(trans
, data
, &result
);
537 // Verify that we consumed all test data.
538 EXPECT_TRUE(data
->at_read_eof());
539 EXPECT_TRUE(data
->at_write_eof());
541 // Verify that the received push data is same as the expected push data.
542 EXPECT_EQ(result2
.compare(expected
), 0) << "Received data: "
544 << "||||| Expected data: "
547 // Verify the SYN_REPLY.
548 // Copy the response info, because trans goes away.
549 *response
= *trans
->GetResponseInfo();
550 *push_response
= *trans2
->GetResponseInfo();
552 VerifyStreamsClosed(helper
);
555 static void DeleteSessionCallback(NormalSpdyTransactionHelper
* helper
,
557 helper
->ResetTrans();
560 static void StartTransactionCallback(
561 const scoped_refptr
<HttpNetworkSession
>& session
,
563 scoped_ptr
<HttpNetworkTransaction
> trans(
564 new HttpNetworkTransaction(session
));
565 TestCompletionCallback callback
;
566 HttpRequestInfo request
;
567 request
.method
= "GET";
568 request
.url
= GURL("http://www.google.com/");
569 request
.load_flags
= 0;
570 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
571 EXPECT_EQ(ERR_IO_PENDING
, rv
);
572 callback
.WaitForResult();
576 scoped_ptr
<UploadDataStream
> upload_data_stream_
;
577 bool google_get_request_initialized_
;
578 bool google_post_request_initialized_
;
579 bool google_chunked_post_request_initialized_
;
580 HttpRequestInfo google_get_request_
;
581 HttpRequestInfo google_post_request_
;
582 HttpRequestInfo google_chunked_post_request_
;
583 HttpRequestInfo google_get_push_request_
;
584 base::ScopedTempDir temp_dir_
;
587 //-----------------------------------------------------------------------------
588 // All tests are run with three different connection types: SPDY after NPN
589 // negotiation, SPDY without SSL, and SPDY with SSL.
590 INSTANTIATE_TEST_CASE_P(Spdy
,
591 SpdyNetworkTransactionSpdy3Test
,
592 ::testing::Values(SPDYNOSSL
, SPDYSSL
, SPDYNPN
));
595 // Verify HttpNetworkTransaction constructor.
596 TEST_P(SpdyNetworkTransactionSpdy3Test
, Constructor
) {
597 SpdySessionDependencies session_deps
;
598 scoped_refptr
<HttpNetworkSession
> session(
599 SpdySessionDependencies::SpdyCreateSession(&session_deps
));
600 scoped_ptr
<HttpTransaction
> trans(new HttpNetworkTransaction(session
));
603 TEST_P(SpdyNetworkTransactionSpdy3Test
, Get
) {
604 // Construct the request.
605 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
606 MockWrite writes
[] = { CreateMockWrite(*req
) };
608 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
609 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
611 CreateMockRead(*resp
),
612 CreateMockRead(*body
),
613 MockRead(ASYNC
, 0, 0) // EOF
616 DelayedSocketData
data(1, reads
, arraysize(reads
),
617 writes
, arraysize(writes
));
618 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
619 BoundNetLog(), GetParam(), NULL
);
620 helper
.RunToCompletion(&data
);
621 TransactionHelperResult out
= helper
.output();
622 EXPECT_EQ(OK
, out
.rv
);
623 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
624 EXPECT_EQ("hello!", out
.response_data
);
627 TEST_P(SpdyNetworkTransactionSpdy3Test
, GetAtEachPriority
) {
628 for (RequestPriority p
= MINIMUM_PRIORITY
; p
< NUM_PRIORITIES
;
629 p
= RequestPriority(p
+ 1)) {
630 // Construct the request.
631 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, p
));
632 MockWrite writes
[] = { CreateMockWrite(*req
) };
634 const int spdy_prio
= reinterpret_cast<SpdySynStreamControlFrame
*>(
635 req
.get())->priority();
636 // this repeats the RequestPriority-->SpdyPriority mapping from
637 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
638 // sure it's being done right.
641 EXPECT_EQ(0, spdy_prio
);
644 EXPECT_EQ(1, spdy_prio
);
647 EXPECT_EQ(2, spdy_prio
);
650 EXPECT_EQ(3, spdy_prio
);
653 EXPECT_EQ(4, spdy_prio
);
659 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
660 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
662 CreateMockRead(*resp
),
663 CreateMockRead(*body
),
664 MockRead(ASYNC
, 0, 0) // EOF
667 DelayedSocketData
data(1, reads
, arraysize(reads
),
668 writes
, arraysize(writes
));
669 HttpRequestInfo http_req
= CreateGetRequest();
670 http_req
.priority
= p
;
672 NormalSpdyTransactionHelper
helper(http_req
, BoundNetLog(),
674 helper
.RunToCompletion(&data
);
675 TransactionHelperResult out
= helper
.output();
676 EXPECT_EQ(OK
, out
.rv
);
677 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
678 EXPECT_EQ("hello!", out
.response_data
);
682 // Start three gets simultaniously; making sure that multiplexed
683 // streams work properly.
685 // This can't use the TransactionHelper method, since it only
686 // handles a single transaction, and finishes them as soon
687 // as it launches them.
689 // TODO(gavinp): create a working generalized TransactionHelper that
690 // can allow multiple streams in flight.
692 TEST_P(SpdyNetworkTransactionSpdy3Test
, ThreeGets
) {
693 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
694 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
695 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
696 scoped_ptr
<SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
698 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
699 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
700 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
701 scoped_ptr
<SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
703 scoped_ptr
<SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
704 scoped_ptr
<SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
705 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(5, false));
706 scoped_ptr
<SpdyFrame
> fbody3(ConstructSpdyBodyFrame(5, true));
708 MockWrite writes
[] = {
709 CreateMockWrite(*req
),
710 CreateMockWrite(*req2
),
711 CreateMockWrite(*req3
),
714 CreateMockRead(*resp
, 1),
715 CreateMockRead(*body
),
716 CreateMockRead(*resp2
, 4),
717 CreateMockRead(*body2
),
718 CreateMockRead(*resp3
, 7),
719 CreateMockRead(*body3
),
721 CreateMockRead(*fbody
),
722 CreateMockRead(*fbody2
),
723 CreateMockRead(*fbody3
),
725 MockRead(ASYNC
, 0, 0), // EOF
727 OrderedSocketData
data(reads
, arraysize(reads
),
728 writes
, arraysize(writes
));
729 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
732 TransactionHelperResult out
;
733 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
734 BoundNetLog(), GetParam(), NULL
);
735 helper
.RunPreTestSetup();
736 helper
.AddData(&data
);
737 // We require placeholder data because three get requests are sent out, so
738 // there needs to be three sets of SSL connection data.
739 helper
.AddData(&data_placeholder
);
740 helper
.AddData(&data_placeholder
);
741 scoped_ptr
<HttpNetworkTransaction
> trans1(
742 new HttpNetworkTransaction(helper
.session()));
743 scoped_ptr
<HttpNetworkTransaction
> trans2(
744 new HttpNetworkTransaction(helper
.session()));
745 scoped_ptr
<HttpNetworkTransaction
> trans3(
746 new HttpNetworkTransaction(helper
.session()));
748 TestCompletionCallback callback1
;
749 TestCompletionCallback callback2
;
750 TestCompletionCallback callback3
;
752 HttpRequestInfo httpreq1
= CreateGetRequest();
753 HttpRequestInfo httpreq2
= CreateGetRequest();
754 HttpRequestInfo httpreq3
= CreateGetRequest();
756 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
757 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
758 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
759 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
760 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
761 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
763 out
.rv
= callback1
.WaitForResult();
764 ASSERT_EQ(OK
, out
.rv
);
765 out
.rv
= callback3
.WaitForResult();
766 ASSERT_EQ(OK
, out
.rv
);
768 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
769 EXPECT_TRUE(response1
->headers
!= NULL
);
770 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
771 out
.status_line
= response1
->headers
->GetStatusLine();
772 out
.response_info
= *response1
;
774 trans2
->GetResponseInfo();
776 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
777 helper
.VerifyDataConsumed();
778 EXPECT_EQ(OK
, out
.rv
);
780 EXPECT_EQ(OK
, out
.rv
);
781 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
782 EXPECT_EQ("hello!hello!", out
.response_data
);
785 TEST_P(SpdyNetworkTransactionSpdy3Test
, TwoGetsLateBinding
) {
786 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
787 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
788 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
789 scoped_ptr
<SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
791 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
792 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
793 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
794 scoped_ptr
<SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
796 MockWrite writes
[] = {
797 CreateMockWrite(*req
),
798 CreateMockWrite(*req2
),
801 CreateMockRead(*resp
, 1),
802 CreateMockRead(*body
),
803 CreateMockRead(*resp2
, 4),
804 CreateMockRead(*body2
),
805 CreateMockRead(*fbody
),
806 CreateMockRead(*fbody2
),
807 MockRead(ASYNC
, 0, 0), // EOF
809 OrderedSocketData
data(reads
, arraysize(reads
),
810 writes
, arraysize(writes
));
812 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
814 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
815 data_placeholder
.set_connect_data(never_finishing_connect
);
818 TransactionHelperResult out
;
819 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
820 BoundNetLog(), GetParam(), NULL
);
821 helper
.RunPreTestSetup();
822 helper
.AddData(&data
);
823 // We require placeholder data because two get requests are sent out, so
824 // there needs to be two sets of SSL connection data.
825 helper
.AddData(&data_placeholder
);
826 scoped_ptr
<HttpNetworkTransaction
> trans1(
827 new HttpNetworkTransaction(helper
.session()));
828 scoped_ptr
<HttpNetworkTransaction
> trans2(
829 new HttpNetworkTransaction(helper
.session()));
831 TestCompletionCallback callback1
;
832 TestCompletionCallback callback2
;
834 HttpRequestInfo httpreq1
= CreateGetRequest();
835 HttpRequestInfo httpreq2
= CreateGetRequest();
837 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
838 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
839 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
840 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
842 out
.rv
= callback1
.WaitForResult();
843 ASSERT_EQ(OK
, out
.rv
);
844 out
.rv
= callback2
.WaitForResult();
845 ASSERT_EQ(OK
, out
.rv
);
847 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
848 EXPECT_TRUE(response1
->headers
!= NULL
);
849 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
850 out
.status_line
= response1
->headers
->GetStatusLine();
851 out
.response_info
= *response1
;
852 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
853 EXPECT_EQ(OK
, out
.rv
);
854 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
855 EXPECT_EQ("hello!hello!", out
.response_data
);
857 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
858 EXPECT_TRUE(response2
->headers
!= NULL
);
859 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
860 out
.status_line
= response2
->headers
->GetStatusLine();
861 out
.response_info
= *response2
;
862 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
863 EXPECT_EQ(OK
, out
.rv
);
864 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
865 EXPECT_EQ("hello!hello!", out
.response_data
);
867 helper
.VerifyDataConsumed();
870 TEST_P(SpdyNetworkTransactionSpdy3Test
, TwoGetsLateBindingFromPreconnect
) {
871 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
872 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
873 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
874 scoped_ptr
<SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
876 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
877 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
878 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
879 scoped_ptr
<SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
881 MockWrite writes
[] = {
882 CreateMockWrite(*req
),
883 CreateMockWrite(*req2
),
886 CreateMockRead(*resp
, 1),
887 CreateMockRead(*body
),
888 CreateMockRead(*resp2
, 4),
889 CreateMockRead(*body2
),
890 CreateMockRead(*fbody
),
891 CreateMockRead(*fbody2
),
892 MockRead(ASYNC
, 0, 0), // EOF
894 OrderedSocketData
preconnect_data(reads
, arraysize(reads
),
895 writes
, arraysize(writes
));
897 MockConnect
never_finishing_connect(ASYNC
, ERR_IO_PENDING
);
899 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
900 data_placeholder
.set_connect_data(never_finishing_connect
);
903 TransactionHelperResult out
;
904 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
905 BoundNetLog(), GetParam(), NULL
);
906 helper
.RunPreTestSetup();
907 helper
.AddData(&preconnect_data
);
908 // We require placeholder data because 3 connections are attempted (first is
909 // the preconnect, 2nd and 3rd are the never finished connections.
910 helper
.AddData(&data_placeholder
);
911 helper
.AddData(&data_placeholder
);
913 scoped_ptr
<HttpNetworkTransaction
> trans1(
914 new HttpNetworkTransaction(helper
.session()));
915 scoped_ptr
<HttpNetworkTransaction
> trans2(
916 new HttpNetworkTransaction(helper
.session()));
918 TestCompletionCallback callback1
;
919 TestCompletionCallback callback2
;
921 HttpRequestInfo httpreq
= CreateGetRequest();
923 // Preconnect the first.
924 SSLConfig preconnect_ssl_config
;
925 helper
.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config
);
926 HttpStreamFactory
* http_stream_factory
=
927 helper
.session()->http_stream_factory();
928 if (http_stream_factory
->has_next_protos()) {
929 preconnect_ssl_config
.next_protos
= http_stream_factory
->next_protos();
932 http_stream_factory
->PreconnectStreams(
933 1, httpreq
, preconnect_ssl_config
, preconnect_ssl_config
);
935 out
.rv
= trans1
->Start(&httpreq
, callback1
.callback(), log
);
936 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
937 out
.rv
= trans2
->Start(&httpreq
, callback2
.callback(), log
);
938 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
940 out
.rv
= callback1
.WaitForResult();
941 ASSERT_EQ(OK
, out
.rv
);
942 out
.rv
= callback2
.WaitForResult();
943 ASSERT_EQ(OK
, out
.rv
);
945 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
946 EXPECT_TRUE(response1
->headers
!= NULL
);
947 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
948 out
.status_line
= response1
->headers
->GetStatusLine();
949 out
.response_info
= *response1
;
950 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
951 EXPECT_EQ(OK
, out
.rv
);
952 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
953 EXPECT_EQ("hello!hello!", out
.response_data
);
955 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
956 EXPECT_TRUE(response2
->headers
!= NULL
);
957 EXPECT_TRUE(response2
->was_fetched_via_spdy
);
958 out
.status_line
= response2
->headers
->GetStatusLine();
959 out
.response_info
= *response2
;
960 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
961 EXPECT_EQ(OK
, out
.rv
);
962 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
963 EXPECT_EQ("hello!hello!", out
.response_data
);
965 helper
.VerifyDataConsumed();
968 // Similar to ThreeGets above, however this test adds a SETTINGS
969 // frame. The SETTINGS frame is read during the IO loop waiting on
970 // the first transaction completion, and sets a maximum concurrent
971 // stream limit of 1. This means that our IO loop exists after the
972 // second transaction completes, so we can assert on read_index().
973 TEST_P(SpdyNetworkTransactionSpdy3Test
, ThreeGetsWithMaxConcurrent
) {
974 // Construct the request.
975 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
976 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
977 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
978 scoped_ptr
<SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
980 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
981 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
982 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
983 scoped_ptr
<SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
985 scoped_ptr
<SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
986 scoped_ptr
<SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
987 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(5, false));
988 scoped_ptr
<SpdyFrame
> fbody3(ConstructSpdyBodyFrame(5, true));
990 SettingsMap settings
;
991 const uint32 max_concurrent_streams
= 1;
992 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
993 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
994 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
996 MockWrite writes
[] = {
997 CreateMockWrite(*req
),
998 CreateMockWrite(*req2
),
999 CreateMockWrite(*req3
),
1002 MockRead reads
[] = {
1003 CreateMockRead(*settings_frame
, 1),
1004 CreateMockRead(*resp
),
1005 CreateMockRead(*body
),
1006 CreateMockRead(*fbody
),
1007 CreateMockRead(*resp2
, 7),
1008 CreateMockRead(*body2
),
1009 CreateMockRead(*fbody2
),
1010 CreateMockRead(*resp3
, 12),
1011 CreateMockRead(*body3
),
1012 CreateMockRead(*fbody3
),
1014 MockRead(ASYNC
, 0, 0), // EOF
1017 OrderedSocketData
data(reads
, arraysize(reads
),
1018 writes
, arraysize(writes
));
1019 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1022 TransactionHelperResult out
;
1024 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1025 BoundNetLog(), GetParam(), NULL
);
1026 helper
.RunPreTestSetup();
1027 helper
.AddData(&data
);
1028 // We require placeholder data because three get requests are sent out, so
1029 // there needs to be three sets of SSL connection data.
1030 helper
.AddData(&data_placeholder
);
1031 helper
.AddData(&data_placeholder
);
1032 scoped_ptr
<HttpNetworkTransaction
> trans1(
1033 new HttpNetworkTransaction(helper
.session()));
1034 scoped_ptr
<HttpNetworkTransaction
> trans2(
1035 new HttpNetworkTransaction(helper
.session()));
1036 scoped_ptr
<HttpNetworkTransaction
> trans3(
1037 new HttpNetworkTransaction(helper
.session()));
1039 TestCompletionCallback callback1
;
1040 TestCompletionCallback callback2
;
1041 TestCompletionCallback callback3
;
1043 HttpRequestInfo httpreq1
= CreateGetRequest();
1044 HttpRequestInfo httpreq2
= CreateGetRequest();
1045 HttpRequestInfo httpreq3
= CreateGetRequest();
1047 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1048 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1049 // run transaction 1 through quickly to force a read of our SETTINGS
1051 out
.rv
= callback1
.WaitForResult();
1052 ASSERT_EQ(OK
, out
.rv
);
1054 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1055 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1056 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1057 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1058 out
.rv
= callback2
.WaitForResult();
1059 ASSERT_EQ(OK
, out
.rv
);
1060 EXPECT_EQ(7U, data
.read_index()); // i.e. the third trans was queued
1062 out
.rv
= callback3
.WaitForResult();
1063 ASSERT_EQ(OK
, out
.rv
);
1065 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1066 ASSERT_TRUE(response1
!= NULL
);
1067 EXPECT_TRUE(response1
->headers
!= NULL
);
1068 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1069 out
.status_line
= response1
->headers
->GetStatusLine();
1070 out
.response_info
= *response1
;
1071 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1072 EXPECT_EQ(OK
, out
.rv
);
1073 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1074 EXPECT_EQ("hello!hello!", out
.response_data
);
1076 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1077 out
.status_line
= response2
->headers
->GetStatusLine();
1078 out
.response_info
= *response2
;
1079 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1080 EXPECT_EQ(OK
, out
.rv
);
1081 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1082 EXPECT_EQ("hello!hello!", out
.response_data
);
1084 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1085 out
.status_line
= response3
->headers
->GetStatusLine();
1086 out
.response_info
= *response3
;
1087 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1088 EXPECT_EQ(OK
, out
.rv
);
1089 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1090 EXPECT_EQ("hello!hello!", out
.response_data
);
1092 helper
.VerifyDataConsumed();
1094 EXPECT_EQ(OK
, out
.rv
);
1097 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1098 // a fourth transaction. The third and fourth transactions have
1099 // different data ("hello!" vs "hello!hello!") and because of the
1100 // user specified priority, we expect to see them inverted in
1101 // the response from the server.
1102 TEST_P(SpdyNetworkTransactionSpdy3Test
, FourGetsWithMaxConcurrentPriority
) {
1103 // Construct the request.
1104 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1105 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1106 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1107 scoped_ptr
<SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
1109 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1110 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1111 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
1112 scoped_ptr
<SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
1114 scoped_ptr
<SpdyFrame
> req4(
1115 ConstructSpdyGet(NULL
, 0, false, 5, HIGHEST
));
1116 scoped_ptr
<SpdyFrame
> resp4(ConstructSpdyGetSynReply(NULL
, 0, 5));
1117 scoped_ptr
<SpdyFrame
> fbody4(ConstructSpdyBodyFrame(5, true));
1119 scoped_ptr
<SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 7, LOWEST
));
1120 scoped_ptr
<SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 7));
1121 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(7, false));
1122 scoped_ptr
<SpdyFrame
> fbody3(ConstructSpdyBodyFrame(7, true));
1124 SettingsMap settings
;
1125 const uint32 max_concurrent_streams
= 1;
1126 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1127 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1128 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1130 MockWrite writes
[] = { CreateMockWrite(*req
),
1131 CreateMockWrite(*req2
),
1132 CreateMockWrite(*req4
),
1133 CreateMockWrite(*req3
),
1135 MockRead reads
[] = {
1136 CreateMockRead(*settings_frame
, 1),
1137 CreateMockRead(*resp
),
1138 CreateMockRead(*body
),
1139 CreateMockRead(*fbody
),
1140 CreateMockRead(*resp2
, 7),
1141 CreateMockRead(*body2
),
1142 CreateMockRead(*fbody2
),
1143 CreateMockRead(*resp4
, 13),
1144 CreateMockRead(*fbody4
),
1145 CreateMockRead(*resp3
, 16),
1146 CreateMockRead(*body3
),
1147 CreateMockRead(*fbody3
),
1149 MockRead(ASYNC
, 0, 0), // EOF
1152 OrderedSocketData
data(reads
, arraysize(reads
),
1153 writes
, arraysize(writes
));
1154 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1157 TransactionHelperResult out
;
1158 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1159 BoundNetLog(), GetParam(), NULL
);
1160 helper
.RunPreTestSetup();
1161 helper
.AddData(&data
);
1162 // We require placeholder data because four get requests are sent out, so
1163 // there needs to be four sets of SSL connection data.
1164 helper
.AddData(&data_placeholder
);
1165 helper
.AddData(&data_placeholder
);
1166 helper
.AddData(&data_placeholder
);
1167 scoped_ptr
<HttpNetworkTransaction
> trans1(
1168 new HttpNetworkTransaction(helper
.session()));
1169 scoped_ptr
<HttpNetworkTransaction
> trans2(
1170 new HttpNetworkTransaction(helper
.session()));
1171 scoped_ptr
<HttpNetworkTransaction
> trans3(
1172 new HttpNetworkTransaction(helper
.session()));
1173 scoped_ptr
<HttpNetworkTransaction
> trans4(
1174 new HttpNetworkTransaction(helper
.session()));
1176 TestCompletionCallback callback1
;
1177 TestCompletionCallback callback2
;
1178 TestCompletionCallback callback3
;
1179 TestCompletionCallback callback4
;
1181 HttpRequestInfo httpreq1
= CreateGetRequest();
1182 HttpRequestInfo httpreq2
= CreateGetRequest();
1183 HttpRequestInfo httpreq3
= CreateGetRequest();
1184 HttpRequestInfo httpreq4
= CreateGetRequest();
1185 httpreq4
.priority
= HIGHEST
;
1187 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1188 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1189 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1190 out
.rv
= callback1
.WaitForResult();
1191 ASSERT_EQ(OK
, out
.rv
);
1193 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1194 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1195 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1196 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1197 out
.rv
= trans4
->Start(&httpreq4
, callback4
.callback(), log
);
1198 ASSERT_EQ(ERR_IO_PENDING
, out
.rv
);
1200 out
.rv
= callback2
.WaitForResult();
1201 ASSERT_EQ(OK
, out
.rv
);
1202 EXPECT_EQ(data
.read_index(), 7U); // i.e. the third & fourth trans queued
1204 out
.rv
= callback3
.WaitForResult();
1205 ASSERT_EQ(OK
, out
.rv
);
1207 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1208 EXPECT_TRUE(response1
->headers
!= NULL
);
1209 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1210 out
.status_line
= response1
->headers
->GetStatusLine();
1211 out
.response_info
= *response1
;
1212 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1213 EXPECT_EQ(OK
, out
.rv
);
1214 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1215 EXPECT_EQ("hello!hello!", out
.response_data
);
1217 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1218 out
.status_line
= response2
->headers
->GetStatusLine();
1219 out
.response_info
= *response2
;
1220 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1221 EXPECT_EQ(OK
, out
.rv
);
1222 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1223 EXPECT_EQ("hello!hello!", out
.response_data
);
1225 // notice: response3 gets two hellos, response4 gets one
1226 // hello, so we know dequeuing priority was respected.
1227 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
1228 out
.status_line
= response3
->headers
->GetStatusLine();
1229 out
.response_info
= *response3
;
1230 out
.rv
= ReadTransaction(trans3
.get(), &out
.response_data
);
1231 EXPECT_EQ(OK
, out
.rv
);
1232 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1233 EXPECT_EQ("hello!hello!", out
.response_data
);
1235 out
.rv
= callback4
.WaitForResult();
1236 EXPECT_EQ(OK
, out
.rv
);
1237 const HttpResponseInfo
* response4
= trans4
->GetResponseInfo();
1238 out
.status_line
= response4
->headers
->GetStatusLine();
1239 out
.response_info
= *response4
;
1240 out
.rv
= ReadTransaction(trans4
.get(), &out
.response_data
);
1241 EXPECT_EQ(OK
, out
.rv
);
1242 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1243 EXPECT_EQ("hello!", out
.response_data
);
1244 helper
.VerifyDataConsumed();
1245 EXPECT_EQ(OK
, out
.rv
);
1248 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1249 // deletes a session in the middle of the transaction to insure
1250 // that we properly remove pendingcreatestream objects from
1252 TEST_P(SpdyNetworkTransactionSpdy3Test
, ThreeGetsWithMaxConcurrentDelete
) {
1253 // Construct the request.
1254 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1255 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1256 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1257 scoped_ptr
<SpdyFrame
> fbody(ConstructSpdyBodyFrame(1, true));
1259 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1260 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1261 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, false));
1262 scoped_ptr
<SpdyFrame
> fbody2(ConstructSpdyBodyFrame(3, true));
1264 SettingsMap settings
;
1265 const uint32 max_concurrent_streams
= 1;
1266 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1267 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1268 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1270 MockWrite writes
[] = { CreateMockWrite(*req
),
1271 CreateMockWrite(*req2
),
1273 MockRead reads
[] = {
1274 CreateMockRead(*settings_frame
, 1),
1275 CreateMockRead(*resp
),
1276 CreateMockRead(*body
),
1277 CreateMockRead(*fbody
),
1278 CreateMockRead(*resp2
, 7),
1279 CreateMockRead(*body2
),
1280 CreateMockRead(*fbody2
),
1281 MockRead(ASYNC
, 0, 0), // EOF
1284 OrderedSocketData
data(reads
, arraysize(reads
),
1285 writes
, arraysize(writes
));
1286 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1289 TransactionHelperResult out
;
1290 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1291 BoundNetLog(), GetParam(), NULL
);
1292 helper
.RunPreTestSetup();
1293 helper
.AddData(&data
);
1294 // We require placeholder data because three get requests are sent out, so
1295 // there needs to be three sets of SSL connection data.
1296 helper
.AddData(&data_placeholder
);
1297 helper
.AddData(&data_placeholder
);
1298 scoped_ptr
<HttpNetworkTransaction
> trans1(
1299 new HttpNetworkTransaction(helper
.session()));
1300 scoped_ptr
<HttpNetworkTransaction
> trans2(
1301 new HttpNetworkTransaction(helper
.session()));
1302 scoped_ptr
<HttpNetworkTransaction
> trans3(
1303 new HttpNetworkTransaction(helper
.session()));
1305 TestCompletionCallback callback1
;
1306 TestCompletionCallback callback2
;
1307 TestCompletionCallback callback3
;
1309 HttpRequestInfo httpreq1
= CreateGetRequest();
1310 HttpRequestInfo httpreq2
= CreateGetRequest();
1311 HttpRequestInfo httpreq3
= CreateGetRequest();
1313 out
.rv
= trans1
->Start(&httpreq1
, callback1
.callback(), log
);
1314 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1315 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1316 out
.rv
= callback1
.WaitForResult();
1317 ASSERT_EQ(OK
, out
.rv
);
1319 out
.rv
= trans2
->Start(&httpreq2
, callback2
.callback(), log
);
1320 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1321 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1322 delete trans3
.release();
1323 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1324 out
.rv
= callback2
.WaitForResult();
1325 ASSERT_EQ(OK
, out
.rv
);
1327 EXPECT_EQ(8U, data
.read_index());
1329 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
1330 ASSERT_TRUE(response1
!= NULL
);
1331 EXPECT_TRUE(response1
->headers
!= NULL
);
1332 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1333 out
.status_line
= response1
->headers
->GetStatusLine();
1334 out
.response_info
= *response1
;
1335 out
.rv
= ReadTransaction(trans1
.get(), &out
.response_data
);
1336 EXPECT_EQ(OK
, out
.rv
);
1337 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1338 EXPECT_EQ("hello!hello!", out
.response_data
);
1340 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
1341 ASSERT_TRUE(response2
!= NULL
);
1342 out
.status_line
= response2
->headers
->GetStatusLine();
1343 out
.response_info
= *response2
;
1344 out
.rv
= ReadTransaction(trans2
.get(), &out
.response_data
);
1345 EXPECT_EQ(OK
, out
.rv
);
1346 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1347 EXPECT_EQ("hello!hello!", out
.response_data
);
1348 helper
.VerifyDataConsumed();
1349 EXPECT_EQ(OK
, out
.rv
);
1354 // The KillerCallback will delete the transaction on error as part of the
1356 class KillerCallback
: public TestCompletionCallbackBase
{
1358 explicit KillerCallback(HttpNetworkTransaction
* transaction
)
1359 : transaction_(transaction
),
1360 ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
1361 base::Bind(&KillerCallback::OnComplete
, base::Unretained(this)))) {
1364 virtual ~KillerCallback() {}
1366 const CompletionCallback
& callback() const { return callback_
; }
1369 void OnComplete(int result
) {
1371 delete transaction_
;
1376 HttpNetworkTransaction
* transaction_
;
1377 CompletionCallback callback_
;
1382 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1383 // closes the socket while we have a pending transaction waiting for
1384 // a pending stream creation. http://crbug.com/52901
1385 TEST_P(SpdyNetworkTransactionSpdy3Test
, ThreeGetsWithMaxConcurrentSocketClose
) {
1386 // Construct the request.
1387 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1388 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1389 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, false));
1390 scoped_ptr
<SpdyFrame
> fin_body(ConstructSpdyBodyFrame(1, true));
1392 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1393 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1395 SettingsMap settings
;
1396 const uint32 max_concurrent_streams
= 1;
1397 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1398 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1399 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
1401 MockWrite writes
[] = { CreateMockWrite(*req
),
1402 CreateMockWrite(*req2
),
1404 MockRead reads
[] = {
1405 CreateMockRead(*settings_frame
, 1),
1406 CreateMockRead(*resp
),
1407 CreateMockRead(*body
),
1408 CreateMockRead(*fin_body
),
1409 CreateMockRead(*resp2
, 7),
1410 MockRead(ASYNC
, ERR_CONNECTION_RESET
, 0), // Abort!
1413 OrderedSocketData
data(reads
, arraysize(reads
),
1414 writes
, arraysize(writes
));
1415 OrderedSocketData
data_placeholder(NULL
, 0, NULL
, 0);
1418 TransactionHelperResult out
;
1419 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1420 BoundNetLog(), GetParam(), NULL
);
1421 helper
.RunPreTestSetup();
1422 helper
.AddData(&data
);
1423 // We require placeholder data because three get requests are sent out, so
1424 // there needs to be three sets of SSL connection data.
1425 helper
.AddData(&data_placeholder
);
1426 helper
.AddData(&data_placeholder
);
1427 HttpNetworkTransaction
trans1(helper
.session());
1428 HttpNetworkTransaction
trans2(helper
.session());
1429 HttpNetworkTransaction
* trans3(new HttpNetworkTransaction(helper
.session()));
1431 TestCompletionCallback callback1
;
1432 TestCompletionCallback callback2
;
1433 KillerCallback
callback3(trans3
);
1435 HttpRequestInfo httpreq1
= CreateGetRequest();
1436 HttpRequestInfo httpreq2
= CreateGetRequest();
1437 HttpRequestInfo httpreq3
= CreateGetRequest();
1439 out
.rv
= trans1
.Start(&httpreq1
, callback1
.callback(), log
);
1440 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1441 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1442 out
.rv
= callback1
.WaitForResult();
1443 ASSERT_EQ(OK
, out
.rv
);
1445 out
.rv
= trans2
.Start(&httpreq2
, callback2
.callback(), log
);
1446 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1447 out
.rv
= trans3
->Start(&httpreq3
, callback3
.callback(), log
);
1448 ASSERT_EQ(out
.rv
, ERR_IO_PENDING
);
1449 out
.rv
= callback3
.WaitForResult();
1450 ASSERT_EQ(ERR_ABORTED
, out
.rv
);
1452 EXPECT_EQ(6U, data
.read_index());
1454 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
1455 ASSERT_TRUE(response1
!= NULL
);
1456 EXPECT_TRUE(response1
->headers
!= NULL
);
1457 EXPECT_TRUE(response1
->was_fetched_via_spdy
);
1458 out
.status_line
= response1
->headers
->GetStatusLine();
1459 out
.response_info
= *response1
;
1460 out
.rv
= ReadTransaction(&trans1
, &out
.response_data
);
1461 EXPECT_EQ(OK
, out
.rv
);
1463 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
1464 ASSERT_TRUE(response2
!= NULL
);
1465 out
.status_line
= response2
->headers
->GetStatusLine();
1466 out
.response_info
= *response2
;
1467 out
.rv
= ReadTransaction(&trans2
, &out
.response_data
);
1468 EXPECT_EQ(ERR_CONNECTION_RESET
, out
.rv
);
1470 helper
.VerifyDataConsumed();
1473 // Test that a simple PUT request works.
1474 TEST_P(SpdyNetworkTransactionSpdy3Test
, Put
) {
1475 // Setup the request
1476 HttpRequestInfo request
;
1477 request
.method
= "PUT";
1478 request
.url
= GURL("http://www.google.com/");
1480 const SpdyHeaderInfo kSynStartHeader
= {
1481 SYN_STREAM
, // Kind = Syn
1483 0, // Associated stream ID
1484 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
1485 0, // Credential Slot
1486 CONTROL_FLAG_FIN
, // Control Flags
1487 false, // Compressed
1491 DATA_FLAG_NONE
// Data Flags
1493 const char* const kPutHeaders
[] = {
1496 ":host", "www.google.com",
1498 ":version", "HTTP/1.1",
1499 "content-length", "0"
1501 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPacket(kSynStartHeader
, NULL
, 0,
1502 kPutHeaders
, arraysize(kPutHeaders
) / 2));
1503 MockWrite writes
[] = {
1504 CreateMockWrite(*req
)
1507 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1508 const SpdyHeaderInfo kSynReplyHeader
= {
1509 SYN_REPLY
, // Kind = SynReply
1511 0, // Associated stream ID
1512 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
1513 0, // Credential Slot
1514 CONTROL_FLAG_NONE
, // Control Flags
1515 false, // Compressed
1519 DATA_FLAG_NONE
// Data Flags
1521 static const char* const kStandardRespHeaders
[] = {
1523 ":version", "HTTP/1.1"
1524 "content-length", "1234"
1526 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPacket(kSynReplyHeader
,
1527 NULL
, 0, kStandardRespHeaders
, arraysize(kStandardRespHeaders
) / 2));
1528 MockRead reads
[] = {
1529 CreateMockRead(*resp
),
1530 CreateMockRead(*body
),
1531 MockRead(ASYNC
, 0, 0) // EOF
1534 DelayedSocketData
data(1, reads
, arraysize(reads
),
1535 writes
, arraysize(writes
));
1536 NormalSpdyTransactionHelper
helper(request
,
1537 BoundNetLog(), GetParam(), NULL
);
1538 helper
.RunToCompletion(&data
);
1539 TransactionHelperResult out
= helper
.output();
1541 EXPECT_EQ(OK
, out
.rv
);
1542 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1545 // Test that a simple HEAD request works.
1546 TEST_P(SpdyNetworkTransactionSpdy3Test
, Head
) {
1547 // Setup the request
1548 HttpRequestInfo request
;
1549 request
.method
= "HEAD";
1550 request
.url
= GURL("http://www.google.com/");
1552 const SpdyHeaderInfo kSynStartHeader
= {
1553 SYN_STREAM
, // Kind = Syn
1555 0, // Associated stream ID
1556 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
1557 0, // Credential Slot
1558 CONTROL_FLAG_FIN
, // Control Flags
1559 false, // Compressed
1563 DATA_FLAG_NONE
// Data Flags
1565 const char* const kHeadHeaders
[] = {
1568 ":host", "www.google.com",
1570 ":version", "HTTP/1.1",
1571 "content-length", "0"
1573 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPacket(kSynStartHeader
, NULL
, 0,
1574 kHeadHeaders
, arraysize(kHeadHeaders
) / 2));
1575 MockWrite writes
[] = {
1576 CreateMockWrite(*req
)
1579 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1580 const SpdyHeaderInfo kSynReplyHeader
= {
1581 SYN_REPLY
, // Kind = SynReply
1583 0, // Associated stream ID
1584 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
1585 0, // Credential Slot
1586 CONTROL_FLAG_NONE
, // Control Flags
1587 false, // Compressed
1591 DATA_FLAG_NONE
// Data Flags
1593 static const char* const kStandardRespHeaders
[] = {
1595 ":version", "HTTP/1.1"
1596 "content-length", "1234"
1598 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPacket(kSynReplyHeader
,
1599 NULL
, 0, kStandardRespHeaders
, arraysize(kStandardRespHeaders
) / 2));
1600 MockRead reads
[] = {
1601 CreateMockRead(*resp
),
1602 CreateMockRead(*body
),
1603 MockRead(ASYNC
, 0, 0) // EOF
1606 DelayedSocketData
data(1, reads
, arraysize(reads
),
1607 writes
, arraysize(writes
));
1608 NormalSpdyTransactionHelper
helper(request
,
1609 BoundNetLog(), GetParam(), NULL
);
1610 helper
.RunToCompletion(&data
);
1611 TransactionHelperResult out
= helper
.output();
1613 EXPECT_EQ(OK
, out
.rv
);
1614 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1617 // Test that a simple POST works.
1618 TEST_P(SpdyNetworkTransactionSpdy3Test
, Post
) {
1619 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(kUploadDataSize
, NULL
, 0));
1620 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1621 MockWrite writes
[] = {
1622 CreateMockWrite(*req
),
1623 CreateMockWrite(*body
), // POST upload frame
1626 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1627 MockRead reads
[] = {
1628 CreateMockRead(*resp
),
1629 CreateMockRead(*body
),
1630 MockRead(ASYNC
, 0, 0) // EOF
1633 DelayedSocketData
data(2, reads
, arraysize(reads
),
1634 writes
, arraysize(writes
));
1635 NormalSpdyTransactionHelper
helper(CreatePostRequest(),
1636 BoundNetLog(), GetParam(), NULL
);
1637 helper
.RunToCompletion(&data
);
1638 TransactionHelperResult out
= helper
.output();
1639 EXPECT_EQ(OK
, out
.rv
);
1640 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1641 EXPECT_EQ("hello!", out
.response_data
);
1644 // Test that a POST with a file works.
1645 TEST_P(SpdyNetworkTransactionSpdy3Test
, FilePost
) {
1646 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(kUploadDataSize
, NULL
, 0));
1647 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1648 MockWrite writes
[] = {
1649 CreateMockWrite(*req
),
1650 CreateMockWrite(*body
), // POST upload frame
1653 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1654 MockRead reads
[] = {
1655 CreateMockRead(*resp
),
1656 CreateMockRead(*body
),
1657 MockRead(ASYNC
, 0, 0) // EOF
1660 DelayedSocketData
data(2, reads
, arraysize(reads
),
1661 writes
, arraysize(writes
));
1663 NormalSpdyTransactionHelper
helper(CreateFilePostRequest(),
1664 BoundNetLog(), GetParam(), NULL
);
1665 helper
.RunToCompletion(&data
);
1666 TransactionHelperResult out
= helper
.output();
1667 EXPECT_EQ(OK
, out
.rv
);
1668 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1669 EXPECT_EQ("hello!", out
.response_data
);
1672 // Test that a complex POST works.
1673 TEST_P(SpdyNetworkTransactionSpdy3Test
, ComplexPost
) {
1674 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(kUploadDataSize
, NULL
, 0));
1675 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1676 MockWrite writes
[] = {
1677 CreateMockWrite(*req
),
1678 CreateMockWrite(*body
), // POST upload frame
1681 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1682 MockRead reads
[] = {
1683 CreateMockRead(*resp
),
1684 CreateMockRead(*body
),
1685 MockRead(ASYNC
, 0, 0) // EOF
1688 DelayedSocketData
data(2, reads
, arraysize(reads
),
1689 writes
, arraysize(writes
));
1691 NormalSpdyTransactionHelper
helper(CreateComplexPostRequest(),
1692 BoundNetLog(), GetParam(), NULL
);
1693 helper
.RunToCompletion(&data
);
1694 TransactionHelperResult out
= helper
.output();
1695 EXPECT_EQ(OK
, out
.rv
);
1696 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1697 EXPECT_EQ("hello!", out
.response_data
);
1700 // Test that a chunked POST works.
1701 TEST_P(SpdyNetworkTransactionSpdy3Test
, ChunkedPost
) {
1702 set_merge_chunks(false);
1704 scoped_ptr
<SpdyFrame
> req(ConstructChunkedSpdyPost(NULL
, 0));
1705 scoped_ptr
<SpdyFrame
> chunk1(ConstructSpdyBodyFrame(1, false));
1706 scoped_ptr
<SpdyFrame
> chunk2(ConstructSpdyBodyFrame(1, true));
1707 MockWrite writes
[] = {
1708 CreateMockWrite(*req
),
1709 CreateMockWrite(*chunk1
),
1710 CreateMockWrite(*chunk2
),
1713 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1714 MockRead reads
[] = {
1715 CreateMockRead(*resp
),
1716 CreateMockRead(*chunk1
),
1717 CreateMockRead(*chunk2
),
1718 MockRead(ASYNC
, 0, 0) // EOF
1721 DelayedSocketData
data(2, reads
, arraysize(reads
),
1722 writes
, arraysize(writes
));
1723 NormalSpdyTransactionHelper
helper(CreateChunkedPostRequest(),
1724 BoundNetLog(), GetParam(), NULL
);
1725 helper
.RunToCompletion(&data
);
1726 TransactionHelperResult out
= helper
.output();
1727 EXPECT_EQ(OK
, out
.rv
);
1728 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1729 EXPECT_EQ("hello!hello!", out
.response_data
);
1732 // Test that a POST without any post data works.
1733 TEST_P(SpdyNetworkTransactionSpdy3Test
, NullPost
) {
1734 // Setup the request
1735 HttpRequestInfo request
;
1736 request
.method
= "POST";
1737 request
.url
= GURL("http://www.google.com/");
1738 // Create an empty UploadData.
1739 request
.upload_data_stream
= NULL
;
1741 // When request.upload_data_stream is NULL for post, content-length is
1742 // expected to be 0.
1743 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(0, NULL
, 0));
1744 // Set the FIN bit since there will be no body.
1745 req
->set_flags(CONTROL_FLAG_FIN
);
1746 MockWrite writes
[] = {
1747 CreateMockWrite(*req
),
1750 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1751 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1752 MockRead reads
[] = {
1753 CreateMockRead(*resp
),
1754 CreateMockRead(*body
),
1755 MockRead(ASYNC
, 0, 0) // EOF
1758 DelayedSocketData
data(1, reads
, arraysize(reads
),
1759 writes
, arraysize(writes
));
1761 NormalSpdyTransactionHelper
helper(request
,
1762 BoundNetLog(), GetParam(), NULL
);
1763 helper
.RunToCompletion(&data
);
1764 TransactionHelperResult out
= helper
.output();
1765 EXPECT_EQ(OK
, out
.rv
);
1766 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1767 EXPECT_EQ("hello!", out
.response_data
);
1770 // Test that a simple POST works.
1771 TEST_P(SpdyNetworkTransactionSpdy3Test
, EmptyPost
) {
1772 // Create an empty UploadDataStream.
1773 ScopedVector
<UploadElementReader
> element_readers
;
1774 UploadDataStream
stream(&element_readers
, 0);
1776 // Setup the request
1777 HttpRequestInfo request
;
1778 request
.method
= "POST";
1779 request
.url
= GURL("http://www.google.com/");
1780 request
.upload_data_stream
= &stream
;
1782 const uint64 kContentLength
= 0;
1783 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(kContentLength
, NULL
, 0));
1784 // Set the FIN bit since there will be no body.
1785 req
->set_flags(CONTROL_FLAG_FIN
);
1786 MockWrite writes
[] = {
1787 CreateMockWrite(*req
),
1790 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
1791 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1792 MockRead reads
[] = {
1793 CreateMockRead(*resp
),
1794 CreateMockRead(*body
),
1795 MockRead(ASYNC
, 0, 0) // EOF
1798 DelayedSocketData
data(1, reads
, arraysize(reads
), writes
, arraysize(writes
));
1800 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam(), NULL
);
1801 helper
.RunToCompletion(&data
);
1802 TransactionHelperResult out
= helper
.output();
1803 EXPECT_EQ(OK
, out
.rv
);
1804 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
1805 EXPECT_EQ("hello!", out
.response_data
);
1808 // While we're doing a post, the server sends back a SYN_REPLY.
1809 TEST_P(SpdyNetworkTransactionSpdy3Test
, PostWithEarlySynReply
) {
1810 static const char upload
[] = { "hello!" };
1811 ScopedVector
<UploadElementReader
> element_readers
;
1812 element_readers
.push_back(
1813 new UploadBytesElementReader(upload
, sizeof(upload
)));
1814 UploadDataStream
stream(&element_readers
, 0);
1816 // Setup the request
1817 HttpRequestInfo request
;
1818 request
.method
= "POST";
1819 request
.url
= GURL("http://www.google.com/");
1820 request
.upload_data_stream
= &stream
;
1822 scoped_ptr
<SpdyFrame
> stream_reply(ConstructSpdyPostSynReply(NULL
, 0));
1823 scoped_ptr
<SpdyFrame
> stream_body(ConstructSpdyBodyFrame(1, true));
1824 MockRead reads
[] = {
1825 CreateMockRead(*stream_reply
, 1),
1826 MockRead(ASYNC
, 0, 3) // EOF
1829 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(kUploadDataSize
, NULL
, 0));
1830 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1831 MockWrite writes
[] = {
1832 CreateMockWrite(*req
, 0),
1833 CreateMockWrite(*body
, 2),
1836 DeterministicSocketData
data(reads
, arraysize(reads
),
1837 writes
, arraysize(writes
));
1838 NormalSpdyTransactionHelper
helper(CreatePostRequest(),
1839 BoundNetLog(), GetParam(), NULL
);
1840 helper
.SetDeterministic();
1841 helper
.RunPreTestSetup();
1842 helper
.AddDeterministicData(&data
);
1843 HttpNetworkTransaction
* trans
= helper
.trans();
1845 TestCompletionCallback callback
;
1846 int rv
= trans
->Start(
1847 &CreatePostRequest(), callback
.callback(), BoundNetLog());
1848 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1851 rv
= callback
.WaitForResult();
1852 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
1856 // The client upon cancellation tries to send a RST_STREAM frame. The mock
1857 // socket causes the TCP write to return zero. This test checks that the client
1858 // tries to queue up the RST_STREAM frame again.
1859 TEST_P(SpdyNetworkTransactionSpdy3Test
, SocketWriteReturnsZero
) {
1860 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1861 scoped_ptr
<SpdyFrame
> rst(
1862 ConstructSpdyRstStream(1, CANCEL
));
1863 MockWrite writes
[] = {
1864 CreateMockWrite(*req
.get(), 0, SYNCHRONOUS
),
1865 MockWrite(SYNCHRONOUS
, 0, 0, 2),
1866 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
1869 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1870 MockRead reads
[] = {
1871 CreateMockRead(*resp
.get(), 1, ASYNC
),
1872 MockRead(ASYNC
, 0, 0, 4) // EOF
1875 DeterministicSocketData
data(reads
, arraysize(reads
),
1876 writes
, arraysize(writes
));
1877 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1878 BoundNetLog(), GetParam(), NULL
);
1879 helper
.SetDeterministic();
1880 helper
.RunPreTestSetup();
1881 helper
.AddDeterministicData(&data
);
1882 HttpNetworkTransaction
* trans
= helper
.trans();
1884 TestCompletionCallback callback
;
1885 int rv
= trans
->Start(
1886 &CreateGetRequest(), callback
.callback(), BoundNetLog());
1887 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1891 helper
.ResetTrans();
1895 helper
.VerifyDataConsumed();
1898 // Test that the transaction doesn't crash when we don't have a reply.
1899 TEST_P(SpdyNetworkTransactionSpdy3Test
, ResponseWithoutSynReply
) {
1900 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1901 MockRead reads
[] = {
1902 CreateMockRead(*body
),
1903 MockRead(ASYNC
, 0, 0) // EOF
1906 DelayedSocketData
data(1, reads
, arraysize(reads
), NULL
, 0);
1907 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1908 BoundNetLog(), GetParam(), NULL
);
1909 helper
.RunToCompletion(&data
);
1910 TransactionHelperResult out
= helper
.output();
1911 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED
, out
.rv
);
1914 // Test that the transaction doesn't crash when we get two replies on the same
1915 // stream ID. See http://crbug.com/45639.
1916 TEST_P(SpdyNetworkTransactionSpdy3Test
, ResponseWithTwoSynReplies
) {
1917 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1918 MockWrite writes
[] = { CreateMockWrite(*req
) };
1920 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
1921 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
1922 MockRead reads
[] = {
1923 CreateMockRead(*resp
),
1924 CreateMockRead(*resp
),
1925 CreateMockRead(*body
),
1926 MockRead(ASYNC
, 0, 0) // EOF
1929 DelayedSocketData
data(1, reads
, arraysize(reads
),
1930 writes
, arraysize(writes
));
1932 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
1933 BoundNetLog(), GetParam(), NULL
);
1934 helper
.RunPreTestSetup();
1935 helper
.AddData(&data
);
1937 HttpNetworkTransaction
* trans
= helper
.trans();
1939 TestCompletionCallback callback
;
1940 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1942 rv
= callback
.WaitForResult();
1945 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1946 ASSERT_TRUE(response
!= NULL
);
1947 EXPECT_TRUE(response
->headers
!= NULL
);
1948 EXPECT_TRUE(response
->was_fetched_via_spdy
);
1949 std::string response_data
;
1950 rv
= ReadTransaction(trans
, &response_data
);
1951 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, rv
);
1953 helper
.VerifyDataConsumed();
1956 // Test that sent data frames and received WINDOW_UPDATE frames change
1957 // the send_window_size_ correctly.
1959 // WINDOW_UPDATE is different than most other frames in that it can arrive
1960 // while the client is still sending the request body. In order to enforce
1961 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
1962 // socket data provider, so that initial read that is done as soon as the
1963 // stream is created, succeeds and schedules another read. This way reads
1964 // and writes are interleaved; after doing a full frame write, SpdyStream
1965 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
1966 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1967 // since request has not been completely written, therefore we feed
1968 // enough number of WINDOW_UPDATEs to finish the first read and cause a
1969 // write, leading to a complete write of request body; after that we send
1970 // a reply with a body, to cause a graceful shutdown.
1972 // TODO(agayev): develop a socket data provider where both, reads and
1973 // writes are ordered so that writing tests like these are easy and rewrite
1974 // all these tests using it. Right now we are working around the
1975 // limitations as described above and it's not deterministic, tests may
1976 // fail under specific circumstances.
1977 TEST_P(SpdyNetworkTransactionSpdy3Test
, WindowUpdateReceived
) {
1978 static int kFrameCount
= 2;
1979 scoped_ptr
<std::string
> content(
1980 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
1981 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(
1982 kMaxSpdyFrameChunkSize
* kFrameCount
, NULL
, 0));
1983 scoped_ptr
<SpdyFrame
> body(
1984 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
1985 scoped_ptr
<SpdyFrame
> body_end(
1986 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), true));
1988 MockWrite writes
[] = {
1989 CreateMockWrite(*req
),
1990 CreateMockWrite(*body
),
1991 CreateMockWrite(*body_end
),
1994 static const int32 kDeltaWindowSize
= 0xff;
1995 static const int kDeltaCount
= 4;
1996 scoped_ptr
<SpdyFrame
> window_update(
1997 ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
1998 scoped_ptr
<SpdyFrame
> window_update_dummy(
1999 ConstructSpdyWindowUpdate(2, kDeltaWindowSize
));
2000 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyPostSynReply(NULL
, 0));
2001 MockRead reads
[] = {
2002 CreateMockRead(*window_update_dummy
),
2003 CreateMockRead(*window_update_dummy
),
2004 CreateMockRead(*window_update_dummy
),
2005 CreateMockRead(*window_update
), // Four updates, therefore window
2006 CreateMockRead(*window_update
), // size should increase by
2007 CreateMockRead(*window_update
), // kDeltaWindowSize * 4
2008 CreateMockRead(*window_update
),
2009 CreateMockRead(*resp
),
2010 CreateMockRead(*body_end
),
2011 MockRead(ASYNC
, 0, 0) // EOF
2014 DelayedSocketData
data(0, reads
, arraysize(reads
),
2015 writes
, arraysize(writes
));
2017 ScopedVector
<UploadElementReader
> element_readers
;
2018 for (int i
= 0; i
< kFrameCount
; ++i
) {
2019 element_readers
.push_back(
2020 new UploadBytesElementReader(content
->c_str(), content
->size()));
2022 UploadDataStream
upload_data_stream(&element_readers
, 0);
2024 // Setup the request
2025 HttpRequestInfo request
;
2026 request
.method
= "POST";
2027 request
.url
= GURL(kDefaultURL
);
2028 request
.upload_data_stream
= &upload_data_stream
;
2030 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam(), NULL
);
2031 helper
.AddData(&data
);
2032 helper
.RunPreTestSetup();
2034 HttpNetworkTransaction
* trans
= helper
.trans();
2036 TestCompletionCallback callback
;
2037 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2039 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2040 rv
= callback
.WaitForResult();
2043 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2044 ASSERT_TRUE(stream
!= NULL
);
2045 ASSERT_TRUE(stream
->stream() != NULL
);
2046 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize
) +
2047 kDeltaWindowSize
* kDeltaCount
-
2048 kMaxSpdyFrameChunkSize
* kFrameCount
,
2049 stream
->stream()->send_window_size());
2050 helper
.VerifyDataConsumed();
2053 // Test that received data frames and sent WINDOW_UPDATE frames change
2054 // the recv_window_size_ correctly.
2055 TEST_P(SpdyNetworkTransactionSpdy3Test
, WindowUpdateSent
) {
2056 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2057 scoped_ptr
<SpdyFrame
> window_update(
2058 ConstructSpdyWindowUpdate(1, kUploadDataSize
));
2060 MockWrite writes
[] = {
2061 CreateMockWrite(*req
),
2062 CreateMockWrite(*window_update
),
2065 scoped_ptr
<SpdyFrame
> resp(
2066 ConstructSpdyGetSynReply(NULL
, 0, 1));
2067 scoped_ptr
<SpdyFrame
> body_no_fin(
2068 ConstructSpdyBodyFrame(1, false));
2069 scoped_ptr
<SpdyFrame
> body_fin(
2070 ConstructSpdyBodyFrame(1, NULL
, 0, true));
2071 MockRead reads
[] = {
2072 CreateMockRead(*resp
),
2073 CreateMockRead(*body_no_fin
),
2074 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Force a pause
2075 CreateMockRead(*body_fin
),
2076 MockRead(ASYNC
, ERR_IO_PENDING
, 0), // Force a pause
2077 MockRead(ASYNC
, 0, 0) // EOF
2080 DelayedSocketData
data(1, reads
, arraysize(reads
),
2081 writes
, arraysize(writes
));
2083 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2084 BoundNetLog(), GetParam(), NULL
);
2085 helper
.AddData(&data
);
2086 helper
.RunPreTestSetup();
2087 HttpNetworkTransaction
* trans
= helper
.trans();
2089 TestCompletionCallback callback
;
2090 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2092 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2093 rv
= callback
.WaitForResult();
2096 SpdyHttpStream
* stream
=
2097 static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2098 ASSERT_TRUE(stream
!= NULL
);
2099 ASSERT_TRUE(stream
->stream() != NULL
);
2102 static_cast<int>(kSpdyStreamInitialWindowSize
) - kUploadDataSize
,
2103 stream
->stream()->recv_window_size());
2105 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2106 ASSERT_TRUE(response
!= NULL
);
2107 ASSERT_TRUE(response
->headers
!= NULL
);
2108 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
2109 EXPECT_TRUE(response
->was_fetched_via_spdy
);
2111 // Force sending of WINDOW_UPDATE by setting initial_recv_window_size to a
2113 stream
->stream()->set_initial_recv_window_size(kUploadDataSize
/ 2);
2115 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
2116 // size increased to default.
2117 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kUploadDataSize
));
2118 rv
= trans
->Read(buf
, kUploadDataSize
, CompletionCallback());
2119 EXPECT_EQ(kUploadDataSize
, rv
);
2120 std::string
content(buf
->data(), buf
->data()+kUploadDataSize
);
2121 EXPECT_STREQ(kUploadData
, content
.c_str());
2123 // Schedule the reading of empty data frame with FIN
2124 data
.CompleteRead();
2126 // Force write of WINDOW_UPDATE which was scheduled during the above
2128 MessageLoop::current()->RunUntilIdle();
2131 data
.CompleteRead();
2133 helper
.VerifyDataConsumed();
2136 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
2137 TEST_P(SpdyNetworkTransactionSpdy3Test
, WindowUpdateOverflow
) {
2138 // Number of full frames we hope to write (but will not, used to
2139 // set content-length header correctly)
2140 static int kFrameCount
= 3;
2142 scoped_ptr
<std::string
> content(
2143 new std::string(kMaxSpdyFrameChunkSize
, 'a'));
2144 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(
2145 kMaxSpdyFrameChunkSize
* kFrameCount
, NULL
, 0));
2146 scoped_ptr
<SpdyFrame
> body(
2147 ConstructSpdyBodyFrame(1, content
->c_str(), content
->size(), false));
2148 scoped_ptr
<SpdyFrame
> rst(
2149 ConstructSpdyRstStream(1, FLOW_CONTROL_ERROR
));
2151 // We're not going to write a data frame with FIN, we'll receive a bad
2152 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2153 MockWrite writes
[] = {
2154 CreateMockWrite(*req
, 0),
2155 CreateMockWrite(*body
, 2),
2156 CreateMockWrite(*rst
, 3),
2159 static const int32 kDeltaWindowSize
= 0x7fffffff; // cause an overflow
2160 scoped_ptr
<SpdyFrame
> window_update(
2161 ConstructSpdyWindowUpdate(1, kDeltaWindowSize
));
2162 MockRead reads
[] = {
2163 CreateMockRead(*window_update
, 1),
2164 MockRead(ASYNC
, 0, 4) // EOF
2167 DeterministicSocketData
data(reads
, arraysize(reads
),
2168 writes
, arraysize(writes
));
2170 ScopedVector
<UploadElementReader
> element_readers
;
2171 for (int i
= 0; i
< kFrameCount
; ++i
) {
2172 element_readers
.push_back(
2173 new UploadBytesElementReader(content
->c_str(), content
->size()));
2175 UploadDataStream
upload_data_stream(&element_readers
, 0);
2177 // Setup the request
2178 HttpRequestInfo request
;
2179 request
.method
= "POST";
2180 request
.url
= GURL("http://www.google.com/");
2181 request
.upload_data_stream
= &upload_data_stream
;
2183 NormalSpdyTransactionHelper
helper(request
,
2184 BoundNetLog(), GetParam(), NULL
);
2185 helper
.SetDeterministic();
2186 helper
.RunPreTestSetup();
2187 helper
.AddDeterministicData(&data
);
2188 HttpNetworkTransaction
* trans
= helper
.trans();
2190 TestCompletionCallback callback
;
2191 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2192 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2195 ASSERT_TRUE(callback
.have_result());
2196 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, callback
.WaitForResult());
2197 helper
.VerifyDataConsumed();
2200 // Test that after hitting a send window size of 0, the write process
2201 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
2203 // This test constructs a POST request followed by enough data frames
2204 // containing 'a' that would make the window size 0, followed by another
2205 // data frame containing default content (which is "hello!") and this frame
2206 // also contains a FIN flag. DelayedSocketData is used to enforce all
2207 // writes go through before a read could happen. However, the last frame
2208 // ("hello!") is not supposed to go through since by the time its turn
2209 // arrives, window size is 0. At this point MessageLoop::Run() called via
2210 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
2211 // which returns after performing all possible writes. We use DCHECKS to
2212 // ensure that last data frame is still there and stream has stalled.
2213 // After that, next read is artifically enforced, which causes a
2214 // WINDOW_UPDATE to be read and I/O process resumes.
2215 TEST_P(SpdyNetworkTransactionSpdy3Test
, FlowControlStallResume
) {
2216 // Number of frames we need to send to zero out the window size: data
2217 // frames plus SYN_STREAM plus the last data frame; also we need another
2218 // data frame that we will send once the WINDOW_UPDATE is received,
2220 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
2222 // Calculate last frame's size; 0 size data frame is legal.
2223 size_t last_frame_size
=
2224 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
2226 // Construct content for a data frame of maximum size.
2227 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
2229 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(
2230 kSpdyStreamInitialWindowSize
+ kUploadDataSize
, NULL
, 0));
2233 scoped_ptr
<SpdyFrame
> body1(
2234 ConstructSpdyBodyFrame(1, content
.c_str(), content
.size(), false));
2236 // Last frame to zero out the window size.
2237 scoped_ptr
<SpdyFrame
> body2(
2238 ConstructSpdyBodyFrame(1, content
.c_str(), last_frame_size
, false));
2240 // Data frame to be sent once WINDOW_UPDATE frame is received.
2241 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(1, true));
2243 // Fill in mock writes.
2244 scoped_array
<MockWrite
> writes(new MockWrite
[num_writes
]);
2246 writes
[i
] = CreateMockWrite(*req
);
2247 for (i
= 1; i
< num_writes
- 2; i
++)
2248 writes
[i
] = CreateMockWrite(*body1
);
2249 writes
[i
++] = CreateMockWrite(*body2
);
2250 writes
[i
] = CreateMockWrite(*body3
);
2252 // Construct read frame, give enough space to upload the rest of the
2254 scoped_ptr
<SpdyFrame
> window_update(
2255 ConstructSpdyWindowUpdate(1, kUploadDataSize
));
2256 scoped_ptr
<SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2257 MockRead reads
[] = {
2258 CreateMockRead(*window_update
),
2259 CreateMockRead(*window_update
),
2260 CreateMockRead(*reply
),
2261 CreateMockRead(*body2
),
2262 CreateMockRead(*body3
),
2263 MockRead(ASYNC
, 0, 0) // EOF
2266 // Force all writes to happen before any read, last write will not
2267 // actually queue a frame, due to window size being 0.
2268 DelayedSocketData
data(num_writes
, reads
, arraysize(reads
),
2269 writes
.get(), num_writes
);
2271 ScopedVector
<UploadElementReader
> element_readers
;
2272 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
2273 upload_data_string
.append(kUploadData
, kUploadDataSize
);
2274 element_readers
.push_back(new UploadBytesElementReader(
2275 upload_data_string
.c_str(), upload_data_string
.size()));
2276 UploadDataStream
upload_data_stream(&element_readers
, 0);
2278 HttpRequestInfo request
;
2279 request
.method
= "POST";
2280 request
.url
= GURL("http://www.google.com/");
2281 request
.upload_data_stream
= &upload_data_stream
;
2282 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam(), NULL
);
2283 helper
.AddData(&data
);
2284 helper
.RunPreTestSetup();
2286 HttpNetworkTransaction
* trans
= helper
.trans();
2288 TestCompletionCallback callback
;
2289 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2290 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2292 MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2294 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2295 ASSERT_TRUE(stream
!= NULL
);
2296 ASSERT_TRUE(stream
->stream() != NULL
);
2297 EXPECT_EQ(0, stream
->stream()->send_window_size());
2298 // All the body data should have been read.
2299 // TODO(satorux): This is because of the weirdness in reading the request
2300 // body in OnSendBodyComplete(). See crbug.com/113107.
2301 EXPECT_TRUE(upload_data_stream
.IsEOF());
2302 // But the body is not yet fully sent (kUploadData is not yet sent).
2303 EXPECT_FALSE(stream
->stream()->body_sent());
2305 data
.ForceNextRead(); // Read in WINDOW_UPDATE frame.
2306 rv
= callback
.WaitForResult();
2307 helper
.VerifyDataConsumed();
2310 // Test we correctly handle the case where the SETTINGS frame results in
2311 // unstalling the send window.
2312 TEST_P(SpdyNetworkTransactionSpdy3Test
, FlowControlStallResumeAfterSettings
) {
2313 // Number of frames we need to send to zero out the window size: data
2314 // frames plus SYN_STREAM plus the last data frame; also we need another
2315 // data frame that we will send once the SETTING is received, therefore +3.
2316 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
2318 // Calculate last frame's size; 0 size data frame is legal.
2319 size_t last_frame_size
=
2320 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
2322 // Construct content for a data frame of maximum size.
2323 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
2325 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(
2326 kSpdyStreamInitialWindowSize
+ kUploadDataSize
, NULL
, 0));
2329 scoped_ptr
<SpdyFrame
> body1(
2330 ConstructSpdyBodyFrame(1, content
.c_str(), content
.size(), false));
2332 // Last frame to zero out the window size.
2333 scoped_ptr
<SpdyFrame
> body2(
2334 ConstructSpdyBodyFrame(1, content
.c_str(), last_frame_size
, false));
2336 // Data frame to be sent once SETTINGS frame is received.
2337 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(1, true));
2339 // Fill in mock writes.
2340 scoped_array
<MockWrite
> writes(new MockWrite
[num_writes
]);
2342 writes
[i
] = CreateMockWrite(*req
);
2343 for (i
= 1; i
< num_writes
- 2; i
++)
2344 writes
[i
] = CreateMockWrite(*body1
);
2345 writes
[i
++] = CreateMockWrite(*body2
);
2346 writes
[i
] = CreateMockWrite(*body3
);
2348 // Construct read frame for SETTINGS that gives enough space to upload the
2349 // rest of the data.
2350 SettingsMap settings
;
2351 settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
2352 SettingsFlagsAndValue(
2353 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
* 2);
2354 scoped_ptr
<SpdyFrame
> settings_frame_large(ConstructSpdySettings(settings
));
2355 scoped_ptr
<SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2356 MockRead reads
[] = {
2357 CreateMockRead(*settings_frame_large
),
2358 CreateMockRead(*reply
),
2359 CreateMockRead(*body2
),
2360 CreateMockRead(*body3
),
2361 MockRead(ASYNC
, 0, 0) // EOF
2364 // Force all writes to happen before any read, last write will not
2365 // actually queue a frame, due to window size being 0.
2366 DelayedSocketData
data(num_writes
, reads
, arraysize(reads
),
2367 writes
.get(), num_writes
);
2369 ScopedVector
<UploadElementReader
> element_readers
;
2370 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
2371 upload_data_string
.append(kUploadData
, kUploadDataSize
);
2372 element_readers
.push_back(new UploadBytesElementReader(
2373 upload_data_string
.c_str(), upload_data_string
.size()));
2374 UploadDataStream
upload_data_stream(&element_readers
, 0);
2376 HttpRequestInfo request
;
2377 request
.method
= "POST";
2378 request
.url
= GURL("http://www.google.com/");
2379 request
.upload_data_stream
= &upload_data_stream
;
2380 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam(), NULL
);
2381 helper
.AddData(&data
);
2382 helper
.RunPreTestSetup();
2384 HttpNetworkTransaction
* trans
= helper
.trans();
2386 TestCompletionCallback callback
;
2387 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2388 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2390 MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2392 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2393 ASSERT_TRUE(stream
!= NULL
);
2394 ASSERT_TRUE(stream
->stream() != NULL
);
2395 EXPECT_EQ(0, stream
->stream()->send_window_size());
2397 // All the body data should have been read.
2398 // TODO(satorux): This is because of the weirdness in reading the request
2399 // body in OnSendBodyComplete(). See crbug.com/113107.
2400 EXPECT_TRUE(upload_data_stream
.IsEOF());
2401 // But the body is not yet fully sent (kUploadData is not yet sent).
2402 EXPECT_FALSE(stream
->stream()->body_sent());
2403 EXPECT_TRUE(stream
->stream()->stalled_by_flow_control());
2405 data
.ForceNextRead(); // Read in SETTINGS frame to unstall.
2406 rv
= callback
.WaitForResult();
2407 helper
.VerifyDataConsumed();
2408 EXPECT_FALSE(stream
->stream()->stalled_by_flow_control());
2411 // Test we correctly handle the case where the SETTINGS frame results in a
2412 // negative send window size.
2413 TEST_P(SpdyNetworkTransactionSpdy3Test
, FlowControlNegativeSendWindowSize
) {
2414 // Number of frames we need to send to zero out the window size: data
2415 // frames plus SYN_STREAM plus the last data frame; also we need another
2416 // data frame that we will send once the SETTING is received, therefore +3.
2417 size_t num_writes
= kSpdyStreamInitialWindowSize
/ kMaxSpdyFrameChunkSize
+ 3;
2419 // Calculate last frame's size; 0 size data frame is legal.
2420 size_t last_frame_size
=
2421 kSpdyStreamInitialWindowSize
% kMaxSpdyFrameChunkSize
;
2423 // Construct content for a data frame of maximum size.
2424 std::string
content(kMaxSpdyFrameChunkSize
, 'a');
2426 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPost(
2427 kSpdyStreamInitialWindowSize
+ kUploadDataSize
, NULL
, 0));
2430 scoped_ptr
<SpdyFrame
> body1(
2431 ConstructSpdyBodyFrame(1, content
.c_str(), content
.size(), false));
2433 // Last frame to zero out the window size.
2434 scoped_ptr
<SpdyFrame
> body2(
2435 ConstructSpdyBodyFrame(1, content
.c_str(), last_frame_size
, false));
2437 // Data frame to be sent once SETTINGS frame is received.
2438 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(1, true));
2440 // Fill in mock writes.
2441 scoped_array
<MockWrite
> writes(new MockWrite
[num_writes
]);
2443 writes
[i
] = CreateMockWrite(*req
);
2444 for (i
= 1; i
< num_writes
- 2; i
++)
2445 writes
[i
] = CreateMockWrite(*body1
);
2446 writes
[i
++] = CreateMockWrite(*body2
);
2447 writes
[i
] = CreateMockWrite(*body3
);
2449 // Construct read frame for SETTINGS that makes the send_window_size
2451 SettingsMap new_settings
;
2452 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
2453 SettingsFlagsAndValue(
2454 SETTINGS_FLAG_NONE
, kSpdyStreamInitialWindowSize
/ 2);
2455 scoped_ptr
<SpdyFrame
> settings_frame_small(
2456 ConstructSpdySettings(new_settings
));
2457 // Construct read frame for WINDOW_UPDATE that makes the send_window_size
2459 scoped_ptr
<SpdyFrame
> window_update_init_size(
2460 ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize
));
2461 scoped_ptr
<SpdyFrame
> reply(ConstructSpdyPostSynReply(NULL
, 0));
2462 MockRead reads
[] = {
2463 CreateMockRead(*settings_frame_small
),
2464 CreateMockRead(*window_update_init_size
),
2465 CreateMockRead(*reply
),
2466 CreateMockRead(*body2
),
2467 CreateMockRead(*body3
),
2468 MockRead(ASYNC
, 0, 0) // EOF
2471 // Force all writes to happen before any read, last write will not actually
2472 // queue a frame, due to window size being 0.
2473 DelayedSocketData
data(num_writes
, reads
, arraysize(reads
),
2474 writes
.get(), num_writes
);
2476 ScopedVector
<UploadElementReader
> element_readers
;
2477 std::string
upload_data_string(kSpdyStreamInitialWindowSize
, 'a');
2478 upload_data_string
.append(kUploadData
, kUploadDataSize
);
2479 element_readers
.push_back(new UploadBytesElementReader(
2480 upload_data_string
.c_str(), upload_data_string
.size()));
2481 UploadDataStream
upload_data_stream(&element_readers
, 0);
2483 HttpRequestInfo request
;
2484 request
.method
= "POST";
2485 request
.url
= GURL("http://www.google.com/");
2486 request
.upload_data_stream
= &upload_data_stream
;
2487 NormalSpdyTransactionHelper
helper(request
, BoundNetLog(), GetParam(), NULL
);
2488 helper
.AddData(&data
);
2489 helper
.RunPreTestSetup();
2491 HttpNetworkTransaction
* trans
= helper
.trans();
2493 TestCompletionCallback callback
;
2494 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2495 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2497 MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2499 SpdyHttpStream
* stream
= static_cast<SpdyHttpStream
*>(trans
->stream_
.get());
2500 ASSERT_TRUE(stream
!= NULL
);
2501 ASSERT_TRUE(stream
->stream() != NULL
);
2502 EXPECT_EQ(0, stream
->stream()->send_window_size());
2504 // All the body data should have been read.
2505 // TODO(satorux): This is because of the weirdness in reading the request
2506 // body in OnSendBodyComplete(). See crbug.com/113107.
2507 EXPECT_TRUE(upload_data_stream
.IsEOF());
2508 // But the body is not yet fully sent (kUploadData is not yet sent).
2509 EXPECT_FALSE(stream
->stream()->body_sent());
2511 data
.ForceNextRead(); // Read in WINDOW_UPDATE or SETTINGS frame.
2512 rv
= callback
.WaitForResult();
2513 helper
.VerifyDataConsumed();
2516 TEST_P(SpdyNetworkTransactionSpdy3Test
, ResetReplyWithTransferEncoding
) {
2517 // Construct the request.
2518 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2519 scoped_ptr
<SpdyFrame
> rst(ConstructSpdyRstStream(1, PROTOCOL_ERROR
));
2520 MockWrite writes
[] = {
2521 CreateMockWrite(*req
),
2522 CreateMockWrite(*rst
),
2525 const char* const headers
[] = {
2526 "transfer-encoding", "chuncked"
2528 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(headers
, 1, 1));
2529 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2530 MockRead reads
[] = {
2531 CreateMockRead(*resp
),
2532 CreateMockRead(*body
),
2533 MockRead(ASYNC
, 0, 0) // EOF
2536 DelayedSocketData
data(1, reads
, arraysize(reads
),
2537 writes
, arraysize(writes
));
2538 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2539 BoundNetLog(), GetParam(), NULL
);
2540 helper
.RunToCompletion(&data
);
2541 TransactionHelperResult out
= helper
.output();
2542 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2544 helper
.session()->spdy_session_pool()->CloseAllSessions();
2545 helper
.VerifyDataConsumed();
2548 TEST_P(SpdyNetworkTransactionSpdy3Test
, ResetPushWithTransferEncoding
) {
2549 // Construct the request.
2550 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2551 scoped_ptr
<SpdyFrame
> rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR
));
2552 MockWrite writes
[] = {
2553 CreateMockWrite(*req
),
2554 CreateMockWrite(*rst
),
2557 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2558 const char* const headers
[] = {":scheme", "http",
2559 ":host", "www.google.com",
2561 "transfer-encoding", "chunked"};
2562 scoped_ptr
<SpdyFrame
> push(ConstructSpdyPush(headers
, arraysize(headers
) / 2,
2564 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2565 MockRead reads
[] = {
2566 CreateMockRead(*resp
),
2567 CreateMockRead(*push
),
2568 CreateMockRead(*body
),
2569 MockRead(ASYNC
, 0, 0) // EOF
2572 DelayedSocketData
data(1, reads
, arraysize(reads
),
2573 writes
, arraysize(writes
));
2574 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2575 BoundNetLog(), GetParam(), NULL
);
2576 helper
.RunToCompletion(&data
);
2577 TransactionHelperResult out
= helper
.output();
2578 EXPECT_EQ(OK
, out
.rv
);
2579 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
2580 EXPECT_EQ("hello!", out
.response_data
);
2582 helper
.session()->spdy_session_pool()->CloseAllSessions();
2583 helper
.VerifyDataConsumed();
2586 TEST_P(SpdyNetworkTransactionSpdy3Test
, CancelledTransaction
) {
2587 // Construct the request.
2588 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2589 MockWrite writes
[] = {
2590 CreateMockWrite(*req
),
2593 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2594 MockRead reads
[] = {
2595 CreateMockRead(*resp
),
2596 // This following read isn't used by the test, except during the
2597 // RunUntilIdle() call at the end since the SpdySession survives the
2598 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2599 // MockRead will do here.
2600 MockRead(ASYNC
, 0, 0) // EOF
2603 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2604 writes
, arraysize(writes
));
2606 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2607 BoundNetLog(), GetParam(), NULL
);
2608 helper
.RunPreTestSetup();
2609 helper
.AddData(&data
);
2610 HttpNetworkTransaction
* trans
= helper
.trans();
2612 TestCompletionCallback callback
;
2613 int rv
= trans
->Start(
2614 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2615 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2616 helper
.ResetTrans(); // Cancel the transaction.
2618 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2619 // MockClientSocketFactory) are still alive.
2620 MessageLoop::current()->RunUntilIdle();
2621 helper
.VerifyDataNotConsumed();
2624 // Verify that the client sends a Rst Frame upon cancelling the stream.
2625 TEST_P(SpdyNetworkTransactionSpdy3Test
, CancelledTransactionSendRst
) {
2626 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2627 scoped_ptr
<SpdyFrame
> rst(
2628 ConstructSpdyRstStream(1, CANCEL
));
2629 MockWrite writes
[] = {
2630 CreateMockWrite(*req
, 0, SYNCHRONOUS
),
2631 CreateMockWrite(*rst
, 2, SYNCHRONOUS
),
2634 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2635 MockRead reads
[] = {
2636 CreateMockRead(*resp
, 1, ASYNC
),
2637 MockRead(ASYNC
, 0, 0, 3) // EOF
2640 DeterministicSocketData
data(reads
, arraysize(reads
),
2641 writes
, arraysize(writes
));
2643 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2646 helper
.SetDeterministic();
2647 helper
.RunPreTestSetup();
2648 helper
.AddDeterministicData(&data
);
2649 HttpNetworkTransaction
* trans
= helper
.trans();
2651 TestCompletionCallback callback
;
2653 int rv
= trans
->Start(
2654 &CreateGetRequest(), callback
.callback(), BoundNetLog());
2655 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2659 helper
.ResetTrans();
2663 helper
.VerifyDataConsumed();
2666 // Verify that the client can correctly deal with the user callback attempting
2667 // to start another transaction on a session that is closing down. See
2668 // http://crbug.com/47455
2669 TEST_P(SpdyNetworkTransactionSpdy3Test
, StartTransactionOnReadCallback
) {
2670 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2671 MockWrite writes
[] = { CreateMockWrite(*req
) };
2672 MockWrite writes2
[] = { CreateMockWrite(*req
) };
2674 // The indicated length of this packet is longer than its actual length. When
2675 // the session receives an empty packet after this one, it shuts down the
2676 // session, and calls the read callback with the incomplete data.
2677 const uint8 kGetBodyFrame2
[] = {
2678 0x00, 0x00, 0x00, 0x01,
2679 0x01, 0x00, 0x00, 0x07,
2680 'h', 'e', 'l', 'l', 'o', '!',
2683 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2684 MockRead reads
[] = {
2685 CreateMockRead(*resp
, 2),
2686 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2687 MockRead(ASYNC
, reinterpret_cast<const char*>(kGetBodyFrame2
),
2688 arraysize(kGetBodyFrame2
), 4),
2689 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
2690 MockRead(ASYNC
, 0, 0, 6), // EOF
2692 MockRead reads2
[] = {
2693 CreateMockRead(*resp
, 2),
2694 MockRead(ASYNC
, 0, 0, 3), // EOF
2697 OrderedSocketData
data(reads
, arraysize(reads
),
2698 writes
, arraysize(writes
));
2699 DelayedSocketData
data2(1, reads2
, arraysize(reads2
),
2700 writes2
, arraysize(writes2
));
2702 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2703 BoundNetLog(), GetParam(), NULL
);
2704 helper
.RunPreTestSetup();
2705 helper
.AddData(&data
);
2706 helper
.AddData(&data2
);
2707 HttpNetworkTransaction
* trans
= helper
.trans();
2709 // Start the transaction with basic parameters.
2710 TestCompletionCallback callback
;
2711 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2713 rv
= callback
.WaitForResult();
2715 const int kSize
= 3000;
2716 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2719 base::Bind(&SpdyNetworkTransactionSpdy3Test::StartTransactionCallback
,
2721 // This forces an err_IO_pending, which sets the callback.
2722 data
.CompleteRead();
2723 // This finishes the read.
2724 data
.CompleteRead();
2725 helper
.VerifyDataConsumed();
2728 // Verify that the client can correctly deal with the user callback deleting the
2729 // transaction. Failures will usually be valgrind errors. See
2730 // http://crbug.com/46925
2731 TEST_P(SpdyNetworkTransactionSpdy3Test
, DeleteSessionOnReadCallback
) {
2732 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2733 MockWrite writes
[] = { CreateMockWrite(*req
) };
2735 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
2736 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2737 MockRead reads
[] = {
2738 CreateMockRead(*resp
.get(), 2),
2739 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2740 CreateMockRead(*body
.get(), 4),
2741 MockRead(ASYNC
, 0, 0, 5), // EOF
2744 OrderedSocketData
data(reads
, arraysize(reads
),
2745 writes
, arraysize(writes
));
2747 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2748 BoundNetLog(), GetParam(), NULL
);
2749 helper
.RunPreTestSetup();
2750 helper
.AddData(&data
);
2751 HttpNetworkTransaction
* trans
= helper
.trans();
2753 // Start the transaction with basic parameters.
2754 TestCompletionCallback callback
;
2755 int rv
= trans
->Start(&helper
.request(), callback
.callback(), BoundNetLog());
2756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2757 rv
= callback
.WaitForResult();
2759 // Setup a user callback which will delete the session, and clear out the
2760 // memory holding the stream object. Note that the callback deletes trans.
2761 const int kSize
= 3000;
2762 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSize
));
2765 base::Bind(&SpdyNetworkTransactionSpdy3Test::DeleteSessionCallback
,
2766 base::Unretained(&helper
)));
2767 ASSERT_EQ(ERR_IO_PENDING
, rv
);
2768 data
.CompleteRead();
2770 // Finish running rest of tasks.
2771 MessageLoop::current()->RunUntilIdle();
2772 helper
.VerifyDataConsumed();
2775 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2776 TEST_P(SpdyNetworkTransactionSpdy3Test
, RedirectGetRequest
) {
2777 // These are headers which the net::URLRequest tacks on.
2778 const char* const kExtraHeaders
[] = {
2782 const SpdyHeaderInfo kSynStartHeader
= MakeSpdyHeader(SYN_STREAM
);
2783 const char* const kStandardGetHeaders
[] = {
2797 const char* const kStandardGetHeaders2
[] = {
2812 // Setup writes/reads to www.google.com
2813 scoped_ptr
<SpdyFrame
> req(ConstructSpdyPacket(
2814 kSynStartHeader
, kExtraHeaders
, arraysize(kExtraHeaders
) / 2,
2815 kStandardGetHeaders
, arraysize(kStandardGetHeaders
) / 2));
2816 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyPacket(
2817 kSynStartHeader
, kExtraHeaders
, arraysize(kExtraHeaders
) / 2,
2818 kStandardGetHeaders2
, arraysize(kStandardGetHeaders2
) / 2));
2819 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReplyRedirect(1));
2820 MockWrite writes
[] = {
2821 CreateMockWrite(*req
, 1),
2823 MockRead reads
[] = {
2824 CreateMockRead(*resp
, 2),
2825 MockRead(ASYNC
, 0, 0, 3) // EOF
2828 // Setup writes/reads to www.foo.com
2829 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
2830 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
2831 MockWrite writes2
[] = {
2832 CreateMockWrite(*req2
, 1),
2834 MockRead reads2
[] = {
2835 CreateMockRead(*resp2
, 2),
2836 CreateMockRead(*body2
, 3),
2837 MockRead(ASYNC
, 0, 0, 4) // EOF
2839 OrderedSocketData
data(reads
, arraysize(reads
),
2840 writes
, arraysize(writes
));
2841 OrderedSocketData
data2(reads2
, arraysize(reads2
),
2842 writes2
, arraysize(writes2
));
2844 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2845 HttpStreamFactory::set_force_spdy_over_ssl(false);
2846 HttpStreamFactory::set_force_spdy_always(true);
2849 SpdyURLRequestContext spdy_url_request_context
;
2851 GURL("http://www.google.com/"), &d
, &spdy_url_request_context
);
2852 spdy_url_request_context
.socket_factory().
2853 AddSocketDataProvider(&data
);
2854 spdy_url_request_context
.socket_factory().
2855 AddSocketDataProvider(&data2
);
2857 d
.set_quit_on_redirect(true);
2859 MessageLoop::current()->Run();
2860 EXPECT_EQ(1, d
.received_redirect_count());
2862 r
.FollowDeferredRedirect();
2863 MessageLoop::current()->Run();
2864 EXPECT_EQ(1, d
.response_started_count());
2865 EXPECT_FALSE(d
.received_data_before_response());
2866 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r
.status().status());
2867 std::string
contents("hello!");
2868 EXPECT_EQ(contents
, d
.data_received());
2870 EXPECT_TRUE(data
.at_read_eof());
2871 EXPECT_TRUE(data
.at_write_eof());
2872 EXPECT_TRUE(data2
.at_read_eof());
2873 EXPECT_TRUE(data2
.at_write_eof());
2876 // Detect response with upper case headers and reset the stream.
2877 TEST_P(SpdyNetworkTransactionSpdy3Test
, UpperCaseHeaders
) {
2878 scoped_ptr
<SpdyFrame
>
2879 syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2880 scoped_ptr
<SpdyFrame
>
2881 rst(ConstructSpdyRstStream(1, PROTOCOL_ERROR
));
2882 MockWrite writes
[] = {
2883 CreateMockWrite(*syn
, 0),
2884 CreateMockWrite(*rst
, 2),
2887 const char* const kExtraHeaders
[] = {"X-UpperCase", "yes"};
2888 scoped_ptr
<SpdyFrame
>
2889 reply(ConstructSpdyGetSynReply(kExtraHeaders
, 1, 1));
2890 MockRead reads
[] = {
2891 CreateMockRead(*reply
, 1),
2892 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2895 HttpResponseInfo response
;
2896 HttpResponseInfo response2
;
2897 OrderedSocketData
data(reads
, arraysize(reads
),
2898 writes
, arraysize(writes
));
2899 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2900 BoundNetLog(), GetParam(), NULL
);
2901 helper
.RunToCompletion(&data
);
2902 TransactionHelperResult out
= helper
.output();
2903 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2906 // Detect response with upper case headers in a HEADERS frame and reset the
2908 TEST_P(SpdyNetworkTransactionSpdy3Test
, UpperCaseHeadersInHeadersFrame
) {
2909 scoped_ptr
<SpdyFrame
>
2910 syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2911 scoped_ptr
<SpdyFrame
>
2912 rst(ConstructSpdyRstStream(1, PROTOCOL_ERROR
));
2913 MockWrite writes
[] = {
2914 CreateMockWrite(*syn
, 0),
2915 CreateMockWrite(*rst
, 2),
2918 static const char* const kInitialHeaders
[] = {
2919 ":status", "200 OK",
2920 ":version", "HTTP/1.1"
2922 static const char* const kLateHeaders
[] = {
2923 "X-UpperCase", "yes",
2925 scoped_ptr
<SpdyFrame
>
2926 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
2927 arraysize(kInitialHeaders
) / 2,
2936 scoped_ptr
<SpdyFrame
>
2937 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
2938 arraysize(kLateHeaders
) / 2,
2947 scoped_ptr
<SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, true));
2948 MockRead reads
[] = {
2949 CreateMockRead(*stream1_reply
),
2950 CreateMockRead(*stream1_headers
),
2951 CreateMockRead(*stream1_body
),
2952 MockRead(ASYNC
, 0, 0) // EOF
2955 DelayedSocketData
data(1, reads
, arraysize(reads
),
2956 writes
, arraysize(writes
));
2957 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2958 BoundNetLog(), GetParam(), NULL
);
2959 helper
.RunToCompletion(&data
);
2960 TransactionHelperResult out
= helper
.output();
2961 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
2964 // Detect push stream with upper case headers and reset the stream.
2965 TEST_P(SpdyNetworkTransactionSpdy3Test
, UpperCaseHeadersOnPush
) {
2966 scoped_ptr
<SpdyFrame
>
2967 syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
2968 scoped_ptr
<SpdyFrame
>
2969 rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR
));
2970 MockWrite writes
[] = {
2971 CreateMockWrite(*syn
, 0),
2972 CreateMockWrite(*rst
, 2),
2975 scoped_ptr
<SpdyFrame
>
2976 reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
2977 const char* const extra_headers
[] = {
2978 "X-UpperCase", "yes"
2980 scoped_ptr
<SpdyFrame
>
2981 push(ConstructSpdyPush(extra_headers
, arraysize(extra_headers
) / 2,
2983 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
2984 MockRead reads
[] = {
2985 CreateMockRead(*reply
, 1),
2986 CreateMockRead(*push
, 1),
2987 CreateMockRead(*body
, 1),
2988 MockRead(ASYNC
, ERR_IO_PENDING
, 3), // Force a pause
2991 HttpResponseInfo response
;
2992 HttpResponseInfo response2
;
2993 OrderedSocketData
data(reads
, arraysize(reads
),
2994 writes
, arraysize(writes
));
2995 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
2996 BoundNetLog(), GetParam(), NULL
);
2997 helper
.RunToCompletion(&data
);
2998 TransactionHelperResult out
= helper
.output();
2999 EXPECT_EQ(OK
, out
.rv
);
3002 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
3004 TEST_P(SpdyNetworkTransactionSpdy3Test
, RedirectServerPush
) {
3005 // These are headers which the net::URLRequest tacks on.
3006 const char* const kExtraHeaders
[] = {
3010 const SpdyHeaderInfo kSynStartHeader
= MakeSpdyHeader(SYN_STREAM
);
3011 const char* const kStandardGetHeaders
[] = {
3026 // Setup writes/reads to www.google.com
3027 scoped_ptr
<SpdyFrame
> req(
3028 ConstructSpdyPacket(kSynStartHeader
,
3030 arraysize(kExtraHeaders
) / 2,
3031 kStandardGetHeaders
,
3032 arraysize(kStandardGetHeaders
) / 2));
3033 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
3034 scoped_ptr
<SpdyFrame
> rep(
3035 ConstructSpdyPush(NULL
,
3039 "http://www.google.com/foo.dat",
3040 "301 Moved Permanently",
3041 "http://www.foo.com/index.php"));
3042 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3043 scoped_ptr
<SpdyFrame
> rst(ConstructSpdyRstStream(2, CANCEL
));
3044 MockWrite writes
[] = {
3045 CreateMockWrite(*req
, 1),
3046 CreateMockWrite(*rst
, 6),
3048 MockRead reads
[] = {
3049 CreateMockRead(*resp
, 2),
3050 CreateMockRead(*rep
, 3),
3051 CreateMockRead(*body
, 4),
3052 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3053 MockRead(ASYNC
, 0, 0, 7) // EOF
3056 // Setup writes/reads to www.foo.com
3057 const char* const kStandardGetHeaders2
[] = {
3071 scoped_ptr
<SpdyFrame
> req2(
3072 ConstructSpdyPacket(kSynStartHeader
,
3074 arraysize(kExtraHeaders
) / 2,
3075 kStandardGetHeaders2
,
3076 arraysize(kStandardGetHeaders2
) / 2));
3077 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
3078 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
3079 MockWrite writes2
[] = {
3080 CreateMockWrite(*req2
, 1),
3082 MockRead reads2
[] = {
3083 CreateMockRead(*resp2
, 2),
3084 CreateMockRead(*body2
, 3),
3085 MockRead(ASYNC
, 0, 0, 5) // EOF
3087 OrderedSocketData
data(reads
, arraysize(reads
),
3088 writes
, arraysize(writes
));
3089 OrderedSocketData
data2(reads2
, arraysize(reads2
),
3090 writes2
, arraysize(writes2
));
3092 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
3093 HttpStreamFactory::set_force_spdy_over_ssl(false);
3094 HttpStreamFactory::set_force_spdy_always(true);
3097 SpdyURLRequestContext spdy_url_request_context
;
3100 GURL("http://www.google.com/"), &d
, &spdy_url_request_context
);
3101 spdy_url_request_context
.socket_factory().
3102 AddSocketDataProvider(&data
);
3105 MessageLoop::current()->Run();
3107 EXPECT_EQ(0, d
.received_redirect_count());
3108 std::string
contents("hello!");
3109 EXPECT_EQ(contents
, d
.data_received());
3112 GURL("http://www.google.com/foo.dat"), &d2
, &spdy_url_request_context
);
3113 spdy_url_request_context
.socket_factory().
3114 AddSocketDataProvider(&data2
);
3116 d2
.set_quit_on_redirect(true);
3118 MessageLoop::current()->Run();
3119 EXPECT_EQ(1, d2
.received_redirect_count());
3121 r2
.FollowDeferredRedirect();
3122 MessageLoop::current()->Run();
3123 EXPECT_EQ(1, d2
.response_started_count());
3124 EXPECT_FALSE(d2
.received_data_before_response());
3125 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, r2
.status().status());
3126 std::string
contents2("hello!");
3127 EXPECT_EQ(contents2
, d2
.data_received());
3129 data
.CompleteRead();
3130 data2
.CompleteRead();
3131 EXPECT_TRUE(data
.at_read_eof());
3132 EXPECT_TRUE(data
.at_write_eof());
3133 EXPECT_TRUE(data2
.at_read_eof());
3134 EXPECT_TRUE(data2
.at_write_eof());
3137 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushSingleDataFrame
) {
3138 static const unsigned char kPushBodyFrame
[] = {
3139 0x00, 0x00, 0x00, 0x02, // header, ID
3140 0x01, 0x00, 0x00, 0x06, // FIN, length
3141 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3143 scoped_ptr
<SpdyFrame
>
3144 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3145 scoped_ptr
<SpdyFrame
>
3146 stream1_body(ConstructSpdyBodyFrame(1, true));
3147 MockWrite writes
[] = {
3148 CreateMockWrite(*stream1_syn
, 1),
3151 scoped_ptr
<SpdyFrame
>
3152 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3153 scoped_ptr
<SpdyFrame
>
3154 stream2_syn(ConstructSpdyPush(NULL
,
3158 "http://www.google.com/foo.dat"));
3159 MockRead reads
[] = {
3160 CreateMockRead(*stream1_reply
, 2),
3161 CreateMockRead(*stream2_syn
, 3),
3162 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
3163 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
3164 arraysize(kPushBodyFrame
), 5),
3165 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
3168 HttpResponseInfo response
;
3169 HttpResponseInfo response2
;
3170 std::string
expected_push_result("pushed");
3171 OrderedSocketData
data(reads
, arraysize(reads
),
3172 writes
, arraysize(writes
));
3173 RunServerPushTest(&data
,
3176 expected_push_result
);
3178 // Verify the SYN_REPLY.
3179 EXPECT_TRUE(response
.headers
!= NULL
);
3180 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3182 // Verify the pushed stream.
3183 EXPECT_TRUE(response2
.headers
!= NULL
);
3184 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3187 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushBeforeSynReply
) {
3188 static const unsigned char kPushBodyFrame
[] = {
3189 0x00, 0x00, 0x00, 0x02, // header, ID
3190 0x01, 0x00, 0x00, 0x06, // FIN, length
3191 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3193 scoped_ptr
<SpdyFrame
>
3194 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3195 scoped_ptr
<SpdyFrame
>
3196 stream1_body(ConstructSpdyBodyFrame(1, true));
3197 MockWrite writes
[] = {
3198 CreateMockWrite(*stream1_syn
, 1),
3201 scoped_ptr
<SpdyFrame
>
3202 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3203 scoped_ptr
<SpdyFrame
>
3204 stream2_syn(ConstructSpdyPush(NULL
,
3208 "http://www.google.com/foo.dat"));
3209 MockRead reads
[] = {
3210 CreateMockRead(*stream2_syn
, 2),
3211 CreateMockRead(*stream1_reply
, 3),
3212 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
3213 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
3214 arraysize(kPushBodyFrame
), 5),
3215 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
3218 HttpResponseInfo response
;
3219 HttpResponseInfo response2
;
3220 std::string
expected_push_result("pushed");
3221 OrderedSocketData
data(reads
, arraysize(reads
),
3222 writes
, arraysize(writes
));
3223 RunServerPushTest(&data
,
3226 expected_push_result
);
3228 // Verify the SYN_REPLY.
3229 EXPECT_TRUE(response
.headers
!= NULL
);
3230 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3232 // Verify the pushed stream.
3233 EXPECT_TRUE(response2
.headers
!= NULL
);
3234 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3237 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushSingleDataFrame2
) {
3238 static const unsigned char kPushBodyFrame
[] = {
3239 0x00, 0x00, 0x00, 0x02, // header, ID
3240 0x01, 0x00, 0x00, 0x06, // FIN, length
3241 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3243 scoped_ptr
<SpdyFrame
>
3244 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3245 MockWrite writes
[] = {
3246 CreateMockWrite(*stream1_syn
, 1),
3249 scoped_ptr
<SpdyFrame
>
3250 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3251 scoped_ptr
<SpdyFrame
>
3252 stream2_syn(ConstructSpdyPush(NULL
,
3256 "http://www.google.com/foo.dat"));
3257 scoped_ptr
<SpdyFrame
>
3258 stream1_body(ConstructSpdyBodyFrame(1, true));
3259 MockRead reads
[] = {
3260 CreateMockRead(*stream1_reply
, 2),
3261 CreateMockRead(*stream2_syn
, 3),
3262 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
3263 arraysize(kPushBodyFrame
), 5),
3264 CreateMockRead(*stream1_body
, 4, SYNCHRONOUS
),
3265 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
3268 HttpResponseInfo response
;
3269 HttpResponseInfo response2
;
3270 std::string
expected_push_result("pushed");
3271 OrderedSocketData
data(reads
, arraysize(reads
),
3272 writes
, arraysize(writes
));
3273 RunServerPushTest(&data
,
3276 expected_push_result
);
3278 // Verify the SYN_REPLY.
3279 EXPECT_TRUE(response
.headers
!= NULL
);
3280 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3282 // Verify the pushed stream.
3283 EXPECT_TRUE(response2
.headers
!= NULL
);
3284 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3287 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushServerAborted
) {
3288 scoped_ptr
<SpdyFrame
>
3289 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3290 scoped_ptr
<SpdyFrame
>
3291 stream1_body(ConstructSpdyBodyFrame(1, true));
3292 MockWrite writes
[] = {
3293 CreateMockWrite(*stream1_syn
, 1),
3296 scoped_ptr
<SpdyFrame
>
3297 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3298 scoped_ptr
<SpdyFrame
>
3299 stream2_syn(ConstructSpdyPush(NULL
,
3303 "http://www.google.com/foo.dat"));
3304 scoped_ptr
<SpdyFrame
>
3305 stream2_rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR
));
3306 MockRead reads
[] = {
3307 CreateMockRead(*stream1_reply
, 2),
3308 CreateMockRead(*stream2_syn
, 3),
3309 CreateMockRead(*stream2_rst
, 4),
3310 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
3311 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
3314 OrderedSocketData
data(reads
, arraysize(reads
),
3315 writes
, arraysize(writes
));
3316 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3317 BoundNetLog(), GetParam(), NULL
);
3319 helper
.RunPreTestSetup();
3320 helper
.AddData(&data
);
3322 HttpNetworkTransaction
* trans
= helper
.trans();
3324 // Start the transaction with basic parameters.
3325 TestCompletionCallback callback
;
3326 int rv
= trans
->Start(
3327 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3328 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3329 rv
= callback
.WaitForResult();
3332 // Verify that we consumed all test data.
3333 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3334 << data
.read_count()
3336 << data
.read_index();
3337 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3338 << data
.write_count()
3340 << data
.write_index();
3342 // Verify the SYN_REPLY.
3343 HttpResponseInfo response
= *trans
->GetResponseInfo();
3344 EXPECT_TRUE(response
.headers
!= NULL
);
3345 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3348 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushDuplicate
) {
3349 // Verify that we don't leak streams and that we properly send a reset
3350 // if the server pushes the same stream twice.
3351 static const unsigned char kPushBodyFrame
[] = {
3352 0x00, 0x00, 0x00, 0x02, // header, ID
3353 0x01, 0x00, 0x00, 0x06, // FIN, length
3354 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3357 scoped_ptr
<SpdyFrame
>
3358 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3359 scoped_ptr
<SpdyFrame
>
3360 stream1_body(ConstructSpdyBodyFrame(1, true));
3361 scoped_ptr
<SpdyFrame
>
3362 stream3_rst(ConstructSpdyRstStream(4, PROTOCOL_ERROR
));
3363 MockWrite writes
[] = {
3364 CreateMockWrite(*stream1_syn
, 1),
3365 CreateMockWrite(*stream3_rst
, 5),
3368 scoped_ptr
<SpdyFrame
>
3369 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3370 scoped_ptr
<SpdyFrame
>
3371 stream2_syn(ConstructSpdyPush(NULL
,
3375 "http://www.google.com/foo.dat"));
3376 scoped_ptr
<SpdyFrame
>
3377 stream3_syn(ConstructSpdyPush(NULL
,
3381 "http://www.google.com/foo.dat"));
3382 MockRead reads
[] = {
3383 CreateMockRead(*stream1_reply
, 2),
3384 CreateMockRead(*stream2_syn
, 3),
3385 CreateMockRead(*stream3_syn
, 4),
3386 CreateMockRead(*stream1_body
, 6, SYNCHRONOUS
),
3387 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
3388 arraysize(kPushBodyFrame
), 7),
3389 MockRead(ASYNC
, ERR_IO_PENDING
, 8), // Force a pause
3392 HttpResponseInfo response
;
3393 HttpResponseInfo response2
;
3394 std::string
expected_push_result("pushed");
3395 OrderedSocketData
data(reads
, arraysize(reads
),
3396 writes
, arraysize(writes
));
3397 RunServerPushTest(&data
,
3400 expected_push_result
);
3402 // Verify the SYN_REPLY.
3403 EXPECT_TRUE(response
.headers
!= NULL
);
3404 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3406 // Verify the pushed stream.
3407 EXPECT_TRUE(response2
.headers
!= NULL
);
3408 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3411 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushMultipleDataFrame
) {
3412 static const unsigned char kPushBodyFrame1
[] = {
3413 0x00, 0x00, 0x00, 0x02, // header, ID
3414 0x01, 0x00, 0x00, 0x1F, // FIN, length
3415 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3417 static const char kPushBodyFrame2
[] = " my darling";
3418 static const char kPushBodyFrame3
[] = " hello";
3419 static const char kPushBodyFrame4
[] = " my baby";
3421 scoped_ptr
<SpdyFrame
>
3422 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3423 scoped_ptr
<SpdyFrame
>
3424 stream1_body(ConstructSpdyBodyFrame(1, true));
3425 MockWrite writes
[] = {
3426 CreateMockWrite(*stream1_syn
, 1),
3429 scoped_ptr
<SpdyFrame
>
3430 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3431 scoped_ptr
<SpdyFrame
>
3432 stream2_syn(ConstructSpdyPush(NULL
,
3436 "http://www.google.com/foo.dat"));
3437 MockRead reads
[] = {
3438 CreateMockRead(*stream1_reply
, 2),
3439 CreateMockRead(*stream2_syn
, 3),
3440 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame1
),
3441 arraysize(kPushBodyFrame1
), 4),
3442 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame2
),
3443 arraysize(kPushBodyFrame2
) - 1, 5),
3444 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame3
),
3445 arraysize(kPushBodyFrame3
) - 1, 6),
3446 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame4
),
3447 arraysize(kPushBodyFrame4
) - 1, 7),
3448 CreateMockRead(*stream1_body
, 8, SYNCHRONOUS
),
3449 MockRead(ASYNC
, ERR_IO_PENDING
, 9), // Force a pause
3452 HttpResponseInfo response
;
3453 HttpResponseInfo response2
;
3454 std::string
expected_push_result("pushed my darling hello my baby");
3455 OrderedSocketData
data(reads
, arraysize(reads
),
3456 writes
, arraysize(writes
));
3457 RunServerPushTest(&data
,
3460 expected_push_result
);
3462 // Verify the SYN_REPLY.
3463 EXPECT_TRUE(response
.headers
!= NULL
);
3464 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3466 // Verify the pushed stream.
3467 EXPECT_TRUE(response2
.headers
!= NULL
);
3468 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3471 TEST_P(SpdyNetworkTransactionSpdy3Test
,
3472 ServerPushMultipleDataFrameInterrupted
) {
3473 static const unsigned char kPushBodyFrame1
[] = {
3474 0x00, 0x00, 0x00, 0x02, // header, ID
3475 0x01, 0x00, 0x00, 0x1F, // FIN, length
3476 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3478 static const char kPushBodyFrame2
[] = " my darling";
3479 static const char kPushBodyFrame3
[] = " hello";
3480 static const char kPushBodyFrame4
[] = " my baby";
3482 scoped_ptr
<SpdyFrame
>
3483 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3484 scoped_ptr
<SpdyFrame
>
3485 stream1_body(ConstructSpdyBodyFrame(1, true));
3486 MockWrite writes
[] = {
3487 CreateMockWrite(*stream1_syn
, 1),
3490 scoped_ptr
<SpdyFrame
>
3491 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3492 scoped_ptr
<SpdyFrame
>
3493 stream2_syn(ConstructSpdyPush(NULL
,
3497 "http://www.google.com/foo.dat"));
3498 MockRead reads
[] = {
3499 CreateMockRead(*stream1_reply
, 2),
3500 CreateMockRead(*stream2_syn
, 3),
3501 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame1
),
3502 arraysize(kPushBodyFrame1
), 4),
3503 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame2
),
3504 arraysize(kPushBodyFrame2
) - 1, 5),
3505 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
3506 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame3
),
3507 arraysize(kPushBodyFrame3
) - 1, 7),
3508 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame4
),
3509 arraysize(kPushBodyFrame4
) - 1, 8),
3510 CreateMockRead(*stream1_body
.get(), 9, SYNCHRONOUS
),
3511 MockRead(ASYNC
, ERR_IO_PENDING
, 10) // Force a pause.
3514 HttpResponseInfo response
;
3515 HttpResponseInfo response2
;
3516 std::string
expected_push_result("pushed my darling hello my baby");
3517 OrderedSocketData
data(reads
, arraysize(reads
),
3518 writes
, arraysize(writes
));
3519 RunServerPushTest(&data
,
3522 expected_push_result
);
3524 // Verify the SYN_REPLY.
3525 EXPECT_TRUE(response
.headers
!= NULL
);
3526 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3528 // Verify the pushed stream.
3529 EXPECT_TRUE(response2
.headers
!= NULL
);
3530 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
3533 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushInvalidAssociatedStreamID0
) {
3534 scoped_ptr
<SpdyFrame
>
3535 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3536 scoped_ptr
<SpdyFrame
>
3537 stream1_body(ConstructSpdyBodyFrame(1, true));
3538 scoped_ptr
<SpdyFrame
>
3539 stream2_rst(ConstructSpdyRstStream(2, REFUSED_STREAM
));
3540 MockWrite writes
[] = {
3541 CreateMockWrite(*stream1_syn
, 1),
3542 CreateMockWrite(*stream2_rst
, 4),
3545 scoped_ptr
<SpdyFrame
>
3546 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3547 scoped_ptr
<SpdyFrame
>
3548 stream2_syn(ConstructSpdyPush(NULL
,
3552 "http://www.google.com/foo.dat"));
3553 MockRead reads
[] = {
3554 CreateMockRead(*stream1_reply
, 2),
3555 CreateMockRead(*stream2_syn
, 3),
3556 CreateMockRead(*stream1_body
, 4),
3557 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3560 OrderedSocketData
data(reads
, arraysize(reads
),
3561 writes
, arraysize(writes
));
3562 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3563 BoundNetLog(), GetParam(), NULL
);
3565 helper
.RunPreTestSetup();
3566 helper
.AddData(&data
);
3568 HttpNetworkTransaction
* trans
= helper
.trans();
3570 // Start the transaction with basic parameters.
3571 TestCompletionCallback callback
;
3572 int rv
= trans
->Start(
3573 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3574 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3575 rv
= callback
.WaitForResult();
3578 // Verify that we consumed all test data.
3579 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3580 << data
.read_count()
3582 << data
.read_index();
3583 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3584 << data
.write_count()
3586 << data
.write_index();
3588 // Verify the SYN_REPLY.
3589 HttpResponseInfo response
= *trans
->GetResponseInfo();
3590 EXPECT_TRUE(response
.headers
!= NULL
);
3591 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3594 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushInvalidAssociatedStreamID9
) {
3595 scoped_ptr
<SpdyFrame
>
3596 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3597 scoped_ptr
<SpdyFrame
>
3598 stream1_body(ConstructSpdyBodyFrame(1, true));
3599 scoped_ptr
<SpdyFrame
>
3600 stream2_rst(ConstructSpdyRstStream(2, INVALID_STREAM
));
3601 MockWrite writes
[] = {
3602 CreateMockWrite(*stream1_syn
, 1),
3603 CreateMockWrite(*stream2_rst
, 4),
3606 scoped_ptr
<SpdyFrame
>
3607 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3608 scoped_ptr
<SpdyFrame
>
3609 stream2_syn(ConstructSpdyPush(NULL
,
3613 "http://www.google.com/foo.dat"));
3614 MockRead reads
[] = {
3615 CreateMockRead(*stream1_reply
, 2),
3616 CreateMockRead(*stream2_syn
, 3),
3617 CreateMockRead(*stream1_body
, 4),
3618 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
3621 OrderedSocketData
data(reads
, arraysize(reads
),
3622 writes
, arraysize(writes
));
3623 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3624 BoundNetLog(), GetParam(), NULL
);
3626 helper
.RunPreTestSetup();
3627 helper
.AddData(&data
);
3629 HttpNetworkTransaction
* trans
= helper
.trans();
3631 // Start the transaction with basic parameters.
3632 TestCompletionCallback callback
;
3633 int rv
= trans
->Start(
3634 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3635 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3636 rv
= callback
.WaitForResult();
3639 // Verify that we consumed all test data.
3640 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3641 << data
.read_count()
3643 << data
.read_index();
3644 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3645 << data
.write_count()
3647 << data
.write_index();
3649 // Verify the SYN_REPLY.
3650 HttpResponseInfo response
= *trans
->GetResponseInfo();
3651 EXPECT_TRUE(response
.headers
!= NULL
);
3652 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3655 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushNoURL
) {
3656 scoped_ptr
<SpdyFrame
>
3657 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3658 scoped_ptr
<SpdyFrame
>
3659 stream1_body(ConstructSpdyBodyFrame(1, true));
3660 scoped_ptr
<SpdyFrame
>
3661 stream2_rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR
));
3662 MockWrite writes
[] = {
3663 CreateMockWrite(*stream1_syn
, 1),
3664 CreateMockWrite(*stream2_rst
, 4),
3667 scoped_ptr
<SpdyFrame
>
3668 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
3669 scoped_ptr
<SpdyFrame
>
3670 stream2_syn(ConstructSpdyPush(NULL
, 0, 2, 1));
3671 MockRead reads
[] = {
3672 CreateMockRead(*stream1_reply
, 2),
3673 CreateMockRead(*stream2_syn
, 3),
3674 CreateMockRead(*stream1_body
, 4),
3675 MockRead(ASYNC
, ERR_IO_PENDING
, 5) // Force a pause
3678 OrderedSocketData
data(reads
, arraysize(reads
),
3679 writes
, arraysize(writes
));
3680 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3681 BoundNetLog(), GetParam(), NULL
);
3683 helper
.RunPreTestSetup();
3684 helper
.AddData(&data
);
3686 HttpNetworkTransaction
* trans
= helper
.trans();
3688 // Start the transaction with basic parameters.
3689 TestCompletionCallback callback
;
3690 int rv
= trans
->Start(
3691 &CreateGetRequest(), callback
.callback(), BoundNetLog());
3692 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3693 rv
= callback
.WaitForResult();
3695 // Verify that we consumed all test data.
3696 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
3697 << data
.read_count()
3699 << data
.read_index();
3700 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
3701 << data
.write_count()
3703 << data
.write_index();
3705 // Verify the SYN_REPLY.
3706 HttpResponseInfo response
= *trans
->GetResponseInfo();
3707 EXPECT_TRUE(response
.headers
!= NULL
);
3708 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
3711 // Verify that various SynReply headers parse correctly through the
3713 TEST_P(SpdyNetworkTransactionSpdy3Test
, SynReplyHeaders
) {
3714 struct SynReplyHeadersTests
{
3716 const char* extra_headers
[5];
3717 const char* expected_headers
;
3719 // This uses a multi-valued cookie header.
3722 "cookie", "val2", // will get appended separated by NULL
3726 "version: HTTP/1.1\n"
3731 // This is the minimalist set of headers.
3735 "version: HTTP/1.1\n"
3738 // Headers with a comma separated list.
3740 { "cookie", "val1,val2",
3744 "version: HTTP/1.1\n"
3745 "cookie: val1,val2\n"
3750 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3751 scoped_ptr
<SpdyFrame
> req(
3752 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
3753 MockWrite writes
[] = { CreateMockWrite(*req
) };
3755 scoped_ptr
<SpdyFrame
> resp(
3756 ConstructSpdyGetSynReply(test_cases
[i
].extra_headers
,
3757 test_cases
[i
].num_headers
,
3759 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3760 MockRead reads
[] = {
3761 CreateMockRead(*resp
),
3762 CreateMockRead(*body
),
3763 MockRead(ASYNC
, 0, 0) // EOF
3766 DelayedSocketData
data(1, reads
, arraysize(reads
),
3767 writes
, arraysize(writes
));
3768 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
3769 BoundNetLog(), GetParam(), NULL
);
3770 helper
.RunToCompletion(&data
);
3771 TransactionHelperResult out
= helper
.output();
3773 EXPECT_EQ(OK
, out
.rv
);
3774 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
3775 EXPECT_EQ("hello!", out
.response_data
);
3777 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3778 EXPECT_TRUE(headers
.get() != NULL
);
3780 std::string name
, value
, lines
;
3781 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3784 lines
.append(value
);
3787 EXPECT_EQ(std::string(test_cases
[i
].expected_headers
), lines
);
3791 // Verify that various SynReply headers parse vary fields correctly
3792 // through the HTTP layer, and the response matches the request.
3793 TEST_P(SpdyNetworkTransactionSpdy3Test
, SynReplyHeadersVary
) {
3794 static const SpdyHeaderInfo syn_reply_info
= {
3795 SYN_REPLY
, // Syn Reply
3797 0, // Associated Stream ID
3798 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
3799 0, // Credential Slot
3800 CONTROL_FLAG_NONE
, // Control Flags
3801 false, // Compressed
3805 DATA_FLAG_NONE
// Data Flags
3807 // Modify the following data to change/add test cases:
3808 struct SynReplyTests
{
3809 const SpdyHeaderInfo
* syn_reply
;
3812 const char* extra_headers
[2][16];
3814 // Test the case of a multi-valued cookie. When the value is delimited
3815 // with NUL characters, it needs to be unfolded into multiple headers.
3820 { { "cookie", "val1,val2",
3824 ":version", "HTTP/1.1",
3826 "url", "/index.php",
3830 }, { // Multiple vary fields.
3834 { { "friend", "barney",
3835 "enemy", "snaggletooth",
3839 ":version", "HTTP/1.1",
3842 "url", "/index.php",
3846 }, { // Test a '*' vary field.
3850 { { "cookie", "val1,val2",
3854 ":version", "HTTP/1.1",
3856 "url", "/index.php",
3860 }, { // Multiple comma-separated vary fields.
3864 { { "friend", "barney",
3865 "enemy", "snaggletooth",
3869 ":version", "HTTP/1.1",
3870 "vary", "friend,enemy",
3871 "url", "/index.php",
3878 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
3879 // Construct the request.
3880 scoped_ptr
<SpdyFrame
> frame_req(
3881 ConstructSpdyGet(test_cases
[i
].extra_headers
[0],
3882 test_cases
[i
].num_headers
[0],
3885 MockWrite writes
[] = {
3886 CreateMockWrite(*frame_req
),
3889 // Construct the reply.
3890 scoped_ptr
<SpdyFrame
> frame_reply(
3891 ConstructSpdyPacket(*test_cases
[i
].syn_reply
,
3892 test_cases
[i
].extra_headers
[1],
3893 test_cases
[i
].num_headers
[1],
3897 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
3898 MockRead reads
[] = {
3899 CreateMockRead(*frame_reply
),
3900 CreateMockRead(*body
),
3901 MockRead(ASYNC
, 0, 0) // EOF
3904 // Attach the headers to the request.
3905 int header_count
= test_cases
[i
].num_headers
[0];
3907 HttpRequestInfo request
= CreateGetRequest();
3908 for (int ct
= 0; ct
< header_count
; ct
++) {
3909 const char* header_key
= test_cases
[i
].extra_headers
[0][ct
* 2];
3910 const char* header_value
= test_cases
[i
].extra_headers
[0][ct
* 2 + 1];
3911 request
.extra_headers
.SetHeader(header_key
, header_value
);
3914 DelayedSocketData
data(1, reads
, arraysize(reads
),
3915 writes
, arraysize(writes
));
3916 NormalSpdyTransactionHelper
helper(request
,
3917 BoundNetLog(), GetParam(), NULL
);
3918 helper
.RunToCompletion(&data
);
3919 TransactionHelperResult out
= helper
.output();
3921 EXPECT_EQ(OK
, out
.rv
) << i
;
3922 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
) << i
;
3923 EXPECT_EQ("hello!", out
.response_data
) << i
;
3925 // Test the response information.
3926 EXPECT_TRUE(out
.response_info
.response_time
>
3927 out
.response_info
.request_time
) << i
;
3928 base::TimeDelta test_delay
= out
.response_info
.response_time
-
3929 out
.response_info
.request_time
;
3930 base::TimeDelta min_expected_delay
;
3931 min_expected_delay
.FromMilliseconds(10);
3932 EXPECT_GT(test_delay
.InMillisecondsF(),
3933 min_expected_delay
.InMillisecondsF()) << i
;
3934 EXPECT_EQ(out
.response_info
.vary_data
.is_valid(),
3935 test_cases
[i
].vary_matches
) << i
;
3937 // Check the headers.
3938 scoped_refptr
<HttpResponseHeaders
> headers
= out
.response_info
.headers
;
3939 ASSERT_TRUE(headers
.get() != NULL
) << i
;
3941 std::string name
, value
, lines
;
3942 while (headers
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
3945 lines
.append(value
);
3949 // Construct the expected header reply string.
3950 char reply_buffer
[256] = "";
3951 ConstructSpdyReplyString(test_cases
[i
].extra_headers
[1],
3952 test_cases
[i
].num_headers
[1],
3956 EXPECT_EQ(std::string(reply_buffer
), lines
) << i
;
3960 // Verify that we don't crash on invalid SynReply responses.
3961 TEST_P(SpdyNetworkTransactionSpdy3Test
, InvalidSynReply
) {
3962 const SpdyHeaderInfo kSynStartHeader
= {
3963 SYN_REPLY
, // Kind = SynReply
3965 0, // Associated stream ID
3966 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
3967 0, // Credential Slot
3968 CONTROL_FLAG_NONE
, // Control Flags
3969 false, // Compressed
3973 DATA_FLAG_NONE
// Data Flags
3976 struct InvalidSynReplyTests
{
3978 const char* headers
[10];
3980 // SYN_REPLY missing status header
3984 "url", "/index.php",
3985 "version", "HTTP/1.1",
3989 // SYN_REPLY missing version header
3992 "url", "/index.php",
3996 // SYN_REPLY with no headers
4000 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
4001 scoped_ptr
<SpdyFrame
> req(
4002 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4003 MockWrite writes
[] = {
4004 CreateMockWrite(*req
),
4007 scoped_ptr
<SpdyFrame
> resp(
4008 ConstructSpdyPacket(kSynStartHeader
,
4010 test_cases
[i
].headers
,
4011 test_cases
[i
].num_headers
));
4012 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4013 MockRead reads
[] = {
4014 CreateMockRead(*resp
),
4015 CreateMockRead(*body
),
4016 MockRead(ASYNC
, 0, 0) // EOF
4019 DelayedSocketData
data(1, reads
, arraysize(reads
),
4020 writes
, arraysize(writes
));
4021 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4022 BoundNetLog(), GetParam(), NULL
);
4023 helper
.RunToCompletion(&data
);
4024 TransactionHelperResult out
= helper
.output();
4025 EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS
, out
.rv
);
4029 // Verify that we don't crash on some corrupt frames.
4030 TEST_P(SpdyNetworkTransactionSpdy3Test
, CorruptFrameSessionError
) {
4031 // This is the length field that's too short.
4032 scoped_ptr
<SpdyFrame
> syn_reply_wrong_length(
4033 ConstructSpdyGetSynReply(NULL
, 0, 1));
4034 syn_reply_wrong_length
->set_length(syn_reply_wrong_length
->length() - 4);
4036 struct SynReplyTests
{
4037 const SpdyFrame
* syn_reply
;
4039 { syn_reply_wrong_length
.get(), },
4042 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
4043 scoped_ptr
<SpdyFrame
> req(
4044 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4045 MockWrite writes
[] = {
4046 CreateMockWrite(*req
),
4047 MockWrite(ASYNC
, 0, 0) // EOF
4050 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4051 MockRead reads
[] = {
4052 CreateMockRead(*test_cases
[i
].syn_reply
),
4053 CreateMockRead(*body
),
4054 MockRead(ASYNC
, 0, 0) // EOF
4057 DelayedSocketData
data(1, reads
, arraysize(reads
),
4058 writes
, arraysize(writes
));
4059 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4060 BoundNetLog(), GetParam(), NULL
);
4061 helper
.RunToCompletion(&data
);
4062 TransactionHelperResult out
= helper
.output();
4063 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
4067 // Test that we shutdown correctly on write errors.
4068 TEST_P(SpdyNetworkTransactionSpdy3Test
, WriteError
) {
4069 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4070 MockWrite writes
[] = {
4071 // We'll write 10 bytes successfully
4072 MockWrite(ASYNC
, req
->data(), 10),
4073 // Followed by ERROR!
4074 MockWrite(ASYNC
, ERR_FAILED
),
4077 DelayedSocketData
data(2, NULL
, 0,
4078 writes
, arraysize(writes
));
4079 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4080 BoundNetLog(), GetParam(), NULL
);
4081 helper
.RunToCompletion(&data
);
4082 TransactionHelperResult out
= helper
.output();
4083 EXPECT_EQ(ERR_FAILED
, out
.rv
);
4087 // Test that partial writes work.
4088 TEST_P(SpdyNetworkTransactionSpdy3Test
, PartialWrite
) {
4089 // Chop the SYN_STREAM frame into 5 chunks.
4090 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4091 const int kChunks
= 5;
4092 scoped_array
<MockWrite
> writes(ChopWriteFrame(*req
.get(), kChunks
));
4094 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4095 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4096 MockRead reads
[] = {
4097 CreateMockRead(*resp
),
4098 CreateMockRead(*body
),
4099 MockRead(ASYNC
, 0, 0) // EOF
4102 DelayedSocketData
data(kChunks
, reads
, arraysize(reads
),
4103 writes
.get(), kChunks
);
4104 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4105 BoundNetLog(), GetParam(), NULL
);
4106 helper
.RunToCompletion(&data
);
4107 TransactionHelperResult out
= helper
.output();
4108 EXPECT_EQ(OK
, out
.rv
);
4109 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4110 EXPECT_EQ("hello!", out
.response_data
);
4113 // In this test, we enable compression, but get a uncompressed SynReply from
4114 // the server. Verify that teardown is all clean.
4115 TEST_P(SpdyNetworkTransactionSpdy3Test
, DecompressFailureOnSynReply
) {
4116 scoped_ptr
<SpdyFrame
> compressed(
4117 ConstructSpdyGet(NULL
, 0, true, 1, LOWEST
));
4118 scoped_ptr
<SpdyFrame
> rst(
4119 ConstructSpdyRstStream(1, PROTOCOL_ERROR
));
4120 MockWrite writes
[] = {
4121 CreateMockWrite(*compressed
),
4124 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4125 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4126 MockRead reads
[] = {
4127 CreateMockRead(*resp
),
4130 DelayedSocketData
data(1, reads
, arraysize(reads
),
4131 writes
, arraysize(writes
));
4132 SpdySessionDependencies
* session_deps
= new SpdySessionDependencies();
4133 session_deps
->enable_compression
= true;
4134 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4135 BoundNetLog(), GetParam(), session_deps
);
4136 helper
.RunToCompletion(&data
);
4137 TransactionHelperResult out
= helper
.output();
4138 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
4142 // Test that the NetLog contains good data for a simple GET request.
4143 TEST_P(SpdyNetworkTransactionSpdy3Test
, NetLog
) {
4144 static const char* const kExtraHeaders
[] = {
4145 "user-agent", "Chrome",
4147 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(kExtraHeaders
, 1, false, 1,
4149 MockWrite writes
[] = { CreateMockWrite(*req
) };
4151 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4152 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4153 MockRead reads
[] = {
4154 CreateMockRead(*resp
),
4155 CreateMockRead(*body
),
4156 MockRead(ASYNC
, 0, 0) // EOF
4159 CapturingBoundNetLog log
;
4161 DelayedSocketData
data(1, reads
, arraysize(reads
),
4162 writes
, arraysize(writes
));
4163 NormalSpdyTransactionHelper
helper(CreateGetRequestWithUserAgent(),
4164 log
.bound(), GetParam(), NULL
);
4165 helper
.RunToCompletion(&data
);
4166 TransactionHelperResult out
= helper
.output();
4167 EXPECT_EQ(OK
, out
.rv
);
4168 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4169 EXPECT_EQ("hello!", out
.response_data
);
4171 // Check that the NetLog was filled reasonably.
4172 // This test is intentionally non-specific about the exact ordering of the
4173 // log; instead we just check to make sure that certain events exist, and that
4174 // they are in the right order.
4175 net::CapturingNetLog::CapturedEntryList entries
;
4176 log
.GetEntries(&entries
);
4178 EXPECT_LT(0u, entries
.size());
4180 pos
= net::ExpectLogContainsSomewhere(entries
, 0,
4181 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
4182 net::NetLog::PHASE_BEGIN
);
4183 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
4184 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST
,
4185 net::NetLog::PHASE_END
);
4186 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
4187 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
4188 net::NetLog::PHASE_BEGIN
);
4189 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
4190 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS
,
4191 net::NetLog::PHASE_END
);
4192 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
4193 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
4194 net::NetLog::PHASE_BEGIN
);
4195 pos
= net::ExpectLogContainsSomewhere(entries
, pos
+ 1,
4196 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY
,
4197 net::NetLog::PHASE_END
);
4199 // Check that we logged all the headers correctly
4200 pos
= net::ExpectLogContainsSomewhere(
4202 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM
,
4203 net::NetLog::PHASE_NONE
);
4205 ListValue
* header_list
;
4206 ASSERT_TRUE(entries
[pos
].params
.get());
4207 ASSERT_TRUE(entries
[pos
].params
->GetList("headers", &header_list
));
4209 std::vector
<std::string
> expected
;
4210 expected
.push_back(":host: www.google.com");
4211 expected
.push_back(":path: /");
4212 expected
.push_back(":scheme: http");
4213 expected
.push_back(":version: HTTP/1.1");
4214 expected
.push_back(":method: GET");
4215 expected
.push_back("user-agent: Chrome");
4216 EXPECT_EQ(expected
.size(), header_list
->GetSize());
4217 for (std::vector
<std::string
>::const_iterator it
= expected
.begin();
4218 it
!= expected
.end();
4220 base::StringValue
header(*it
);
4221 EXPECT_NE(header_list
->end(), header_list
->Find(header
)) <<
4222 "Header not found: " << *it
;
4226 // Since we buffer the IO from the stream to the renderer, this test verifies
4227 // that when we read out the maximum amount of data (e.g. we received 50 bytes
4228 // on the network, but issued a Read for only 5 of those bytes) that the data
4229 // flow still works correctly.
4230 TEST_P(SpdyNetworkTransactionSpdy3Test
, BufferFull
) {
4231 BufferedSpdyFramer
framer(3, false);
4233 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4234 MockWrite writes
[] = { CreateMockWrite(*req
) };
4236 // 2 data frames in a single read.
4237 scoped_ptr
<SpdyFrame
> data_frame_1(
4238 framer
.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE
));
4239 scoped_ptr
<SpdyFrame
> data_frame_2(
4240 framer
.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE
));
4241 const SpdyFrame
* data_frames
[2] = {
4245 char combined_data_frames
[100];
4246 int combined_data_frames_len
=
4247 CombineFrames(data_frames
, arraysize(data_frames
),
4248 combined_data_frames
, arraysize(combined_data_frames
));
4249 scoped_ptr
<SpdyFrame
> last_frame(
4250 framer
.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN
));
4252 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4253 MockRead reads
[] = {
4254 CreateMockRead(*resp
),
4255 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
4256 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4257 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
4258 CreateMockRead(*last_frame
),
4259 MockRead(ASYNC
, 0, 0) // EOF
4262 DelayedSocketData
data(1, reads
, arraysize(reads
),
4263 writes
, arraysize(writes
));
4265 TestCompletionCallback callback
;
4267 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4268 BoundNetLog(), GetParam(), NULL
);
4269 helper
.RunPreTestSetup();
4270 helper
.AddData(&data
);
4271 HttpNetworkTransaction
* trans
= helper
.trans();
4272 int rv
= trans
->Start(
4273 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4276 TransactionHelperResult out
= helper
.output();
4277 out
.rv
= callback
.WaitForResult();
4278 EXPECT_EQ(out
.rv
, OK
);
4280 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4281 EXPECT_TRUE(response
->headers
!= NULL
);
4282 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4283 out
.status_line
= response
->headers
->GetStatusLine();
4284 out
.response_info
= *response
; // Make a copy so we can verify.
4287 TestCompletionCallback read_callback
;
4289 std::string content
;
4291 // Read small chunks at a time.
4292 const int kSmallReadSize
= 3;
4293 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4294 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4295 if (rv
== net::ERR_IO_PENDING
) {
4296 data
.CompleteRead();
4297 rv
= read_callback
.WaitForResult();
4300 content
.append(buf
->data(), rv
);
4301 } else if (rv
< 0) {
4306 out
.response_data
.swap(content
);
4308 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4309 // MockClientSocketFactory) are still alive.
4310 MessageLoop::current()->RunUntilIdle();
4312 // Verify that we consumed all test data.
4313 helper
.VerifyDataConsumed();
4315 EXPECT_EQ(OK
, out
.rv
);
4316 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4317 EXPECT_EQ("goodbye world", out
.response_data
);
4320 // Verify that basic buffering works; when multiple data frames arrive
4321 // at the same time, ensure that we don't notify a read completion for
4322 // each data frame individually.
4323 TEST_P(SpdyNetworkTransactionSpdy3Test
, Buffering
) {
4324 BufferedSpdyFramer
framer(3, false);
4326 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4327 MockWrite writes
[] = { CreateMockWrite(*req
) };
4329 // 4 data frames in a single read.
4330 scoped_ptr
<SpdyFrame
> data_frame(
4331 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4332 scoped_ptr
<SpdyFrame
> data_frame_fin(
4333 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4334 const SpdyFrame
* data_frames
[4] = {
4338 data_frame_fin
.get()
4340 char combined_data_frames
[100];
4341 int combined_data_frames_len
=
4342 CombineFrames(data_frames
, arraysize(data_frames
),
4343 combined_data_frames
, arraysize(combined_data_frames
));
4345 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4346 MockRead reads
[] = {
4347 CreateMockRead(*resp
),
4348 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a pause
4349 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4350 MockRead(ASYNC
, 0, 0) // EOF
4353 DelayedSocketData
data(1, reads
, arraysize(reads
),
4354 writes
, arraysize(writes
));
4356 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4357 BoundNetLog(), GetParam(), NULL
);
4358 helper
.RunPreTestSetup();
4359 helper
.AddData(&data
);
4360 HttpNetworkTransaction
* trans
= helper
.trans();
4362 TestCompletionCallback callback
;
4363 int rv
= trans
->Start(
4364 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4365 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4367 TransactionHelperResult out
= helper
.output();
4368 out
.rv
= callback
.WaitForResult();
4369 EXPECT_EQ(out
.rv
, OK
);
4371 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4372 EXPECT_TRUE(response
->headers
!= NULL
);
4373 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4374 out
.status_line
= response
->headers
->GetStatusLine();
4375 out
.response_info
= *response
; // Make a copy so we can verify.
4378 TestCompletionCallback read_callback
;
4380 std::string content
;
4381 int reads_completed
= 0;
4383 // Read small chunks at a time.
4384 const int kSmallReadSize
= 14;
4385 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4386 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4387 if (rv
== net::ERR_IO_PENDING
) {
4388 data
.CompleteRead();
4389 rv
= read_callback
.WaitForResult();
4392 EXPECT_EQ(kSmallReadSize
, rv
);
4393 content
.append(buf
->data(), rv
);
4394 } else if (rv
< 0) {
4395 FAIL() << "Unexpected read error: " << rv
;
4400 EXPECT_EQ(3, reads_completed
); // Reads are: 14 bytes, 14 bytes, 0 bytes.
4402 out
.response_data
.swap(content
);
4404 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4405 // MockClientSocketFactory) are still alive.
4406 MessageLoop::current()->RunUntilIdle();
4408 // Verify that we consumed all test data.
4409 helper
.VerifyDataConsumed();
4411 EXPECT_EQ(OK
, out
.rv
);
4412 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4413 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4416 // Verify the case where we buffer data but read it after it has been buffered.
4417 TEST_P(SpdyNetworkTransactionSpdy3Test
, BufferedAll
) {
4418 BufferedSpdyFramer
framer(3, false);
4420 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4421 MockWrite writes
[] = { CreateMockWrite(*req
) };
4423 // 5 data frames in a single read.
4424 scoped_ptr
<SpdyFrame
> syn_reply(
4425 ConstructSpdyGetSynReply(NULL
, 0, 1));
4426 syn_reply
->set_flags(CONTROL_FLAG_NONE
); // turn off FIN bit
4427 scoped_ptr
<SpdyFrame
> data_frame(
4428 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4429 scoped_ptr
<SpdyFrame
> data_frame_fin(
4430 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN
));
4431 const SpdyFrame
* frames
[5] = {
4436 data_frame_fin
.get()
4438 char combined_frames
[200];
4439 int combined_frames_len
=
4440 CombineFrames(frames
, arraysize(frames
),
4441 combined_frames
, arraysize(combined_frames
));
4443 MockRead reads
[] = {
4444 MockRead(ASYNC
, combined_frames
, combined_frames_len
),
4445 MockRead(ASYNC
, 0, 0) // EOF
4448 DelayedSocketData
data(1, reads
, arraysize(reads
),
4449 writes
, arraysize(writes
));
4451 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4452 BoundNetLog(), GetParam(), NULL
);
4453 helper
.RunPreTestSetup();
4454 helper
.AddData(&data
);
4455 HttpNetworkTransaction
* trans
= helper
.trans();
4457 TestCompletionCallback callback
;
4458 int rv
= trans
->Start(
4459 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4460 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4462 TransactionHelperResult out
= helper
.output();
4463 out
.rv
= callback
.WaitForResult();
4464 EXPECT_EQ(out
.rv
, OK
);
4466 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4467 EXPECT_TRUE(response
->headers
!= NULL
);
4468 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4469 out
.status_line
= response
->headers
->GetStatusLine();
4470 out
.response_info
= *response
; // Make a copy so we can verify.
4473 TestCompletionCallback read_callback
;
4475 std::string content
;
4476 int reads_completed
= 0;
4478 // Read small chunks at a time.
4479 const int kSmallReadSize
= 14;
4480 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4481 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4483 EXPECT_EQ(kSmallReadSize
, rv
);
4484 content
.append(buf
->data(), rv
);
4485 } else if (rv
< 0) {
4486 FAIL() << "Unexpected read error: " << rv
;
4491 EXPECT_EQ(3, reads_completed
);
4493 out
.response_data
.swap(content
);
4495 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4496 // MockClientSocketFactory) are still alive.
4497 MessageLoop::current()->RunUntilIdle();
4499 // Verify that we consumed all test data.
4500 helper
.VerifyDataConsumed();
4502 EXPECT_EQ(OK
, out
.rv
);
4503 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4504 EXPECT_EQ("messagemessagemessagemessage", out
.response_data
);
4507 // Verify the case where we buffer data and close the connection.
4508 TEST_P(SpdyNetworkTransactionSpdy3Test
, BufferedClosed
) {
4509 BufferedSpdyFramer
framer(3, false);
4511 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4512 MockWrite writes
[] = { CreateMockWrite(*req
) };
4514 // All data frames in a single read.
4515 // NOTE: We don't FIN the stream.
4516 scoped_ptr
<SpdyFrame
> data_frame(
4517 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4518 const SpdyFrame
* data_frames
[4] = {
4524 char combined_data_frames
[100];
4525 int combined_data_frames_len
=
4526 CombineFrames(data_frames
, arraysize(data_frames
),
4527 combined_data_frames
, arraysize(combined_data_frames
));
4528 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4529 MockRead reads
[] = {
4530 CreateMockRead(*resp
),
4531 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4532 MockRead(ASYNC
, combined_data_frames
, combined_data_frames_len
),
4533 MockRead(ASYNC
, 0, 0) // EOF
4536 DelayedSocketData
data(1, reads
, arraysize(reads
),
4537 writes
, arraysize(writes
));
4539 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4540 BoundNetLog(), GetParam(), NULL
);
4541 helper
.RunPreTestSetup();
4542 helper
.AddData(&data
);
4543 HttpNetworkTransaction
* trans
= helper
.trans();
4545 TestCompletionCallback callback
;
4547 int rv
= trans
->Start(
4548 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4549 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4551 TransactionHelperResult out
= helper
.output();
4552 out
.rv
= callback
.WaitForResult();
4553 EXPECT_EQ(out
.rv
, OK
);
4555 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4556 EXPECT_TRUE(response
->headers
!= NULL
);
4557 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4558 out
.status_line
= response
->headers
->GetStatusLine();
4559 out
.response_info
= *response
; // Make a copy so we can verify.
4562 TestCompletionCallback read_callback
;
4564 std::string content
;
4565 int reads_completed
= 0;
4567 // Read small chunks at a time.
4568 const int kSmallReadSize
= 14;
4569 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kSmallReadSize
));
4570 rv
= trans
->Read(buf
, kSmallReadSize
, read_callback
.callback());
4571 if (rv
== net::ERR_IO_PENDING
) {
4572 data
.CompleteRead();
4573 rv
= read_callback
.WaitForResult();
4576 content
.append(buf
->data(), rv
);
4577 } else if (rv
< 0) {
4578 // This test intentionally closes the connection, and will get an error.
4579 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
4585 EXPECT_EQ(0, reads_completed
);
4587 out
.response_data
.swap(content
);
4589 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4590 // MockClientSocketFactory) are still alive.
4591 MessageLoop::current()->RunUntilIdle();
4593 // Verify that we consumed all test data.
4594 helper
.VerifyDataConsumed();
4597 // Verify the case where we buffer data and cancel the transaction.
4598 TEST_P(SpdyNetworkTransactionSpdy3Test
, BufferedCancelled
) {
4599 BufferedSpdyFramer
framer(3, false);
4601 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4602 MockWrite writes
[] = { CreateMockWrite(*req
) };
4604 // NOTE: We don't FIN the stream.
4605 scoped_ptr
<SpdyFrame
> data_frame(
4606 framer
.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE
));
4608 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4609 MockRead reads
[] = {
4610 CreateMockRead(*resp
),
4611 MockRead(ASYNC
, ERR_IO_PENDING
), // Force a wait
4612 CreateMockRead(*data_frame
),
4613 MockRead(ASYNC
, 0, 0) // EOF
4616 DelayedSocketData
data(1, reads
, arraysize(reads
),
4617 writes
, arraysize(writes
));
4619 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4620 BoundNetLog(), GetParam(), NULL
);
4621 helper
.RunPreTestSetup();
4622 helper
.AddData(&data
);
4623 HttpNetworkTransaction
* trans
= helper
.trans();
4624 TestCompletionCallback callback
;
4626 int rv
= trans
->Start(
4627 &CreateGetRequest(), callback
.callback(), BoundNetLog());
4628 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4630 TransactionHelperResult out
= helper
.output();
4631 out
.rv
= callback
.WaitForResult();
4632 EXPECT_EQ(out
.rv
, OK
);
4634 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4635 EXPECT_TRUE(response
->headers
!= NULL
);
4636 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4637 out
.status_line
= response
->headers
->GetStatusLine();
4638 out
.response_info
= *response
; // Make a copy so we can verify.
4641 TestCompletionCallback read_callback
;
4644 const int kReadSize
= 256;
4645 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(kReadSize
));
4646 rv
= trans
->Read(buf
, kReadSize
, read_callback
.callback());
4647 if (rv
== net::ERR_IO_PENDING
) {
4648 // Complete the read now, which causes buffering to start.
4649 data
.CompleteRead();
4650 // Destroy the transaction, causing the stream to get cancelled
4651 // and orphaning the buffered IO task.
4652 helper
.ResetTrans();
4655 // We shouldn't get here in this test.
4656 FAIL() << "Unexpected read: " << rv
;
4659 // Flush the MessageLoop; this will cause the buffered IO task
4660 // to run for the final time.
4661 MessageLoop::current()->RunUntilIdle();
4663 // Verify that we consumed all test data.
4664 helper
.VerifyDataConsumed();
4667 // Test that if the server requests persistence of settings, that we save
4668 // the settings in the HttpServerProperties.
4669 TEST_P(SpdyNetworkTransactionSpdy3Test
, SettingsSaved
) {
4670 static const SpdyHeaderInfo kSynReplyInfo
= {
4671 SYN_REPLY
, // Syn Reply
4673 0, // Associated Stream ID
4674 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
4675 0, // Credential Slot
4676 CONTROL_FLAG_NONE
, // Control Flags
4677 false, // Compressed
4681 DATA_FLAG_NONE
// Data Flags
4683 static const char* const kExtraHeaders
[] = {
4685 ":version", "HTTP/1.1"
4688 BoundNetLog net_log
;
4689 NormalSpdyTransactionHelper
helper(CreateGetRequest(), net_log
,
4691 helper
.RunPreTestSetup();
4693 // Verify that no settings exist initially.
4694 HostPortPair
host_port_pair("www.google.com", helper
.port());
4695 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4696 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4697 host_port_pair
).empty());
4699 // Construct the request.
4700 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4701 MockWrite writes
[] = { CreateMockWrite(*req
) };
4703 // Construct the reply.
4704 scoped_ptr
<SpdyFrame
> reply(
4705 ConstructSpdyPacket(kSynReplyInfo
,
4707 arraysize(kExtraHeaders
) / 2,
4711 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4712 unsigned int kSampleValue1
= 0x0a0a0a0a;
4713 const SpdySettingsIds kSampleId2
= SETTINGS_DOWNLOAD_BANDWIDTH
;
4714 unsigned int kSampleValue2
= 0x0b0b0b0b;
4715 const SpdySettingsIds kSampleId3
= SETTINGS_ROUND_TRIP_TIME
;
4716 unsigned int kSampleValue3
= 0x0c0c0c0c;
4717 scoped_ptr
<SpdyFrame
> settings_frame
;
4719 // Construct the SETTINGS frame.
4720 SettingsMap settings
;
4721 // First add a persisted setting.
4722 settings
[kSampleId1
] =
4723 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue1
);
4724 // Next add a non-persisted setting.
4725 settings
[kSampleId2
] =
4726 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kSampleValue2
);
4727 // Next add another persisted setting.
4728 settings
[kSampleId3
] =
4729 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST
, kSampleValue3
);
4730 settings_frame
.reset(ConstructSpdySettings(settings
));
4733 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4734 MockRead reads
[] = {
4735 CreateMockRead(*reply
),
4736 CreateMockRead(*body
),
4737 CreateMockRead(*settings_frame
),
4738 MockRead(ASYNC
, 0, 0) // EOF
4741 DelayedSocketData
data(1, reads
, arraysize(reads
),
4742 writes
, arraysize(writes
));
4743 helper
.AddData(&data
);
4744 helper
.RunDefaultTest();
4745 helper
.VerifyDataConsumed();
4746 TransactionHelperResult out
= helper
.output();
4747 EXPECT_EQ(OK
, out
.rv
);
4748 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4749 EXPECT_EQ("hello!", out
.response_data
);
4752 // Verify we had two persisted settings.
4753 const SettingsMap
& settings_map
=
4754 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4756 ASSERT_EQ(2u, settings_map
.size());
4758 // Verify the first persisted setting.
4759 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4760 EXPECT_TRUE(it1
!= settings_map
.end());
4761 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4762 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4763 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4765 // Verify the second persisted setting.
4766 SettingsMap::const_iterator it3
= settings_map
.find(kSampleId3
);
4767 EXPECT_TRUE(it3
!= settings_map
.end());
4768 SettingsFlagsAndValue flags_and_value3
= it3
->second
;
4769 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value3
.first
);
4770 EXPECT_EQ(kSampleValue3
, flags_and_value3
.second
);
4774 // Test that when there are settings saved that they are sent back to the
4775 // server upon session establishment.
4776 TEST_P(SpdyNetworkTransactionSpdy3Test
, SettingsPlayback
) {
4777 static const SpdyHeaderInfo kSynReplyInfo
= {
4778 SYN_REPLY
, // Syn Reply
4780 0, // Associated Stream ID
4781 ConvertRequestPriorityToSpdyPriority(LOWEST
, 3), // Priority
4782 0, // Credential Slot
4783 CONTROL_FLAG_NONE
, // Control Flags
4784 false, // Compressed
4788 DATA_FLAG_NONE
// Data Flags
4790 static const char* kExtraHeaders
[] = {
4792 ":version", "HTTP/1.1"
4795 BoundNetLog net_log
;
4796 NormalSpdyTransactionHelper
helper(CreateGetRequest(), net_log
,
4798 helper
.RunPreTestSetup();
4800 // Verify that no settings exist initially.
4801 HostPortPair
host_port_pair("www.google.com", helper
.port());
4802 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
4803 EXPECT_TRUE(spdy_session_pool
->http_server_properties()->GetSpdySettings(
4804 host_port_pair
).empty());
4806 const SpdySettingsIds kSampleId1
= SETTINGS_UPLOAD_BANDWIDTH
;
4807 unsigned int kSampleValue1
= 0x0a0a0a0a;
4808 const SpdySettingsIds kSampleId2
= SETTINGS_ROUND_TRIP_TIME
;
4809 unsigned int kSampleValue2
= 0x0c0c0c0c;
4811 // First add a persisted setting.
4812 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4815 SETTINGS_FLAG_PLEASE_PERSIST
,
4818 // Next add another persisted setting.
4819 spdy_session_pool
->http_server_properties()->SetSpdySetting(
4822 SETTINGS_FLAG_PLEASE_PERSIST
,
4825 EXPECT_EQ(2u, spdy_session_pool
->http_server_properties()->GetSpdySettings(
4826 host_port_pair
).size());
4828 // Construct the SETTINGS frame.
4829 const SettingsMap
& settings
=
4830 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4832 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
4834 // Construct the request.
4835 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4837 MockWrite writes
[] = {
4838 CreateMockWrite(*settings_frame
),
4839 CreateMockWrite(*req
),
4842 // Construct the reply.
4843 scoped_ptr
<SpdyFrame
> reply(
4844 ConstructSpdyPacket(kSynReplyInfo
,
4846 arraysize(kExtraHeaders
) / 2,
4850 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4851 MockRead reads
[] = {
4852 CreateMockRead(*reply
),
4853 CreateMockRead(*body
),
4854 MockRead(ASYNC
, 0, 0) // EOF
4857 DelayedSocketData
data(2, reads
, arraysize(reads
),
4858 writes
, arraysize(writes
));
4859 helper
.AddData(&data
);
4860 helper
.RunDefaultTest();
4861 helper
.VerifyDataConsumed();
4862 TransactionHelperResult out
= helper
.output();
4863 EXPECT_EQ(OK
, out
.rv
);
4864 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
4865 EXPECT_EQ("hello!", out
.response_data
);
4868 // Verify we had two persisted settings.
4869 const SettingsMap
& settings_map
=
4870 spdy_session_pool
->http_server_properties()->GetSpdySettings(
4872 ASSERT_EQ(2u, settings_map
.size());
4874 // Verify the first persisted setting.
4875 SettingsMap::const_iterator it1
= settings_map
.find(kSampleId1
);
4876 EXPECT_TRUE(it1
!= settings_map
.end());
4877 SettingsFlagsAndValue flags_and_value1
= it1
->second
;
4878 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value1
.first
);
4879 EXPECT_EQ(kSampleValue1
, flags_and_value1
.second
);
4881 // Verify the second persisted setting.
4882 SettingsMap::const_iterator it2
= settings_map
.find(kSampleId2
);
4883 EXPECT_TRUE(it2
!= settings_map
.end());
4884 SettingsFlagsAndValue flags_and_value2
= it2
->second
;
4885 EXPECT_EQ(SETTINGS_FLAG_PERSISTED
, flags_and_value2
.first
);
4886 EXPECT_EQ(kSampleValue2
, flags_and_value2
.second
);
4890 TEST_P(SpdyNetworkTransactionSpdy3Test
, GoAwayWithActiveStream
) {
4891 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4892 MockWrite writes
[] = { CreateMockWrite(*req
) };
4894 scoped_ptr
<SpdyFrame
> go_away(ConstructSpdyGoAway());
4895 MockRead reads
[] = {
4896 CreateMockRead(*go_away
),
4897 MockRead(ASYNC
, 0, 0), // EOF
4900 DelayedSocketData
data(1, reads
, arraysize(reads
),
4901 writes
, arraysize(writes
));
4902 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4903 BoundNetLog(), GetParam(), NULL
);
4904 helper
.AddData(&data
);
4905 helper
.RunToCompletion(&data
);
4906 TransactionHelperResult out
= helper
.output();
4907 EXPECT_EQ(ERR_ABORTED
, out
.rv
);
4910 TEST_P(SpdyNetworkTransactionSpdy3Test
, CloseWithActiveStream
) {
4911 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4912 MockWrite writes
[] = { CreateMockWrite(*req
) };
4914 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4915 MockRead reads
[] = {
4916 CreateMockRead(*resp
),
4917 MockRead(SYNCHRONOUS
, 0, 0) // EOF
4920 DelayedSocketData
data(1, reads
, arraysize(reads
),
4921 writes
, arraysize(writes
));
4923 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4924 log
, GetParam(), NULL
);
4925 helper
.RunPreTestSetup();
4926 helper
.AddData(&data
);
4927 HttpNetworkTransaction
* trans
= helper
.trans();
4929 TestCompletionCallback callback
;
4930 TransactionHelperResult out
;
4931 out
.rv
= trans
->Start(&CreateGetRequest(), callback
.callback(), log
);
4933 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
4934 out
.rv
= callback
.WaitForResult();
4935 EXPECT_EQ(out
.rv
, OK
);
4937 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4938 EXPECT_TRUE(response
->headers
!= NULL
);
4939 EXPECT_TRUE(response
->was_fetched_via_spdy
);
4940 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
4941 EXPECT_EQ(ERR_CONNECTION_CLOSED
, out
.rv
);
4943 // Verify that we consumed all test data.
4944 helper
.VerifyDataConsumed();
4947 // Test to make sure we can correctly connect through a proxy.
4948 TEST_P(SpdyNetworkTransactionSpdy3Test
, ProxyConnect
) {
4949 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
4950 BoundNetLog(), GetParam(), NULL
);
4951 helper
.session_deps().reset(new SpdySessionDependencies(
4952 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4953 helper
.SetSession(make_scoped_refptr(
4954 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
4955 helper
.RunPreTestSetup();
4956 HttpNetworkTransaction
* trans
= helper
.trans();
4958 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4959 "Host: www.google.com\r\n"
4960 "Proxy-Connection: keep-alive\r\n\r\n"};
4961 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4962 "Host: www.google.com\r\n"
4963 "Proxy-Connection: keep-alive\r\n\r\n"};
4964 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4965 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
4966 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
4967 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
4969 MockWrite writes_SPDYNPN
[] = {
4970 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
4971 CreateMockWrite(*req
, 2),
4973 MockRead reads_SPDYNPN
[] = {
4974 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4975 CreateMockRead(*resp
, 3),
4976 CreateMockRead(*body
.get(), 4),
4977 MockRead(ASYNC
, 0, 0, 5),
4980 MockWrite writes_SPDYSSL
[] = {
4981 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
4982 CreateMockWrite(*req
, 2),
4984 MockRead reads_SPDYSSL
[] = {
4985 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
4986 CreateMockRead(*resp
, 3),
4987 CreateMockRead(*body
.get(), 4),
4988 MockRead(ASYNC
, 0, 0, 5),
4991 MockWrite writes_SPDYNOSSL
[] = {
4992 CreateMockWrite(*req
, 0),
4995 MockRead reads_SPDYNOSSL
[] = {
4996 CreateMockRead(*resp
, 1),
4997 CreateMockRead(*body
.get(), 2),
4998 MockRead(ASYNC
, 0, 0, 3),
5001 scoped_ptr
<OrderedSocketData
> data
;
5002 switch(GetParam()) {
5004 data
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
5005 arraysize(reads_SPDYNOSSL
),
5007 arraysize(writes_SPDYNOSSL
)));
5010 data
.reset(new OrderedSocketData(reads_SPDYSSL
,
5011 arraysize(reads_SPDYSSL
),
5013 arraysize(writes_SPDYSSL
)));
5016 data
.reset(new OrderedSocketData(reads_SPDYNPN
,
5017 arraysize(reads_SPDYNPN
),
5019 arraysize(writes_SPDYNPN
)));
5025 helper
.AddData(data
.get());
5026 TestCompletionCallback callback
;
5028 int rv
= trans
->Start(
5029 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5030 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5032 rv
= callback
.WaitForResult();
5035 // Verify the SYN_REPLY.
5036 HttpResponseInfo response
= *trans
->GetResponseInfo();
5037 EXPECT_TRUE(response
.headers
!= NULL
);
5038 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5040 std::string response_data
;
5041 ASSERT_EQ(OK
, ReadTransaction(trans
, &response_data
));
5042 EXPECT_EQ("hello!", response_data
);
5043 helper
.VerifyDataConsumed();
5046 // Test to make sure we can correctly connect through a proxy to www.google.com,
5047 // if there already exists a direct spdy connection to www.google.com. See
5048 // http://crbug.com/49874
5049 TEST_P(SpdyNetworkTransactionSpdy3Test
, DirectConnectProxyReconnect
) {
5050 // When setting up the first transaction, we store the SpdySessionPool so that
5051 // we can use the same pool in the second transaction.
5052 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5053 BoundNetLog(), GetParam(), NULL
);
5055 // Use a proxy service which returns a proxy fallback list from DIRECT to
5056 // myproxy:70. For this test there will be no fallback, so it is equivalent
5057 // to simply DIRECT. The reason for appending the second proxy is to verify
5058 // that the session pool key used does is just "DIRECT".
5059 helper
.session_deps().reset(new SpdySessionDependencies(
5060 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
5061 helper
.SetSession(make_scoped_refptr(
5062 SpdySessionDependencies::SpdyCreateSession(helper
.session_deps().get())));
5064 SpdySessionPool
* spdy_session_pool
= helper
.session()->spdy_session_pool();
5065 helper
.RunPreTestSetup();
5067 // Construct and send a simple GET request.
5068 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5069 MockWrite writes
[] = {
5070 CreateMockWrite(*req
, 1),
5073 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
5074 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
5075 MockRead reads
[] = {
5076 CreateMockRead(*resp
, 2),
5077 CreateMockRead(*body
, 3),
5078 MockRead(ASYNC
, ERR_IO_PENDING
, 4), // Force a pause
5079 MockRead(ASYNC
, 0, 5) // EOF
5081 OrderedSocketData
data(reads
, arraysize(reads
),
5082 writes
, arraysize(writes
));
5083 helper
.AddData(&data
);
5084 HttpNetworkTransaction
* trans
= helper
.trans();
5086 TestCompletionCallback callback
;
5087 TransactionHelperResult out
;
5088 out
.rv
= trans
->Start(
5089 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5091 EXPECT_EQ(out
.rv
, ERR_IO_PENDING
);
5092 out
.rv
= callback
.WaitForResult();
5093 EXPECT_EQ(out
.rv
, OK
);
5095 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5096 EXPECT_TRUE(response
->headers
!= NULL
);
5097 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5098 out
.rv
= ReadTransaction(trans
, &out
.response_data
);
5099 EXPECT_EQ(OK
, out
.rv
);
5100 out
.status_line
= response
->headers
->GetStatusLine();
5101 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5102 EXPECT_EQ("hello!", out
.response_data
);
5104 // Check that the SpdySession is still in the SpdySessionPool.
5105 HostPortPair
host_port_pair("www.google.com", helper
.port());
5106 HostPortProxyPair
session_pool_key_direct(
5107 host_port_pair
, ProxyServer::Direct());
5108 EXPECT_TRUE(spdy_session_pool
->HasSession(session_pool_key_direct
));
5109 HostPortProxyPair
session_pool_key_proxy(
5111 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP
));
5112 EXPECT_FALSE(spdy_session_pool
->HasSession(session_pool_key_proxy
));
5114 // Set up data for the proxy connection.
5115 const char kConnect443
[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
5116 "Host: www.google.com\r\n"
5117 "Proxy-Connection: keep-alive\r\n\r\n"};
5118 const char kConnect80
[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
5119 "Host: www.google.com\r\n"
5120 "Proxy-Connection: keep-alive\r\n\r\n"};
5121 const char kHTTP200
[] = {"HTTP/1.1 200 OK\r\n\r\n"};
5122 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(
5123 "http://www.google.com/foo.dat", false, 1, LOWEST
));
5124 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
5125 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
5127 MockWrite writes_SPDYNPN
[] = {
5128 MockWrite(SYNCHRONOUS
, kConnect443
, arraysize(kConnect443
) - 1, 0),
5129 CreateMockWrite(*req2
, 2),
5131 MockRead reads_SPDYNPN
[] = {
5132 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
5133 CreateMockRead(*resp2
, 3),
5134 CreateMockRead(*body2
, 4),
5135 MockRead(ASYNC
, 0, 5) // EOF
5138 MockWrite writes_SPDYNOSSL
[] = {
5139 CreateMockWrite(*req2
, 0),
5141 MockRead reads_SPDYNOSSL
[] = {
5142 CreateMockRead(*resp2
, 1),
5143 CreateMockRead(*body2
, 2),
5144 MockRead(ASYNC
, 0, 3) // EOF
5147 MockWrite writes_SPDYSSL
[] = {
5148 MockWrite(SYNCHRONOUS
, kConnect80
, arraysize(kConnect80
) - 1, 0),
5149 CreateMockWrite(*req2
, 2),
5151 MockRead reads_SPDYSSL
[] = {
5152 MockRead(SYNCHRONOUS
, kHTTP200
, arraysize(kHTTP200
) - 1, 1),
5153 CreateMockRead(*resp2
, 3),
5154 CreateMockRead(*body2
, 4),
5155 MockRead(ASYNC
, 0, 0, 5),
5158 scoped_ptr
<OrderedSocketData
> data_proxy
;
5159 switch(GetParam()) {
5161 data_proxy
.reset(new OrderedSocketData(reads_SPDYNPN
,
5162 arraysize(reads_SPDYNPN
),
5164 arraysize(writes_SPDYNPN
)));
5167 data_proxy
.reset(new OrderedSocketData(reads_SPDYNOSSL
,
5168 arraysize(reads_SPDYNOSSL
),
5170 arraysize(writes_SPDYNOSSL
)));
5173 data_proxy
.reset(new OrderedSocketData(reads_SPDYSSL
,
5174 arraysize(reads_SPDYSSL
),
5176 arraysize(writes_SPDYSSL
)));
5182 // Create another request to www.google.com, but this time through a proxy.
5183 HttpRequestInfo request_proxy
;
5184 request_proxy
.method
= "GET";
5185 request_proxy
.url
= GURL("http://www.google.com/foo.dat");
5186 request_proxy
.load_flags
= 0;
5187 scoped_ptr
<SpdySessionDependencies
> ssd_proxy(new SpdySessionDependencies());
5188 // Ensure that this transaction uses the same SpdySessionPool.
5189 scoped_refptr
<HttpNetworkSession
> session_proxy(
5190 SpdySessionDependencies::SpdyCreateSession(ssd_proxy
.get()));
5191 NormalSpdyTransactionHelper
helper_proxy(request_proxy
,
5192 BoundNetLog(), GetParam(), NULL
);
5193 HttpNetworkSessionPeer
session_peer(session_proxy
);
5194 scoped_ptr
<net::ProxyService
> proxy_service(
5195 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5196 session_peer
.SetProxyService(proxy_service
.get());
5197 helper_proxy
.session_deps().swap(ssd_proxy
);
5198 helper_proxy
.SetSession(session_proxy
);
5199 helper_proxy
.RunPreTestSetup();
5200 helper_proxy
.AddData(data_proxy
.get());
5202 HttpNetworkTransaction
* trans_proxy
= helper_proxy
.trans();
5203 TestCompletionCallback callback_proxy
;
5204 int rv
= trans_proxy
->Start(
5205 &request_proxy
, callback_proxy
.callback(), BoundNetLog());
5206 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5207 rv
= callback_proxy
.WaitForResult();
5210 HttpResponseInfo response_proxy
= *trans_proxy
->GetResponseInfo();
5211 EXPECT_TRUE(response_proxy
.headers
!= NULL
);
5212 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy
.headers
->GetStatusLine());
5214 std::string response_data
;
5215 ASSERT_EQ(OK
, ReadTransaction(trans_proxy
, &response_data
));
5216 EXPECT_EQ("hello!", response_data
);
5218 data
.CompleteRead();
5219 helper_proxy
.VerifyDataConsumed();
5222 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5223 // on a new connection, if the connection was previously known to be good.
5224 // This can happen when a server reboots without saying goodbye, or when
5225 // we're behind a NAT that masked the RST.
5226 TEST_P(SpdyNetworkTransactionSpdy3Test
, VerifyRetryOnConnectionReset
) {
5227 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
5228 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
5229 MockRead reads
[] = {
5230 CreateMockRead(*resp
),
5231 CreateMockRead(*body
),
5232 MockRead(ASYNC
, ERR_IO_PENDING
),
5233 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
5236 MockRead reads2
[] = {
5237 CreateMockRead(*resp
),
5238 CreateMockRead(*body
),
5239 MockRead(ASYNC
, 0, 0) // EOF
5242 // This test has a couple of variants.
5244 // Induce the RST while waiting for our transaction to send.
5245 VARIANT_RST_DURING_SEND_COMPLETION
,
5246 // Induce the RST while waiting for our transaction to read.
5247 // In this case, the send completed - everything copied into the SNDBUF.
5248 VARIANT_RST_DURING_READ_COMPLETION
5251 for (int variant
= VARIANT_RST_DURING_SEND_COMPLETION
;
5252 variant
<= VARIANT_RST_DURING_READ_COMPLETION
;
5254 DelayedSocketData
data1(1, reads
, arraysize(reads
), NULL
, 0);
5256 DelayedSocketData
data2(1, reads2
, arraysize(reads2
), NULL
, 0);
5258 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5259 BoundNetLog(), GetParam(), NULL
);
5260 helper
.AddData(&data1
);
5261 helper
.AddData(&data2
);
5262 helper
.RunPreTestSetup();
5264 for (int i
= 0; i
< 2; ++i
) {
5265 scoped_ptr
<HttpNetworkTransaction
> trans(
5266 new HttpNetworkTransaction(helper
.session()));
5268 TestCompletionCallback callback
;
5269 int rv
= trans
->Start(
5270 &helper
.request(), callback
.callback(), BoundNetLog());
5271 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5272 // On the second transaction, we trigger the RST.
5274 if (variant
== VARIANT_RST_DURING_READ_COMPLETION
) {
5275 // Writes to the socket complete asynchronously on SPDY by running
5276 // through the message loop. Complete the write here.
5277 MessageLoop::current()->RunUntilIdle();
5280 // Now schedule the ERR_CONNECTION_RESET.
5281 EXPECT_EQ(3u, data1
.read_index());
5282 data1
.CompleteRead();
5283 EXPECT_EQ(4u, data1
.read_index());
5285 rv
= callback
.WaitForResult();
5288 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5289 ASSERT_TRUE(response
!= NULL
);
5290 EXPECT_TRUE(response
->headers
!= NULL
);
5291 EXPECT_TRUE(response
->was_fetched_via_spdy
);
5292 std::string response_data
;
5293 rv
= ReadTransaction(trans
.get(), &response_data
);
5295 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5296 EXPECT_EQ("hello!", response_data
);
5299 helper
.VerifyDataConsumed();
5303 // Test that turning SPDY on and off works properly.
5304 TEST_P(SpdyNetworkTransactionSpdy3Test
, SpdyOnOffToggle
) {
5305 net::HttpStreamFactory::set_spdy_enabled(true);
5306 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5307 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
5309 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 1));
5310 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(1, true));
5311 MockRead spdy_reads
[] = {
5312 CreateMockRead(*resp
),
5313 CreateMockRead(*body
),
5314 MockRead(ASYNC
, 0, 0) // EOF
5317 DelayedSocketData
data(1, spdy_reads
, arraysize(spdy_reads
),
5318 spdy_writes
, arraysize(spdy_writes
));
5319 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5320 BoundNetLog(), GetParam(), NULL
);
5321 helper
.RunToCompletion(&data
);
5322 TransactionHelperResult out
= helper
.output();
5323 EXPECT_EQ(OK
, out
.rv
);
5324 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5325 EXPECT_EQ("hello!", out
.response_data
);
5327 net::HttpStreamFactory::set_spdy_enabled(false);
5328 MockRead http_reads
[] = {
5329 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5330 MockRead("hello from http"),
5331 MockRead(SYNCHRONOUS
, OK
),
5333 DelayedSocketData
data2(1, http_reads
, arraysize(http_reads
), NULL
, 0);
5334 NormalSpdyTransactionHelper
helper2(CreateGetRequest(),
5335 BoundNetLog(), GetParam(), NULL
);
5336 helper2
.SetSpdyDisabled();
5337 helper2
.RunToCompletion(&data2
);
5338 TransactionHelperResult out2
= helper2
.output();
5339 EXPECT_EQ(OK
, out2
.rv
);
5340 EXPECT_EQ("HTTP/1.1 200 OK", out2
.status_line
);
5341 EXPECT_EQ("hello from http", out2
.response_data
);
5343 net::HttpStreamFactory::set_spdy_enabled(true);
5346 // Tests that Basic authentication works over SPDY
5347 TEST_P(SpdyNetworkTransactionSpdy3Test
, SpdyBasicAuth
) {
5348 net::HttpStreamFactory::set_spdy_enabled(true);
5350 // The first request will be a bare GET, the second request will be a
5351 // GET with an Authorization header.
5352 scoped_ptr
<SpdyFrame
> req_get(
5353 ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5354 const char* const kExtraAuthorizationHeaders
[] = {
5356 "Basic Zm9vOmJhcg==",
5358 scoped_ptr
<SpdyFrame
> req_get_authorization(
5360 kExtraAuthorizationHeaders
,
5361 arraysize(kExtraAuthorizationHeaders
) / 2,
5363 MockWrite spdy_writes
[] = {
5364 CreateMockWrite(*req_get
, 1),
5365 CreateMockWrite(*req_get_authorization
, 4),
5368 // The first response is a 401 authentication challenge, and the second
5369 // response will be a 200 response since the second request includes a valid
5370 // Authorization header.
5371 const char* const kExtraAuthenticationHeaders
[] = {
5373 "Basic realm=\"MyRealm\""
5375 scoped_ptr
<SpdyFrame
> resp_authentication(
5376 ConstructSpdySynReplyError(
5377 "401 Authentication Required",
5378 kExtraAuthenticationHeaders
,
5379 arraysize(kExtraAuthenticationHeaders
) / 2,
5381 scoped_ptr
<SpdyFrame
> body_authentication(
5382 ConstructSpdyBodyFrame(1, true));
5383 scoped_ptr
<SpdyFrame
> resp_data(ConstructSpdyGetSynReply(NULL
, 0, 3));
5384 scoped_ptr
<SpdyFrame
> body_data(ConstructSpdyBodyFrame(3, true));
5385 MockRead spdy_reads
[] = {
5386 CreateMockRead(*resp_authentication
, 2),
5387 CreateMockRead(*body_authentication
, 3),
5388 CreateMockRead(*resp_data
, 5),
5389 CreateMockRead(*body_data
, 6),
5390 MockRead(ASYNC
, 0, 7),
5393 OrderedSocketData
data(spdy_reads
, arraysize(spdy_reads
),
5394 spdy_writes
, arraysize(spdy_writes
));
5395 HttpRequestInfo
request(CreateGetRequest());
5396 BoundNetLog net_log
;
5397 NormalSpdyTransactionHelper
helper(request
, net_log
, GetParam(), NULL
);
5399 helper
.RunPreTestSetup();
5400 helper
.AddData(&data
);
5401 HttpNetworkTransaction
* trans
= helper
.trans();
5402 TestCompletionCallback callback
;
5403 const int rv_start
= trans
->Start(&request
, callback
.callback(), net_log
);
5404 EXPECT_EQ(ERR_IO_PENDING
, rv_start
);
5405 const int rv_start_complete
= callback
.WaitForResult();
5406 EXPECT_EQ(OK
, rv_start_complete
);
5408 // Make sure the response has an auth challenge.
5409 const HttpResponseInfo
* const response_start
= trans
->GetResponseInfo();
5410 ASSERT_TRUE(response_start
!= NULL
);
5411 ASSERT_TRUE(response_start
->headers
!= NULL
);
5412 EXPECT_EQ(401, response_start
->headers
->response_code());
5413 EXPECT_TRUE(response_start
->was_fetched_via_spdy
);
5414 AuthChallengeInfo
* auth_challenge
= response_start
->auth_challenge
.get();
5415 ASSERT_TRUE(auth_challenge
!= NULL
);
5416 EXPECT_FALSE(auth_challenge
->is_proxy
);
5417 EXPECT_EQ("basic", auth_challenge
->scheme
);
5418 EXPECT_EQ("MyRealm", auth_challenge
->realm
);
5420 // Restart with a username/password.
5421 AuthCredentials
credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
5422 TestCompletionCallback callback_restart
;
5423 const int rv_restart
= trans
->RestartWithAuth(
5424 credentials
, callback_restart
.callback());
5425 EXPECT_EQ(ERR_IO_PENDING
, rv_restart
);
5426 const int rv_restart_complete
= callback_restart
.WaitForResult();
5427 EXPECT_EQ(OK
, rv_restart_complete
);
5428 // TODO(cbentzel): This is actually the same response object as before, but
5429 // data has changed.
5430 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
5431 ASSERT_TRUE(response_restart
!= NULL
);
5432 ASSERT_TRUE(response_restart
->headers
!= NULL
);
5433 EXPECT_EQ(200, response_restart
->headers
->response_code());
5434 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
5437 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushWithHeaders
) {
5438 static const unsigned char kPushBodyFrame
[] = {
5439 0x00, 0x00, 0x00, 0x02, // header, ID
5440 0x01, 0x00, 0x00, 0x06, // FIN, length
5441 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5443 scoped_ptr
<SpdyFrame
>
5444 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5445 scoped_ptr
<SpdyFrame
>
5446 stream1_body(ConstructSpdyBodyFrame(1, true));
5447 MockWrite writes
[] = {
5448 CreateMockWrite(*stream1_syn
, 1),
5451 static const char* const kInitialHeaders
[] = {
5453 ":host", "www.google.com",
5454 ":path", "/foo.dat",
5456 static const char* const kLateHeaders
[] = {
5464 scoped_ptr
<SpdyFrame
>
5465 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5466 arraysize(kInitialHeaders
) / 2,
5475 scoped_ptr
<SpdyFrame
>
5476 stream2_headers(ConstructSpdyControlFrame(kLateHeaders
,
5477 arraysize(kLateHeaders
) / 2,
5487 scoped_ptr
<SpdyFrame
>
5488 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5489 MockRead reads
[] = {
5490 CreateMockRead(*stream1_reply
, 2),
5491 CreateMockRead(*stream2_syn
, 3),
5492 CreateMockRead(*stream2_headers
, 4),
5493 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
5494 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5495 arraysize(kPushBodyFrame
), 6),
5496 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
5499 HttpResponseInfo response
;
5500 HttpResponseInfo response2
;
5501 std::string
expected_push_result("pushed");
5502 OrderedSocketData
data(reads
, arraysize(reads
),
5503 writes
, arraysize(writes
));
5504 RunServerPushTest(&data
,
5507 expected_push_result
);
5509 // Verify the SYN_REPLY.
5510 EXPECT_TRUE(response
.headers
!= NULL
);
5511 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5513 // Verify the pushed stream.
5514 EXPECT_TRUE(response2
.headers
!= NULL
);
5515 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5518 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushClaimBeforeHeaders
) {
5519 // We push a stream and attempt to claim it before the headers come down.
5520 static const unsigned char kPushBodyFrame
[] = {
5521 0x00, 0x00, 0x00, 0x02, // header, ID
5522 0x01, 0x00, 0x00, 0x06, // FIN, length
5523 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5525 scoped_ptr
<SpdyFrame
>
5526 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5527 scoped_ptr
<SpdyFrame
>
5528 stream1_body(ConstructSpdyBodyFrame(1, true));
5529 MockWrite writes
[] = {
5530 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5533 static const char* const kInitialHeaders
[] = {
5535 ":host", "www.google.com",
5538 static const char* const kLateHeaders
[] = {
5546 scoped_ptr
<SpdyFrame
>
5547 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5548 arraysize(kInitialHeaders
) / 2,
5557 scoped_ptr
<SpdyFrame
>
5558 stream2_headers(ConstructSpdyControlFrame(kLateHeaders
,
5559 arraysize(kLateHeaders
) / 2,
5569 scoped_ptr
<SpdyFrame
>
5570 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5571 MockRead reads
[] = {
5572 CreateMockRead(*stream1_reply
, 1),
5573 CreateMockRead(*stream2_syn
, 2),
5574 CreateMockRead(*stream1_body
, 3),
5575 CreateMockRead(*stream2_headers
, 4),
5576 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5577 arraysize(kPushBodyFrame
), 5),
5578 MockRead(ASYNC
, 0, 6), // EOF
5581 HttpResponseInfo response
;
5582 HttpResponseInfo response2
;
5583 std::string
expected_push_result("pushed");
5584 DeterministicSocketData
data(reads
, arraysize(reads
),
5585 writes
, arraysize(writes
));
5587 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5588 BoundNetLog(), GetParam(), NULL
);
5589 helper
.SetDeterministic();
5590 helper
.AddDeterministicData(&data
);
5591 helper
.RunPreTestSetup();
5593 HttpNetworkTransaction
* trans
= helper
.trans();
5595 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5596 // and the body of the primary stream, but before we've received the HEADERS
5597 // for the pushed stream.
5600 // Start the transaction.
5601 TestCompletionCallback callback
;
5602 int rv
= trans
->Start(
5603 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5604 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5606 rv
= callback
.WaitForResult();
5609 // Request the pushed path. At this point, we've received the push, but the
5610 // headers are not yet complete.
5611 scoped_ptr
<HttpNetworkTransaction
> trans2(
5612 new HttpNetworkTransaction(helper
.session()));
5614 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5615 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5617 MessageLoop::current()->RunUntilIdle();
5619 // Read the server push body.
5620 std::string result2
;
5621 ReadResult(trans2
.get(), &data
, &result2
);
5622 // Read the response body.
5624 ReadResult(trans
, &data
, &result
);
5626 // Verify that the received push data is same as the expected push data.
5627 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5628 << "Received data: "
5630 << "||||| Expected data: "
5631 << expected_push_result
;
5633 // Verify the SYN_REPLY.
5634 // Copy the response info, because trans goes away.
5635 response
= *trans
->GetResponseInfo();
5636 response2
= *trans2
->GetResponseInfo();
5638 VerifyStreamsClosed(helper
);
5640 // Verify the SYN_REPLY.
5641 EXPECT_TRUE(response
.headers
!= NULL
);
5642 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5644 // Verify the pushed stream.
5645 EXPECT_TRUE(response2
.headers
!= NULL
);
5646 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5648 // Read the final EOF (which will close the session)
5651 // Verify that we consumed all test data.
5652 EXPECT_TRUE(data
.at_read_eof());
5653 EXPECT_TRUE(data
.at_write_eof());
5656 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushWithTwoHeaderFrames
) {
5657 // We push a stream and attempt to claim it before the headers come down.
5658 static const unsigned char kPushBodyFrame
[] = {
5659 0x00, 0x00, 0x00, 0x02, // header, ID
5660 0x01, 0x00, 0x00, 0x06, // FIN, length
5661 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5663 scoped_ptr
<SpdyFrame
>
5664 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5665 scoped_ptr
<SpdyFrame
>
5666 stream1_body(ConstructSpdyBodyFrame(1, true));
5667 MockWrite writes
[] = {
5668 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5671 static const char* const kInitialHeaders
[] = {
5673 ":host", "www.google.com",
5676 static const char* const kMiddleHeaders
[] = {
5680 static const char* const kLateHeaders
[] = {
5686 scoped_ptr
<SpdyFrame
>
5687 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5688 arraysize(kInitialHeaders
) / 2,
5697 scoped_ptr
<SpdyFrame
>
5698 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders
,
5699 arraysize(kMiddleHeaders
) / 2,
5708 scoped_ptr
<SpdyFrame
>
5709 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders
,
5710 arraysize(kLateHeaders
) / 2,
5720 scoped_ptr
<SpdyFrame
>
5721 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5722 MockRead reads
[] = {
5723 CreateMockRead(*stream1_reply
, 1),
5724 CreateMockRead(*stream2_syn
, 2),
5725 CreateMockRead(*stream1_body
, 3),
5726 CreateMockRead(*stream2_headers1
, 4),
5727 CreateMockRead(*stream2_headers2
, 5),
5728 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5729 arraysize(kPushBodyFrame
), 6),
5730 MockRead(ASYNC
, 0, 7), // EOF
5733 HttpResponseInfo response
;
5734 HttpResponseInfo response2
;
5735 std::string
expected_push_result("pushed");
5736 DeterministicSocketData
data(reads
, arraysize(reads
),
5737 writes
, arraysize(writes
));
5739 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5740 BoundNetLog(), GetParam(), NULL
);
5741 helper
.SetDeterministic();
5742 helper
.AddDeterministicData(&data
);
5743 helper
.RunPreTestSetup();
5745 HttpNetworkTransaction
* trans
= helper
.trans();
5747 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5748 // the first HEADERS frame, and the body of the primary stream, but before
5749 // we've received the final HEADERS for the pushed stream.
5752 // Start the transaction.
5753 TestCompletionCallback callback
;
5754 int rv
= trans
->Start(
5755 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5758 rv
= callback
.WaitForResult();
5761 // Request the pushed path. At this point, we've received the push, but the
5762 // headers are not yet complete.
5763 scoped_ptr
<HttpNetworkTransaction
> trans2(
5764 new HttpNetworkTransaction(helper
.session()));
5766 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5767 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5769 MessageLoop::current()->RunUntilIdle();
5771 // Read the server push body.
5772 std::string result2
;
5773 ReadResult(trans2
.get(), &data
, &result2
);
5774 // Read the response body.
5776 ReadResult(trans
, &data
, &result
);
5778 // Verify that the received push data is same as the expected push data.
5779 EXPECT_EQ(result2
.compare(expected_push_result
), 0)
5780 << "Received data: "
5782 << "||||| Expected data: "
5783 << expected_push_result
;
5785 // Verify the SYN_REPLY.
5786 // Copy the response info, because trans goes away.
5787 response
= *trans
->GetResponseInfo();
5788 response2
= *trans2
->GetResponseInfo();
5790 VerifyStreamsClosed(helper
);
5792 // Verify the SYN_REPLY.
5793 EXPECT_TRUE(response
.headers
!= NULL
);
5794 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5796 // Verify the pushed stream.
5797 EXPECT_TRUE(response2
.headers
!= NULL
);
5798 EXPECT_EQ("HTTP/1.1 200 OK", response2
.headers
->GetStatusLine());
5800 // Verify we got all the headers
5801 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5803 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5804 "host", "www.google.com"));
5805 EXPECT_TRUE(response2
.headers
->HasHeaderValue(
5806 "path", "/foo.dat"));
5807 EXPECT_TRUE(response2
.headers
->HasHeaderValue("hello", "bye"));
5808 EXPECT_TRUE(response2
.headers
->HasHeaderValue("status", "200"));
5809 EXPECT_TRUE(response2
.headers
->HasHeaderValue("version", "HTTP/1.1"));
5811 // Read the final EOF (which will close the session)
5814 // Verify that we consumed all test data.
5815 EXPECT_TRUE(data
.at_read_eof());
5816 EXPECT_TRUE(data
.at_write_eof());
5819 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushWithNoStatusHeaderFrames
) {
5820 // We push a stream and attempt to claim it before the headers come down.
5821 static const unsigned char kPushBodyFrame
[] = {
5822 0x00, 0x00, 0x00, 0x02, // header, ID
5823 0x01, 0x00, 0x00, 0x06, // FIN, length
5824 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5826 scoped_ptr
<SpdyFrame
>
5827 stream1_syn(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5828 scoped_ptr
<SpdyFrame
>
5829 stream1_body(ConstructSpdyBodyFrame(1, true));
5830 MockWrite writes
[] = {
5831 CreateMockWrite(*stream1_syn
, 0, SYNCHRONOUS
),
5834 static const char* const kInitialHeaders
[] = {
5836 ":host", "www.google.com",
5839 static const char* const kMiddleHeaders
[] = {
5843 scoped_ptr
<SpdyFrame
>
5844 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders
,
5845 arraysize(kInitialHeaders
) / 2,
5854 scoped_ptr
<SpdyFrame
>
5855 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders
,
5856 arraysize(kMiddleHeaders
) / 2,
5866 scoped_ptr
<SpdyFrame
>
5867 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
5868 MockRead reads
[] = {
5869 CreateMockRead(*stream1_reply
, 1),
5870 CreateMockRead(*stream2_syn
, 2),
5871 CreateMockRead(*stream1_body
, 3),
5872 CreateMockRead(*stream2_headers1
, 4),
5873 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
5874 arraysize(kPushBodyFrame
), 5),
5875 MockRead(ASYNC
, 0, 6), // EOF
5878 DeterministicSocketData
data(reads
, arraysize(reads
),
5879 writes
, arraysize(writes
));
5881 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5882 BoundNetLog(), GetParam(), NULL
);
5883 helper
.SetDeterministic();
5884 helper
.AddDeterministicData(&data
);
5885 helper
.RunPreTestSetup();
5887 HttpNetworkTransaction
* trans
= helper
.trans();
5889 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5890 // the first HEADERS frame, and the body of the primary stream, but before
5891 // we've received the final HEADERS for the pushed stream.
5894 // Start the transaction.
5895 TestCompletionCallback callback
;
5896 int rv
= trans
->Start(
5897 &CreateGetRequest(), callback
.callback(), BoundNetLog());
5898 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5900 rv
= callback
.WaitForResult();
5903 // Request the pushed path. At this point, we've received the push, but the
5904 // headers are not yet complete.
5905 scoped_ptr
<HttpNetworkTransaction
> trans2(
5906 new HttpNetworkTransaction(helper
.session()));
5908 &CreateGetPushRequest(), callback
.callback(), BoundNetLog());
5909 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5911 MessageLoop::current()->RunUntilIdle();
5913 // Read the server push body.
5914 std::string result2
;
5915 ReadResult(trans2
.get(), &data
, &result2
);
5916 // Read the response body.
5918 ReadResult(trans
, &data
, &result
);
5919 EXPECT_EQ("hello!", result
);
5921 // Verify that we haven't received any push data.
5922 EXPECT_EQ("", result2
);
5924 // Verify the SYN_REPLY.
5925 // Copy the response info, because trans goes away.
5926 HttpResponseInfo response
= *trans
->GetResponseInfo();
5927 ASSERT_TRUE(trans2
->GetResponseInfo() == NULL
);
5929 VerifyStreamsClosed(helper
);
5931 // Verify the SYN_REPLY.
5932 EXPECT_TRUE(response
.headers
!= NULL
);
5933 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
5935 // Read the final EOF (which will close the session).
5938 // Verify that we consumed all test data.
5939 EXPECT_TRUE(data
.at_read_eof());
5940 EXPECT_TRUE(data
.at_write_eof());
5943 TEST_P(SpdyNetworkTransactionSpdy3Test
, SynReplyWithHeaders
) {
5944 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
5945 MockWrite writes
[] = { CreateMockWrite(*req
) };
5947 static const char* const kInitialHeaders
[] = {
5953 static const char* const kLateHeaders
[] = {
5957 scoped_ptr
<SpdyFrame
>
5958 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
5959 arraysize(kInitialHeaders
) / 2,
5968 scoped_ptr
<SpdyFrame
>
5969 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
5970 arraysize(kLateHeaders
) / 2,
5979 scoped_ptr
<SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, true));
5980 MockRead reads
[] = {
5981 CreateMockRead(*stream1_reply
),
5982 CreateMockRead(*stream1_headers
),
5983 CreateMockRead(*stream1_body
),
5984 MockRead(ASYNC
, 0, 0) // EOF
5987 DelayedSocketData
data(1, reads
, arraysize(reads
),
5988 writes
, arraysize(writes
));
5989 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
5990 BoundNetLog(), GetParam(), NULL
);
5991 helper
.RunToCompletion(&data
);
5992 TransactionHelperResult out
= helper
.output();
5993 EXPECT_EQ(OK
, out
.rv
);
5994 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
5995 EXPECT_EQ("hello!", out
.response_data
);
5998 TEST_P(SpdyNetworkTransactionSpdy3Test
, SynReplyWithLateHeaders
) {
5999 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
6000 MockWrite writes
[] = { CreateMockWrite(*req
) };
6002 static const char* const kInitialHeaders
[] = {
6008 static const char* const kLateHeaders
[] = {
6012 scoped_ptr
<SpdyFrame
>
6013 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
6014 arraysize(kInitialHeaders
) / 2,
6023 scoped_ptr
<SpdyFrame
>
6024 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
6025 arraysize(kLateHeaders
) / 2,
6034 scoped_ptr
<SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, false));
6035 scoped_ptr
<SpdyFrame
> stream1_body2(ConstructSpdyBodyFrame(1, true));
6036 MockRead reads
[] = {
6037 CreateMockRead(*stream1_reply
),
6038 CreateMockRead(*stream1_body
),
6039 CreateMockRead(*stream1_headers
),
6040 CreateMockRead(*stream1_body2
),
6041 MockRead(ASYNC
, 0, 0) // EOF
6044 DelayedSocketData
data(1, reads
, arraysize(reads
),
6045 writes
, arraysize(writes
));
6046 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
6047 BoundNetLog(), GetParam(), NULL
);
6048 helper
.RunToCompletion(&data
);
6049 TransactionHelperResult out
= helper
.output();
6050 EXPECT_EQ(OK
, out
.rv
);
6051 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
6052 EXPECT_EQ("hello!hello!", out
.response_data
);
6055 TEST_P(SpdyNetworkTransactionSpdy3Test
, SynReplyWithDuplicateLateHeaders
) {
6056 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
6057 MockWrite writes
[] = { CreateMockWrite(*req
) };
6059 static const char* const kInitialHeaders
[] = {
6065 static const char* const kLateHeaders
[] = {
6069 scoped_ptr
<SpdyFrame
>
6070 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders
,
6071 arraysize(kInitialHeaders
) / 2,
6080 scoped_ptr
<SpdyFrame
>
6081 stream1_headers(ConstructSpdyControlFrame(kLateHeaders
,
6082 arraysize(kLateHeaders
) / 2,
6091 scoped_ptr
<SpdyFrame
> stream1_body(ConstructSpdyBodyFrame(1, false));
6092 scoped_ptr
<SpdyFrame
> stream1_body2(ConstructSpdyBodyFrame(1, true));
6093 MockRead reads
[] = {
6094 CreateMockRead(*stream1_reply
),
6095 CreateMockRead(*stream1_body
),
6096 CreateMockRead(*stream1_headers
),
6097 CreateMockRead(*stream1_body2
),
6098 MockRead(ASYNC
, 0, 0) // EOF
6101 DelayedSocketData
data(1, reads
, arraysize(reads
),
6102 writes
, arraysize(writes
));
6103 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
6104 BoundNetLog(), GetParam(), NULL
);
6105 helper
.RunToCompletion(&data
);
6106 TransactionHelperResult out
= helper
.output();
6107 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR
, out
.rv
);
6110 TEST_P(SpdyNetworkTransactionSpdy3Test
, ServerPushCrossOriginCorrectness
) {
6111 // In this test we want to verify that we can't accidentally push content
6112 // which can't be pushed by this content server.
6113 // This test assumes that:
6114 // - if we're requesting http://www.foo.com/barbaz
6115 // - the browser has made a connection to "www.foo.com".
6117 // A list of the URL to fetch, followed by the URL being pushed.
6118 static const char* const kTestCases
[] = {
6119 "http://www.google.com/foo.html",
6120 "http://www.google.com:81/foo.js", // Bad port
6122 "http://www.google.com/foo.html",
6123 "https://www.google.com/foo.js", // Bad protocol
6125 "http://www.google.com/foo.html",
6126 "ftp://www.google.com/foo.js", // Invalid Protocol
6128 "http://www.google.com/foo.html",
6129 "http://blat.www.google.com/foo.js", // Cross subdomain
6131 "http://www.google.com/foo.html",
6132 "http://www.foo.com/foo.js", // Cross domain
6136 static const unsigned char kPushBodyFrame
[] = {
6137 0x00, 0x00, 0x00, 0x02, // header, ID
6138 0x01, 0x00, 0x00, 0x06, // FIN, length
6139 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
6142 for (size_t index
= 0; index
< arraysize(kTestCases
); index
+= 2) {
6143 const char* url_to_fetch
= kTestCases
[index
];
6144 const char* url_to_push
= kTestCases
[index
+ 1];
6146 scoped_ptr
<SpdyFrame
>
6147 stream1_syn(ConstructSpdyGet(url_to_fetch
, false, 1, LOWEST
));
6148 scoped_ptr
<SpdyFrame
>
6149 stream1_body(ConstructSpdyBodyFrame(1, true));
6150 scoped_ptr
<SpdyFrame
> push_rst(
6151 ConstructSpdyRstStream(2, REFUSED_STREAM
));
6152 MockWrite writes
[] = {
6153 CreateMockWrite(*stream1_syn
, 1),
6154 CreateMockWrite(*push_rst
, 4),
6157 scoped_ptr
<SpdyFrame
>
6158 stream1_reply(ConstructSpdyGetSynReply(NULL
, 0, 1));
6159 scoped_ptr
<SpdyFrame
>
6160 stream2_syn(ConstructSpdyPush(NULL
,
6165 scoped_ptr
<SpdyFrame
> rst(
6166 ConstructSpdyRstStream(2, CANCEL
));
6168 MockRead reads
[] = {
6169 CreateMockRead(*stream1_reply
, 2),
6170 CreateMockRead(*stream2_syn
, 3),
6171 CreateMockRead(*stream1_body
, 5, SYNCHRONOUS
),
6172 MockRead(ASYNC
, reinterpret_cast<const char*>(kPushBodyFrame
),
6173 arraysize(kPushBodyFrame
), 6),
6174 MockRead(ASYNC
, ERR_IO_PENDING
, 7), // Force a pause
6177 HttpResponseInfo response
;
6178 OrderedSocketData
data(reads
, arraysize(reads
),
6179 writes
, arraysize(writes
));
6181 HttpRequestInfo request
;
6182 request
.method
= "GET";
6183 request
.url
= GURL(url_to_fetch
);
6184 request
.load_flags
= 0;
6186 // Enable cross-origin push. Since we are not using a proxy, this should
6187 // not actually enable cross-origin SPDY push.
6188 scoped_ptr
<SpdySessionDependencies
> session_deps(
6189 new SpdySessionDependencies());
6190 session_deps
->trusted_spdy_proxy
= "123.45.67.89:8080";
6191 NormalSpdyTransactionHelper
helper(request
,
6192 BoundNetLog(), GetParam(),
6193 session_deps
.release());
6194 helper
.RunPreTestSetup();
6195 helper
.AddData(&data
);
6197 HttpNetworkTransaction
* trans
= helper
.trans();
6199 // Start the transaction with basic parameters.
6200 TestCompletionCallback callback
;
6202 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6204 rv
= callback
.WaitForResult();
6206 // Read the response body.
6208 ReadResult(trans
, &data
, &result
);
6210 // Verify that we consumed all test data.
6211 EXPECT_TRUE(data
.at_read_eof());
6212 EXPECT_TRUE(data
.at_write_eof());
6214 // Verify the SYN_REPLY.
6215 // Copy the response info, because trans goes away.
6216 response
= *trans
->GetResponseInfo();
6218 VerifyStreamsClosed(helper
);
6220 // Verify the SYN_REPLY.
6221 EXPECT_TRUE(response
.headers
!= NULL
);
6222 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
6226 TEST_P(SpdyNetworkTransactionSpdy3Test
, RetryAfterRefused
) {
6227 // Construct the request.
6228 scoped_ptr
<SpdyFrame
> req(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
6229 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
6230 MockWrite writes
[] = {
6231 CreateMockWrite(*req
, 1),
6232 CreateMockWrite(*req2
, 3),
6235 scoped_ptr
<SpdyFrame
> refused(
6236 ConstructSpdyRstStream(1, REFUSED_STREAM
));
6237 scoped_ptr
<SpdyFrame
> resp(ConstructSpdyGetSynReply(NULL
, 0, 3));
6238 scoped_ptr
<SpdyFrame
> body(ConstructSpdyBodyFrame(3, true));
6239 MockRead reads
[] = {
6240 CreateMockRead(*refused
, 2),
6241 CreateMockRead(*resp
, 4),
6242 CreateMockRead(*body
, 5),
6243 MockRead(ASYNC
, 0, 6) // EOF
6246 OrderedSocketData
data(reads
, arraysize(reads
),
6247 writes
, arraysize(writes
));
6248 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
6249 BoundNetLog(), GetParam(), NULL
);
6251 helper
.RunPreTestSetup();
6252 helper
.AddData(&data
);
6254 HttpNetworkTransaction
* trans
= helper
.trans();
6256 // Start the transaction with basic parameters.
6257 TestCompletionCallback callback
;
6258 int rv
= trans
->Start(
6259 &CreateGetRequest(), callback
.callback(), BoundNetLog());
6260 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6261 rv
= callback
.WaitForResult();
6264 // Verify that we consumed all test data.
6265 EXPECT_TRUE(data
.at_read_eof()) << "Read count: "
6266 << data
.read_count()
6268 << data
.read_index();
6269 EXPECT_TRUE(data
.at_write_eof()) << "Write count: "
6270 << data
.write_count()
6272 << data
.write_index();
6274 // Verify the SYN_REPLY.
6275 HttpResponseInfo response
= *trans
->GetResponseInfo();
6276 EXPECT_TRUE(response
.headers
!= NULL
);
6277 EXPECT_EQ("HTTP/1.1 200 OK", response
.headers
->GetStatusLine());
6280 TEST_P(SpdyNetworkTransactionSpdy3Test
, OutOfOrderSynStream
) {
6281 // This first request will start to establish the SpdySession.
6282 // Then we will start the second (MEDIUM priority) and then third
6283 // (HIGHEST priority) request in such a way that the third will actually
6284 // start before the second, causing the second to be numbered differently
6285 // than they order they were created.
6286 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
6287 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, HIGHEST
));
6288 scoped_ptr
<SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, MEDIUM
));
6289 MockWrite writes
[] = {
6290 CreateMockWrite(*req1
, 0),
6291 CreateMockWrite(*req2
, 3),
6292 CreateMockWrite(*req3
, 4),
6295 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
6296 scoped_ptr
<SpdyFrame
> body1(ConstructSpdyBodyFrame(1, true));
6297 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
6298 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, true));
6299 scoped_ptr
<SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
6300 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(5, true));
6301 MockRead reads
[] = {
6302 CreateMockRead(*resp1
, 1),
6303 CreateMockRead(*body1
, 2),
6304 CreateMockRead(*resp2
, 5),
6305 CreateMockRead(*body2
, 6),
6306 CreateMockRead(*resp3
, 7),
6307 CreateMockRead(*body3
, 8),
6308 MockRead(ASYNC
, 0, 9) // EOF
6311 DeterministicSocketData
data(reads
, arraysize(reads
),
6312 writes
, arraysize(writes
));
6313 NormalSpdyTransactionHelper
helper(CreateGetRequest(),
6314 BoundNetLog(), GetParam(), NULL
);
6315 helper
.SetDeterministic();
6316 helper
.RunPreTestSetup();
6317 helper
.AddDeterministicData(&data
);
6319 // Start the first transaction to set up the SpdySession
6320 HttpNetworkTransaction
* trans
= helper
.trans();
6321 TestCompletionCallback callback
;
6322 HttpRequestInfo info1
= CreateGetRequest();
6323 info1
.priority
= LOWEST
;
6324 int rv
= trans
->Start(&info1
, callback
.callback(), BoundNetLog());
6325 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6327 // Run the message loop, but do not allow the write to complete.
6328 // This leaves the SpdySession with a write pending, which prevents
6329 // SpdySession from attempting subsequent writes until this write completes.
6330 MessageLoop::current()->RunUntilIdle();
6332 // Now, start both new transactions
6333 HttpRequestInfo info2
= CreateGetRequest();
6334 info2
.priority
= MEDIUM
;
6335 TestCompletionCallback callback2
;
6336 scoped_ptr
<HttpNetworkTransaction
> trans2(
6337 new HttpNetworkTransaction(helper
.session()));
6338 rv
= trans2
->Start(&info2
, callback2
.callback(), BoundNetLog());
6339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6340 MessageLoop::current()->RunUntilIdle();
6342 HttpRequestInfo info3
= CreateGetRequest();
6343 info3
.priority
= HIGHEST
;
6344 TestCompletionCallback callback3
;
6345 scoped_ptr
<HttpNetworkTransaction
> trans3(
6346 new HttpNetworkTransaction(helper
.session()));
6347 rv
= trans3
->Start(&info3
, callback3
.callback(), BoundNetLog());
6348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6349 MessageLoop::current()->RunUntilIdle();
6351 // We now have two SYN_STREAM frames queued up which will be
6352 // dequeued only once the first write completes, which we
6353 // now allow to happen.
6355 EXPECT_EQ(OK
, callback
.WaitForResult());
6357 // And now we can allow everything else to run to completion.
6360 EXPECT_EQ(OK
, callback2
.WaitForResult());
6361 EXPECT_EQ(OK
, callback3
.WaitForResult());
6363 helper
.VerifyDataConsumed();